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