1 /*
2 * Copyright 2005-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 */
8
9
10 #include <Alert.h>
11 #include <Application.h>
12 #include <Button.h>
13 #include <MenuField.h>
14 #include <MenuItem.h>
15 #include <PopUpMenu.h>
16 #include <String.h>
17 #include <Window.h>
18
19 #include <WindowPrivate.h>
20
21 #include <stdio.h>
22 #include <string.h>
23
24
25 const uint32 kMsgUpdateLook = 'uplk';
26 const uint32 kMsgUpdateFeel = 'upfe';
27 const uint32 kMsgUpdateFlags = 'upfl';
28
29 const uint32 kMsgAddWindow = 'adwn';
30 const uint32 kMsgAddSubsetWindow = 'adsw';
31
32
33 int32 gNormalWindowCount = 0;
34
35
36 class Window : public BWindow {
37 public:
38 Window(BRect frame, window_look look, window_feel feel);
39 virtual ~Window();
40
41 virtual void MessageReceived(BMessage* message);
42 virtual bool QuitRequested();
43
44 private:
45 BMessage* AddWindowMessage(window_look look, window_feel feel);
46 BString TitleForFeel(window_feel feel);
47 void _UpdateFlagsMenuLabel();
48
49 BMenuField* fFlagsField;
50 };
51
52
Window(BRect frame,window_look look,window_feel feel)53 Window::Window(BRect frame, window_look look, window_feel feel)
54 : BWindow(frame, TitleForFeel(feel).String(), look, feel,
55 B_ASYNCHRONOUS_CONTROLS)
56 {
57 BRect rect(Bounds());
58 BView *view = new BView(rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
59 view->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
60 AddChild(view);
61
62 if (!IsModal() && !IsFloating())
63 gNormalWindowCount++;
64
65 float labelWidth = view->StringWidth("Flags:") + 5.f;
66
67 BPopUpMenu* menu = new BPopUpMenu("looks");
68 const struct { const char* name; int32 look; } looks[] = {
69 {"Titled", B_TITLED_WINDOW_LOOK}, {"Document", B_DOCUMENT_WINDOW_LOOK},
70 {"Floating", B_FLOATING_WINDOW_LOOK}, {"Modal", B_MODAL_WINDOW_LOOK},
71 {"Bordered", B_BORDERED_WINDOW_LOOK}, {"No Border", B_NO_BORDER_WINDOW_LOOK},
72 {"Left Titled", kLeftTitledWindowLook}, {"Desktop", kDesktopWindowLook}
73 };
74 for (uint32 i = 0; i < sizeof(looks) / sizeof(looks[0]); i++) {
75 BMessage* message = new BMessage(kMsgUpdateLook);
76 message->AddInt32("look", looks[i].look);
77 BMenuItem* item = new BMenuItem(looks[i].name, message);
78 if (looks[i].look == (int32)Look())
79 item->SetMarked(true);
80
81 menu->AddItem(item);
82 }
83
84 rect.InsetBy(10, 10);
85 BMenuField* menuField = new BMenuField(rect, "look", "Look:", menu);
86 menuField->ResizeToPreferred();
87 menuField->SetDivider(labelWidth);
88 view->AddChild(menuField);
89
90 menu = new BPopUpMenu("feels");
91 const struct { const char* name; int32 feel; } feels[] = {
92 {"Normal", B_NORMAL_WINDOW_FEEL},
93 {"Modal Subset", B_MODAL_SUBSET_WINDOW_FEEL},
94 {"App Modal", B_MODAL_APP_WINDOW_FEEL},
95 {"All Modal", B_MODAL_ALL_WINDOW_FEEL},
96 {"Floating Subset", B_FLOATING_SUBSET_WINDOW_FEEL},
97 {"App Floating", B_FLOATING_APP_WINDOW_FEEL},
98 {"All Floating", B_FLOATING_ALL_WINDOW_FEEL},
99 {"Menu", kMenuWindowFeel},
100 {"WindowScreen", kWindowScreenFeel},
101 {"Desktop", kDesktopWindowFeel},
102 };
103 for (uint32 i = 0; i < sizeof(feels) / sizeof(feels[0]); i++) {
104 BMessage* message = new BMessage(kMsgUpdateFeel);
105 message->AddInt32("feel", feels[i].feel);
106 BMenuItem* item = new BMenuItem(feels[i].name, message);
107 if (feels[i].feel == (int32)Feel())
108 item->SetMarked(true);
109
110 menu->AddItem(item);
111 }
112
113 rect.OffsetBy(0, menuField->Bounds().Height() + 10);
114 menuField = new BMenuField(rect, "feel", "Feel:", menu);
115 menuField->ResizeToPreferred();
116 menuField->SetDivider(labelWidth);
117 view->AddChild(menuField);
118
119 menu = new BPopUpMenu("none", false, false);
120 const struct { const char* name; uint32 flag; } flags[] = {
121 {"Not Zoomable", B_NOT_ZOOMABLE},
122 {"Not Closable", B_NOT_CLOSABLE},
123 {"Not Movable", B_NOT_MOVABLE},
124 {"Not Horizontally Resizable", B_NOT_H_RESIZABLE},
125 {"Not Vertically Resizable", B_NOT_V_RESIZABLE},
126 {"Outline Resize", B_OUTLINE_RESIZE},
127 {"Accept First Click", B_WILL_ACCEPT_FIRST_CLICK},
128 {"Not Anchored On Activate", B_NOT_ANCHORED_ON_ACTIVATE},
129 {"Avoid Front", B_AVOID_FRONT},
130 #if defined(__HAIKU__) || defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
131 {"Same Position In All Workspaces", B_SAME_POSITION_IN_ALL_WORKSPACES},
132 #endif
133 };
134 for (uint32 i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
135 BMessage* message = new BMessage(kMsgUpdateFlags);
136 message->AddInt32("flag", flags[i].flag);
137 BMenuItem* item = new BMenuItem(flags[i].name, message);
138
139 menu->AddItem(item);
140 }
141
142 rect.OffsetBy(0, menuField->Bounds().Height() + 10);
143 fFlagsField = new BMenuField(rect, "flags", "Flags:", menu);
144 fFlagsField->ResizeToPreferred();
145 fFlagsField->SetDivider(labelWidth);
146 view->AddChild(fFlagsField);
147
148 // normal
149
150 rect.OffsetBy(0, menuField->Bounds().Height() + 10);
151 BButton* button = new BButton(rect, "normal", "Add Normal Window",
152 AddWindowMessage(B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL),
153 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
154 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
155 float width, height;
156 button->GetPreferredSize(&width, &height);
157 button->ResizeTo(rect.Width(), height);
158 view->AddChild(button);
159
160 // modal
161
162 rect = button->Frame();
163 rect.OffsetBy(0, rect.Height() + 5);
164 button = new BButton(rect, "modal_subset", "Add Modal Subset",
165 AddWindowMessage(B_MODAL_WINDOW_LOOK, B_MODAL_SUBSET_WINDOW_FEEL),
166 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
167 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
168 view->AddChild(button);
169
170 rect.OffsetBy(0, rect.Height() + 5);
171 button = new BButton(rect, "app_modal", "Add Application Modal",
172 AddWindowMessage(B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL),
173 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
174 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
175 view->AddChild(button);
176
177 rect.OffsetBy(0, rect.Height() + 5);
178 button = new BButton(rect, "all_modal", "Add All Modal",
179 AddWindowMessage(B_MODAL_WINDOW_LOOK, B_MODAL_ALL_WINDOW_FEEL),
180 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
181 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
182 view->AddChild(button);
183
184 // floating
185
186 rect = button->Frame();
187 rect.OffsetBy(0, rect.Height() + 5);
188 button = new BButton(rect, "floating_subset", "Add Floating Subset",
189 AddWindowMessage(B_FLOATING_WINDOW_LOOK, B_FLOATING_SUBSET_WINDOW_FEEL),
190 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
191 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
192 view->AddChild(button);
193
194 rect.OffsetBy(0, rect.Height() + 5);
195 button = new BButton(rect, "app_floating", "Add Application Floating",
196 AddWindowMessage(B_FLOATING_WINDOW_LOOK, B_FLOATING_APP_WINDOW_FEEL),
197 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
198 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
199 view->AddChild(button);
200
201 rect.OffsetBy(0, rect.Height() + 5);
202 button = new BButton(rect, "all_floating", "Add All Floating",
203 AddWindowMessage(B_FLOATING_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL),
204 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
205 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
206 view->AddChild(button);
207
208 // close
209
210 rect.OffsetBy(0, rect.Height() + 15);
211 button = new BButton(rect, "close", "Close Window",
212 new BMessage(B_QUIT_REQUESTED), B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
213 B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE);
214 button->ResizeToPreferred();
215 button->MoveTo((rect.Width() - button->Bounds().Width()) / 2, rect.top);
216 view->AddChild(button);
217
218 ResizeTo(Bounds().Width(), button->Frame().bottom + 10);
219 }
220
221
~Window()222 Window::~Window()
223 {
224 }
225
226
227 void
MessageReceived(BMessage * message)228 Window::MessageReceived(BMessage* message)
229 {
230 switch (message->what) {
231 case kMsgUpdateLook:
232 {
233 int32 look;
234 if (message->FindInt32("look", &look) != B_OK)
235 break;
236
237 SetLook((window_look)look);
238 break;
239 }
240
241 case kMsgUpdateFeel:
242 {
243 int32 feel;
244 if (message->FindInt32("feel", &feel) != B_OK)
245 break;
246
247 if (!IsModal() && !IsFloating())
248 gNormalWindowCount--;
249
250 SetFeel((window_feel)feel);
251 SetTitle(TitleForFeel((window_feel)feel).String());
252
253 if (!IsModal() && !IsFloating())
254 gNormalWindowCount++;
255 break;
256 }
257
258 case kMsgUpdateFlags:
259 {
260 uint32 flag;
261 if (message->FindInt32("flag", (int32*)&flag) != B_OK)
262 break;
263
264 BMenuItem* item;
265 if (message->FindPointer("source", (void**)&item) != B_OK)
266 break;
267
268 item->SetMarked(!item->IsMarked());
269
270 uint32 flags = Flags();
271 if (item->IsMarked())
272 flags |= flag;
273 else
274 flags &= ~flag;
275
276 SetFlags(flags);
277 _UpdateFlagsMenuLabel();
278 break;
279 }
280
281 case kMsgAddWindow:
282 case kMsgAddSubsetWindow:
283 {
284 int32 look, feel;
285 if (message->FindInt32("look", &look) != B_OK
286 || message->FindInt32("feel", &feel) != B_OK)
287 break;
288
289 BWindow* window = new Window(Frame().OffsetByCopy(20, 20),
290 (window_look)look, (window_feel)feel);
291
292 if (message->what == kMsgAddSubsetWindow) {
293 status_t status = window->AddToSubset(this);
294 if (status != B_OK) {
295 char text[512];
296 snprintf(text, sizeof(text),
297 "Window could not be added to subset:\n\n\%s", strerror(status));
298 (new BAlert("Alert", text, "OK"))->Go(NULL);
299
300 delete window;
301 break;
302 }
303 }
304
305 window->Show();
306 break;
307 }
308
309 default:
310 BWindow::MessageReceived(message);
311 }
312 }
313
314
315 bool
QuitRequested()316 Window::QuitRequested()
317 {
318 if (!IsModal() && !IsFloating())
319 gNormalWindowCount--;
320
321 if (gNormalWindowCount < 1)
322 be_app->PostMessage(B_QUIT_REQUESTED);
323
324 return true;
325 }
326
327
328 BMessage*
AddWindowMessage(window_look look,window_feel feel)329 Window::AddWindowMessage(window_look look, window_feel feel)
330 {
331 BMessage* message = new BMessage(kMsgAddWindow);
332
333 if (feel == B_FLOATING_SUBSET_WINDOW_FEEL
334 || feel == B_MODAL_SUBSET_WINDOW_FEEL)
335 message->what = kMsgAddSubsetWindow;
336
337 message->AddInt32("look", look);
338 message->AddInt32("feel", feel);
339
340 return message;
341 }
342
343
344 BString
TitleForFeel(window_feel feel)345 Window::TitleForFeel(window_feel feel)
346 {
347 BString title = "Look&Feel - ";
348
349 switch ((uint32)feel) {
350 case B_NORMAL_WINDOW_FEEL:
351 title += "Normal";
352 break;
353
354 // modal feels
355
356 case B_MODAL_SUBSET_WINDOW_FEEL:
357 title += "Modal Subset";
358 break;
359 case B_MODAL_APP_WINDOW_FEEL:
360 title += "Application Modal";
361 break;
362 case B_MODAL_ALL_WINDOW_FEEL:
363 title += "All Modal";
364 break;
365
366 // floating feels
367
368 case B_FLOATING_SUBSET_WINDOW_FEEL:
369 title += "Floating Subset";
370 break;
371 case B_FLOATING_APP_WINDOW_FEEL:
372 title += "Application Floating";
373 break;
374 case B_FLOATING_ALL_WINDOW_FEEL:
375 title += "All Floating";
376 break;
377
378 // special/private feels
379
380 case kMenuWindowFeel:
381 title += "Menu";
382 break;
383 case kWindowScreenFeel:
384 title += "WindowScreen";
385 break;
386 case kDesktopWindowFeel:
387 title += "Desktop";
388 break;
389 }
390
391 return title;
392 }
393
394
395 void
_UpdateFlagsMenuLabel()396 Window::_UpdateFlagsMenuLabel()
397 {
398 BString label;
399 BMenu* menu = fFlagsField->Menu();
400
401 for (int32 i = 0; i < menu->CountItems(); i++) {
402 BMenuItem* item = menu->ItemAt(i);
403
404 if (item->IsMarked()) {
405 if (label != "")
406 label += " + ";
407 label += item->Label();
408 }
409 }
410
411 if (label == "")
412 label = "none";
413
414 menu->Superitem()->SetLabel(label.String());
415 }
416
417
418 // #pragma mark -
419
420
421 class Application : public BApplication {
422 public:
423 Application();
424
425 virtual void ReadyToRun();
426 };
427
428
Application()429 Application::Application()
430 : BApplication("application/x-vnd.haiku-looknfeel")
431 {
432 }
433
434
435 void
ReadyToRun()436 Application::ReadyToRun()
437 {
438 Window *window = new Window(BRect(100, 100, 400, 420),
439 B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL);
440 window->Show();
441 }
442
443
444 // #pragma mark -
445
446
447 int
main(int argc,char ** argv)448 main(int argc, char **argv)
449 {
450 Application app;// app;
451
452 app.Run();
453 return 0;
454 }
455