xref: /haiku/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp (revision faf79e7f783976326856422ff006b4c6ae9c3031)
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