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