1 /*
2 * Copyright 2016-2017, Rene Gollent, rene@gollent.com.
3 * Distributed under the terms of the MIT License.
4 */
5 #include "ConnectionConfigWindow.h"
6
7 #include <Application.h>
8 #include <Button.h>
9 #include <GroupView.h>
10 #include <MenuField.h>
11 #include <LayoutBuilder.h>
12
13 #include <AutoDeleter.h>
14 #include <AutoLocker.h>
15
16 #include "AppMessageCodes.h"
17 #include "ConnectionConfigHandlerRoster.h"
18 #include "Settings.h"
19 #include "TargetHostInterfaceInfo.h"
20 #include "TargetHostInterfaceRoster.h"
21 #include "TargetHostInterface.h"
22
23
24 enum {
25 MSG_SWITCH_CONNECTION_TYPE = 'swct',
26 MSG_CREATE_CONNECTION = 'crco'
27 };
28
29
ConnectionConfigWindow()30 ConnectionConfigWindow::ConnectionConfigWindow()
31 :
32 BWindow(BRect(), "Create new connection", B_TITLED_WINDOW,
33 B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
34 ConnectionConfigView::Listener(),
35 fConnectionTypeField(NULL),
36 fConfigGroupView(NULL),
37 fCloseButton(NULL),
38 fConnectButton(NULL),
39 fCurrentSettings(NULL),
40 fActiveInfo(NULL)
41 {
42 }
43
44
~ConnectionConfigWindow()45 ConnectionConfigWindow::~ConnectionConfigWindow()
46 {
47 if (fCurrentSettings != NULL)
48 fCurrentSettings->ReleaseReference();
49 }
50
51
52 ConnectionConfigWindow*
Create()53 ConnectionConfigWindow::Create()
54 {
55 ConnectionConfigWindow* self = new ConnectionConfigWindow();
56
57 try {
58 self->_Init();
59 } catch (...) {
60 delete self;
61 throw;
62 }
63
64 return self;
65
66 }
67
68
69 void
Show()70 ConnectionConfigWindow::Show()
71 {
72 CenterOnScreen();
73 BWindow::Show();
74 }
75
76
77 bool
QuitRequested()78 ConnectionConfigWindow::QuitRequested()
79 {
80 return be_app_messenger.SendMessage(MSG_CONNECTION_CONFIG_WINDOW_CLOSED)
81 == B_OK;
82 }
83
84
85 void
ConfigurationChanged(Settings * settings)86 ConnectionConfigWindow::ConfigurationChanged(Settings* settings)
87 {
88 if (fCurrentSettings != NULL)
89 fCurrentSettings->ReleaseReference();
90 fCurrentSettings = settings;
91 fCurrentSettings->AcquireReference();
92
93 fConnectButton->SetEnabled(fActiveInfo->IsConfigured(settings));
94 }
95
96
97 void
MessageReceived(BMessage * message)98 ConnectionConfigWindow::MessageReceived(BMessage* message)
99 {
100 switch (message->what) {
101 case MSG_CREATE_CONNECTION:
102 {
103 TargetHostInterfaceRoster* roster
104 = TargetHostInterfaceRoster::Default();
105 AutoLocker<TargetHostInterfaceRoster> rosterLocker(roster);
106
107 TargetHostInterface* interface;
108 status_t error = roster->CreateInterface(fActiveInfo,
109 fCurrentSettings, interface);
110
111 // TODO: notify user.
112 if (error != B_OK)
113 break;
114
115 PostMessage(B_QUIT_REQUESTED);
116 break;
117 }
118 default:
119 BWindow::MessageReceived(message);
120 break;
121 }
122 }
123
124
125 void
_Init()126 ConnectionConfigWindow::_Init()
127 {
128 BMenu* menu = _BuildTypeMenu();
129
130 fConfigGroupView = new BGroupView(B_HORIZONTAL);
131
132 BLayoutBuilder::Group<>(this, B_VERTICAL)
133 .SetInsets(B_USE_DEFAULT_SPACING)
134 .Add(fConnectionTypeField = new BMenuField("Type:", menu))
135 .AddGroup(fConfigGroupView)
136 // this group is a placeholder to contain
137 // the actual config view
138 .End()
139 .AddGroup(B_HORIZONTAL)
140 .SetInsets(B_USE_SMALL_SPACING)
141 .AddGlue()
142 .Add(fCloseButton = new BButton("Close",
143 new BMessage(B_QUIT_REQUESTED)))
144 .Add(fConnectButton = new BButton("Connect",
145 new BMessage(MSG_CREATE_CONNECTION)))
146 .End();
147
148 fConnectionTypeField->Menu()->SetLabelFromMarked(true);
149 fConnectionTypeField->Menu()->SetTargetForItems(this);
150
151 fCloseButton->SetTarget(this);
152 fConnectButton->SetTarget(this);
153 fConnectButton->SetEnabled(false);
154
155 if (menu->CountItems() > 0) {
156 BMenuItem* item = menu->ItemAt(0);
157 BMessage* message = item->Message();
158 TargetHostInterfaceInfo* info = NULL;
159 if (message->FindPointer("info", reinterpret_cast<void**>(&info))
160 == B_OK) {
161 _UpdateActiveConfig(info);
162 menu->ItemAt(0)->SetMarked(true);
163 }
164 }
165 }
166
167
168 BMenu*
_BuildTypeMenu()169 ConnectionConfigWindow::_BuildTypeMenu()
170 {
171 BMenu* menu = new BMenu("Types");
172 TargetHostInterfaceRoster* roster = TargetHostInterfaceRoster::Default();
173
174 AutoLocker<TargetHostInterfaceRoster> rosterLocker(roster);
175
176 for (int32 i = 0; i < roster->CountInterfaceInfos(); i++) {
177 TargetHostInterfaceInfo* info = roster->InterfaceInfoAt(i);
178 if (info->IsLocal())
179 continue;
180
181 BMenuItem* item = new BMenuItem(info->Name(), new BMessage(
182 MSG_SWITCH_CONNECTION_TYPE));
183 item->Message()->AddPointer("info", info);
184 menu->AddItem(item);
185 }
186
187 return menu;
188 }
189
190
191 void
_UpdateActiveConfig(TargetHostInterfaceInfo * info)192 ConnectionConfigWindow::_UpdateActiveConfig(TargetHostInterfaceInfo* info)
193 {
194 if (fConfigGroupView->CountChildren() > 0) {
195 BView* view = fConfigGroupView->ChildAt(0);
196 fConfigGroupView->RemoveChild(view);
197 delete view;
198 }
199
200 ConnectionConfigHandlerRoster* roster
201 = ConnectionConfigHandlerRoster::Default();
202
203 if (roster->HasHandlerFor(info)) {
204 ConnectionConfigView* view = NULL;
205 status_t error = roster->CreateConfigView(info, this, view);
206 if (error != B_OK)
207 return;
208
209 ObjectDeleter<ConnectionConfigView> viewDeleter(view);
210 BLayoutItem* item = fConfigGroupView->GroupLayout()->AddView(view);
211 if (item != NULL)
212 viewDeleter.Detach();
213
214 fActiveInfo = info;
215 }
216
217 fConfigGroupView->InvalidateLayout();
218 }
219