1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011-2014, 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 fTeamWindow->Show(); 182 } 183 184 185 void 186 GraphicalUserInterface::Terminate() 187 { 188 // quit window 189 if (fTeamWindowMessenger && fTeamWindowMessenger->LockTarget()) 190 fTeamWindow->Quit(); 191 } 192 193 194 bool 195 GraphicalUserInterface::IsInteractive() const 196 { 197 return true; 198 } 199 200 201 status_t 202 GraphicalUserInterface::LoadSettings(const TeamUiSettings* settings) 203 { 204 status_t result = fTeamWindow->LoadSettings((GuiTeamUiSettings*)settings); 205 206 return result; 207 } 208 209 210 status_t 211 GraphicalUserInterface::SaveSettings(TeamUiSettings*& settings) const 212 { 213 settings = new(std::nothrow) GuiTeamUiSettings(ID()); 214 if (settings == NULL) 215 return B_NO_MEMORY; 216 217 fTeamWindow->SaveSettings((GuiTeamUiSettings*)settings); 218 219 return B_OK; 220 } 221 222 223 void 224 GraphicalUserInterface::NotifyUser(const char* title, const char* message, 225 user_notification_type type) 226 { 227 // convert notification type to alert type 228 alert_type alertType; 229 switch (type) { 230 case USER_NOTIFICATION_INFO: 231 alertType = B_INFO_ALERT; 232 break; 233 case USER_NOTIFICATION_WARNING: 234 case USER_NOTIFICATION_ERROR: 235 default: 236 alertType = B_WARNING_ALERT; 237 break; 238 } 239 240 BAlert* alert = new(std::nothrow) BAlert(title, message, "OK", 241 NULL, NULL, B_WIDTH_AS_USUAL, alertType); 242 if (alert != NULL) 243 alert->Go(NULL); 244 245 // TODO: We need to let the alert run asynchronously, but we shouldn't just 246 // create it and don't care anymore. Maybe an error window, which can 247 // display a list of errors would be the better choice. 248 } 249 250 251 int32 252 GraphicalUserInterface::SynchronouslyAskUser(const char* title, 253 const char* message, const char* choice1, const char* choice2, 254 const char* choice3) 255 { 256 BAlert* alert = new(std::nothrow) BAlert(title, message, 257 choice1, choice2, choice3); 258 if (alert == NULL) 259 return 0; 260 return alert->Go(); 261 } 262 263 264 status_t 265 GraphicalUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref) 266 { 267 BAutolock lock(&fFilePanelHandler->Locker()); 268 269 if (fFilePanel == NULL) { 270 BMessenger messenger(fFilePanelHandler); 271 BMessage* message = new(std::nothrow) BMessage( 272 MSG_USER_INTERFACE_FILE_CHOSEN); 273 if (message == NULL) 274 return B_NO_MEMORY; 275 ObjectDeleter<BMessage> messageDeleter(message); 276 fFilePanel = new(std::nothrow) BFilePanel(B_OPEN_PANEL, 277 &messenger, NULL, B_FILE_NODE, false, message); 278 if (fFilePanel == NULL) 279 return B_NO_MEMORY; 280 messageDeleter.Detach(); 281 } 282 283 fFilePanelHandler->SetCurrentRef(_ref); 284 fFilePanel->Show(); 285 return fFilePanelHandler->WaitForPanel(); 286 } 287