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 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 45 ConnectionConfigWindow::~ConnectionConfigWindow() 46 { 47 if (fCurrentSettings != NULL) 48 fCurrentSettings->ReleaseReference(); 49 } 50 51 52 ConnectionConfigWindow* 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 70 ConnectionConfigWindow::Show() 71 { 72 CenterOnScreen(); 73 BWindow::Show(); 74 } 75 76 77 bool 78 ConnectionConfigWindow::QuitRequested() 79 { 80 return be_app_messenger.SendMessage(MSG_CONNECTION_CONFIG_WINDOW_CLOSED) 81 == B_OK; 82 } 83 84 85 void 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 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 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* 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 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