1/*
2
3InterfaceUtils.cpp
4
5Copyright (c) 2002 Haiku.
6
7Author:
8	Michael Pfeiffer
9
10Permission is hereby granted, free of charge, to any person obtaining a copy of
11this software and associated documentation files (the "Software"), to deal in
12the Software without restriction, including without limitation the rights to
13use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14of the Software, and to permit persons to whom the Software is furnished to do
15so, subject to the following conditions:
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26THE SOFTWARE.
27
28*/
29
30#include "BlockingWindow.h"
31
32
33#include <Alert.h>
34#include <Debug.h>
35#include <Message.h>
36#include <TextView.h>
37
38
39#include <string.h>
40
41
42// #pragma mark -- EscapeMessageFilter
43
44
45EscapeMessageFilter::EscapeMessageFilter(BWindow *window, int32 what)
46	: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, '_KYD')
47	, fWindow(window),
48	fWhat(what)
49{
50}
51
52
53filter_result
54EscapeMessageFilter::Filter(BMessage *msg, BHandler **target)
55{
56	int32 key;
57	filter_result result = B_DISPATCH_MESSAGE;
58	if (msg->FindInt32("key", &key) == B_OK && key == 1) {
59		fWindow->PostMessage(fWhat);
60		result = B_SKIP_MESSAGE;
61	}
62	return result;
63}
64
65
66// #pragma mark -- HWindow
67
68
69HWindow::HWindow(BRect frame, const char *title, window_type type, uint32 flags,
70		uint32 workspace, uint32 escape_msg)
71	: BWindow(frame, title, type, flags, workspace)
72{
73	Init(escape_msg);
74}
75
76
77HWindow::HWindow(BRect frame, const char *title, window_look look, window_feel feel,
78		uint32 flags, uint32 workspace, uint32 escape_msg)
79	: BWindow(frame, title, look, feel, flags, workspace)
80{
81	Init(escape_msg);
82}
83
84
85void
86HWindow::Init(uint32 escape_msg)
87{
88	AddShortcut('i', 0, new BMessage(B_ABOUT_REQUESTED));
89	AddCommonFilter(new EscapeMessageFilter(this, escape_msg));
90}
91
92
93void
94HWindow::MessageReceived(BMessage* msg)
95{
96	if (msg->what == B_ABOUT_REQUESTED) {
97		AboutRequested();
98	} else {
99		inherited::MessageReceived(msg);
100	}
101}
102
103
104void
105HWindow::AboutRequested()
106{
107	const char* aboutText = AboutText();
108	if (aboutText == NULL)
109		return;
110
111	BAlert *about = new BAlert("About", aboutText, "Cool");
112	BTextView *v = about->TextView();
113	if (v) {
114		rgb_color red = {255, 0, 51, 255};
115		rgb_color blue = {0, 102, 255, 255};
116
117		v->SetStylable(true);
118		char *text = (char*)v->Text();
119		char *s = text;
120		// set all Be in blue and red
121		while ((s = strstr(s, "Be")) != NULL) {
122			int32 i = s - text;
123			v->SetFontAndColor(i, i+1, NULL, 0, &blue);
124			v->SetFontAndColor(i+1, i+2, NULL, 0, &red);
125			s += 2;
126		}
127		// first text line
128		s = strchr(text, '\n');
129		BFont font;
130		v->GetFontAndColor(0, &font);
131		font.SetSize(12); // font.SetFace(B_OUTLINED_FACE);
132		v->SetFontAndColor(0, s-text+1, &font, B_FONT_SIZE);
133	};
134	about->SetFlags(about->Flags() | B_CLOSE_ON_ESCAPE);
135	about->Go();
136}
137
138
139// #pragma mark -- BlockingWindow
140
141
142BlockingWindow::BlockingWindow(BRect frame, const char *title, window_type type,
143		uint32 flags, uint32 workspace, uint32 escape_msg)
144	: HWindow(frame, title, type, flags, workspace)
145{
146	Init(title);
147}
148
149
150BlockingWindow::BlockingWindow(BRect frame, const char *title, window_look look,
151		window_feel feel, uint32 flags, uint32 workspace, uint32 escape_msg)
152	: HWindow(frame, title, look, feel, flags, workspace)
153{
154	Init(title);
155}
156
157
158BlockingWindow::~BlockingWindow()
159{
160	delete_sem(fExitSem);
161}
162
163
164void
165BlockingWindow::Init(const char* title)
166{
167	fUserQuitResult = B_OK;
168	fResult = NULL;
169	fExitSem = create_sem(0, title);
170	fReadyToQuit = false;
171}
172
173
174bool
175BlockingWindow::QuitRequested()
176{
177	if (fReadyToQuit)
178		return true;
179
180	// user requested to quit the window
181	*fResult = fUserQuitResult;
182	release_sem(fExitSem);
183	return false;
184}
185
186
187void
188BlockingWindow::Quit()
189{
190	fReadyToQuit = false; // finally allow window to quit
191	inherited::Quit(); // and quit it
192}
193
194
195void
196BlockingWindow::Quit(status_t result)
197{
198	if (fResult)
199		*fResult = result;
200
201	release_sem(fExitSem);
202}
203
204
205void
206BlockingWindow::SetUserQuitResult(status_t result)
207{
208	fUserQuitResult = result;
209}
210
211
212status_t
213BlockingWindow::Go()
214{
215	status_t result = B_ERROR;
216	fResult = &result;
217	Show();
218	acquire_sem(fExitSem);
219	// here the window still exists, because QuitRequested returns false if
220	// fReadyToQuit is false, now we can quit the window and am sure that the
221	// window thread dies before this thread
222	if (Lock()) {
223		Quit();
224	} else {
225		ASSERT(false); // should not reach here!!!
226	}
227	// here the window does not exist, good to have the result in a local variable
228	return result;
229}
230