1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011-2016, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "GraphicalUserInterface.h" 9 10 #include <Alert.h> 11 #include <AutoDeleter.h> 12 #include <Autolock.h> 13 #include <FilePanel.h> 14 #include <Locker.h> 15 16 #include "GuiTeamUiSettings.h" 17 #include "MessageCodes.h" 18 #include "TeamWindow.h" 19 #include "Tracing.h" 20 21 22 // #pragma mark - GraphicalUserInterface::FilePanelHandler 23 24 25 class GraphicalUserInterface::FilePanelHandler : public BHandler { 26 public: 27 FilePanelHandler(); 28 virtual ~FilePanelHandler(); 29 30 status_t Init(); 31 32 virtual void MessageReceived(BMessage* message); 33 34 status_t WaitForPanel(); 35 36 void SetCurrentRef(entry_ref* ref); 37 38 BLocker& Locker() 39 { return fPanelLock; } 40 41 private: 42 entry_ref* fCurrentRef; 43 BLocker fPanelLock; 44 sem_id fPanelWaitSem; 45 }; 46 47 48 GraphicalUserInterface::FilePanelHandler::FilePanelHandler() 49 : 50 BHandler("GuiPanelHandler"), 51 fCurrentRef(NULL), 52 fPanelLock(), 53 fPanelWaitSem(-1) 54 { 55 } 56 57 58 GraphicalUserInterface::FilePanelHandler::~FilePanelHandler() 59 { 60 if (fPanelWaitSem >= 0) 61 delete_sem(fPanelWaitSem); 62 } 63 64 65 status_t 66 GraphicalUserInterface::FilePanelHandler::Init() 67 { 68 fPanelWaitSem = create_sem(0, "FilePanelWaitSem"); 69 70 if (fPanelWaitSem < 0) 71 return fPanelWaitSem; 72 73 return B_OK; 74 } 75 76 77 void 78 GraphicalUserInterface::FilePanelHandler::MessageReceived(BMessage* message) 79 { 80 switch (message->what) { 81 case MSG_USER_INTERFACE_FILE_CHOSEN: 82 { 83 entry_ref ref; 84 if (message->FindRef("refs", &ref) == B_OK 85 && fCurrentRef != NULL) { 86 *fCurrentRef = ref; 87 fCurrentRef = NULL; 88 } 89 // fall through 90 } 91 92 case B_CANCEL: 93 { 94 release_sem(fPanelWaitSem); 95 break; 96 } 97 98 default: 99 BHandler::MessageReceived(message); 100 break; 101 } 102 } 103 104 105 status_t 106 GraphicalUserInterface::FilePanelHandler::WaitForPanel() 107 { 108 status_t result = B_OK; 109 do { 110 result = acquire_sem(fPanelWaitSem); 111 } while (result == B_INTERRUPTED); 112 113 return result; 114 } 115 116 117 void 118 GraphicalUserInterface::FilePanelHandler::SetCurrentRef(entry_ref* ref) 119 { 120 fCurrentRef = ref; 121 } 122 123 124 // #pragma mark - GraphicalUserInterface 125 126 127 GraphicalUserInterface::GraphicalUserInterface() 128 : 129 fTeamWindow(NULL), 130 fTeamWindowMessenger(NULL), 131 fFilePanelHandler(NULL), 132 fFilePanel(NULL) 133 { 134 } 135 136 137 GraphicalUserInterface::~GraphicalUserInterface() 138 { 139 delete fTeamWindowMessenger; 140 delete fFilePanel; 141 } 142 143 144 const char* 145 GraphicalUserInterface::ID() const 146 { 147 return "GraphicalUserInterface"; 148 } 149 150 151 status_t 152 GraphicalUserInterface::Init(Team* team, UserInterfaceListener* listener) 153 { 154 try { 155 fTeamWindow = TeamWindow::Create(team, listener); 156 fTeamWindowMessenger = new BMessenger(fTeamWindow); 157 fFilePanelHandler = new FilePanelHandler(); 158 status_t error = fFilePanelHandler->Init(); 159 if (error != B_OK) { 160 ERROR("Error: Failed to create file panel semaphore!\n"); 161 return error; 162 } 163 fTeamWindow->AddHandler(fFilePanelHandler); 164 165 // start the message loop 166 fTeamWindow->Hide(); 167 fTeamWindow->Show(); 168 } catch (...) { 169 // TODO: Notify the user! 170 ERROR("Error: Failed to create team window!\n"); 171 return B_NO_MEMORY; 172 } 173 174 return B_OK; 175 } 176 177 178 void 179 GraphicalUserInterface::Show() 180 { 181 if (fTeamWindow->IsHidden()) 182 fTeamWindow->Show(); 183 else 184 fTeamWindow->Activate(); 185 } 186 187 188 void 189 GraphicalUserInterface::Terminate() 190 { 191 // quit window 192 if (fTeamWindowMessenger && fTeamWindowMessenger->LockTarget()) 193 fTeamWindow->Quit(); 194 } 195 196 197 UserInterface* 198 GraphicalUserInterface::Clone() const 199 { 200 return new(std::nothrow) GraphicalUserInterface; 201 } 202 203 204 bool 205 GraphicalUserInterface::IsInteractive() const 206 { 207 return true; 208 } 209 210 211 status_t 212 GraphicalUserInterface::LoadSettings(const TeamUiSettings* settings) 213 { 214 status_t result = fTeamWindow->LoadSettings((GuiTeamUiSettings*)settings); 215 216 return result; 217 } 218 219 220 status_t 221 GraphicalUserInterface::SaveSettings(TeamUiSettings*& settings) const 222 { 223 settings = new(std::nothrow) GuiTeamUiSettings(ID()); 224 if (settings == NULL) 225 return B_NO_MEMORY; 226 227 fTeamWindow->SaveSettings((GuiTeamUiSettings*)settings); 228 229 return B_OK; 230 } 231 232 233 void 234 GraphicalUserInterface::NotifyUser(const char* title, const char* message, 235 user_notification_type type) 236 { 237 // convert notification type to alert type 238 alert_type alertType; 239 switch (type) { 240 case USER_NOTIFICATION_INFO: 241 alertType = B_INFO_ALERT; 242 break; 243 case USER_NOTIFICATION_WARNING: 244 case USER_NOTIFICATION_ERROR: 245 default: 246 alertType = B_WARNING_ALERT; 247 break; 248 } 249 250 BAlert* alert = new(std::nothrow) BAlert(title, message, "OK", 251 NULL, NULL, B_WIDTH_AS_USUAL, alertType); 252 if (alert != NULL) 253 alert->Go(NULL); 254 255 // TODO: We need to let the alert run asynchronously, but we shouldn't just 256 // create it and don't care anymore. Maybe an error window, which can 257 // display a list of errors would be the better choice. 258 } 259 260 261 void 262 GraphicalUserInterface::NotifyBackgroundWorkStatus(const char* message) 263 { 264 fTeamWindow->DisplayBackgroundStatus(message); 265 } 266 267 268 int32 269 GraphicalUserInterface::SynchronouslyAskUser(const char* title, 270 const char* message, const char* choice1, const char* choice2, 271 const char* choice3) 272 { 273 BAlert* alert = new(std::nothrow) BAlert(title, message, 274 choice1, choice2, choice3); 275 if (alert == NULL) 276 return 0; 277 return alert->Go(); 278 } 279 280 281 status_t 282 GraphicalUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref) 283 { 284 BAutolock lock(&fFilePanelHandler->Locker()); 285 286 if (fFilePanel == NULL) { 287 BMessenger messenger(fFilePanelHandler); 288 BMessage* message = new(std::nothrow) BMessage( 289 MSG_USER_INTERFACE_FILE_CHOSEN); 290 if (message == NULL) 291 return B_NO_MEMORY; 292 ObjectDeleter<BMessage> messageDeleter(message); 293 fFilePanel = new(std::nothrow) BFilePanel(B_OPEN_PANEL, 294 &messenger, NULL, B_FILE_NODE, false, message); 295 if (fFilePanel == NULL) 296 return B_NO_MEMORY; 297 messageDeleter.Detach(); 298 } 299 300 fFilePanelHandler->SetCurrentRef(_ref); 301 fFilePanel->Show(); 302 return fFilePanelHandler->WaitForPanel(); 303 } 304