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 delete fFilePanelHandler; 142 } 143 144 145 const char* 146 GraphicalUserInterface::ID() const 147 { 148 return "GraphicalUserInterface"; 149 } 150 151 152 status_t 153 GraphicalUserInterface::Init(Team* team, UserInterfaceListener* listener) 154 { 155 try { 156 fTeamWindow = TeamWindow::Create(team, listener); 157 fTeamWindowMessenger = new BMessenger(fTeamWindow); 158 fFilePanelHandler = new FilePanelHandler(); 159 status_t error = fFilePanelHandler->Init(); 160 if (error != B_OK) { 161 ERROR("Error: Failed to create file panel semaphore!\n"); 162 return error; 163 } 164 fTeamWindow->AddHandler(fFilePanelHandler); 165 166 // start the message loop 167 fTeamWindow->Hide(); 168 fTeamWindow->Show(); 169 } catch (...) { 170 // TODO: Notify the user! 171 ERROR("Error: Failed to create team window!\n"); 172 return B_NO_MEMORY; 173 } 174 175 return B_OK; 176 } 177 178 179 void 180 GraphicalUserInterface::Show() 181 { 182 if (fTeamWindow->IsHidden()) 183 fTeamWindow->Show(); 184 else 185 fTeamWindow->Activate(); 186 } 187 188 189 void 190 GraphicalUserInterface::Terminate() 191 { 192 // quit window 193 if (fTeamWindowMessenger && fTeamWindowMessenger->LockTarget()) 194 fTeamWindow->Quit(); 195 } 196 197 198 UserInterface* 199 GraphicalUserInterface::Clone() const 200 { 201 return new(std::nothrow) GraphicalUserInterface; 202 } 203 204 205 bool 206 GraphicalUserInterface::IsInteractive() const 207 { 208 return true; 209 } 210 211 212 status_t 213 GraphicalUserInterface::LoadSettings(const TeamUiSettings* settings) 214 { 215 status_t result = fTeamWindow->LoadSettings((GuiTeamUiSettings*)settings); 216 217 return result; 218 } 219 220 221 status_t 222 GraphicalUserInterface::SaveSettings(TeamUiSettings*& settings) const 223 { 224 settings = new(std::nothrow) GuiTeamUiSettings(ID()); 225 if (settings == NULL) 226 return B_NO_MEMORY; 227 228 fTeamWindow->SaveSettings((GuiTeamUiSettings*)settings); 229 230 return B_OK; 231 } 232 233 234 void 235 GraphicalUserInterface::NotifyUser(const char* title, const char* message, 236 user_notification_type type) 237 { 238 // convert notification type to alert type 239 alert_type alertType; 240 switch (type) { 241 case USER_NOTIFICATION_INFO: 242 alertType = B_INFO_ALERT; 243 break; 244 case USER_NOTIFICATION_WARNING: 245 case USER_NOTIFICATION_ERROR: 246 default: 247 alertType = B_WARNING_ALERT; 248 break; 249 } 250 251 BAlert* alert = new(std::nothrow) BAlert(title, message, "OK", 252 NULL, NULL, B_WIDTH_AS_USUAL, alertType); 253 if (alert != NULL) 254 alert->Go(NULL); 255 256 // TODO: We need to let the alert run asynchronously, but we shouldn't just 257 // create it and don't care anymore. Maybe an error window, which can 258 // display a list of errors would be the better choice. 259 } 260 261 262 void 263 GraphicalUserInterface::NotifyBackgroundWorkStatus(const char* message) 264 { 265 fTeamWindow->DisplayBackgroundStatus(message); 266 } 267 268 269 int32 270 GraphicalUserInterface::SynchronouslyAskUser(const char* title, 271 const char* message, const char* choice1, const char* choice2, 272 const char* choice3) 273 { 274 BAlert* alert = new(std::nothrow) BAlert(title, message, 275 choice1, choice2, choice3); 276 if (alert == NULL) 277 return 0; 278 return alert->Go(); 279 } 280 281 282 status_t 283 GraphicalUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref) 284 { 285 BAutolock lock(&fFilePanelHandler->Locker()); 286 287 if (fFilePanel == NULL) { 288 BMessenger messenger(fFilePanelHandler); 289 BMessage* message = new(std::nothrow) BMessage( 290 MSG_USER_INTERFACE_FILE_CHOSEN); 291 if (message == NULL) 292 return B_NO_MEMORY; 293 ObjectDeleter<BMessage> messageDeleter(message); 294 fFilePanel = new(std::nothrow) BFilePanel(B_OPEN_PANEL, 295 &messenger, NULL, B_FILE_NODE, false, message); 296 if (fFilePanel == NULL) 297 return B_NO_MEMORY; 298 messageDeleter.Detach(); 299 } 300 301 fFilePanelHandler->SetCurrentRef(_ref); 302 fFilePanel->Show(); 303 return fFilePanelHandler->WaitForPanel(); 304 } 305