vfs: check userland buffers before reading them.
[haiku.git] / src / tests / servers / app / look_and_feel / LookAndFeel.cpp
blob5aecb51a22f9dfd10b95e3c677237887fa24f515
1 /*
2 * Copyright 2005-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 */
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>
19 #include <WindowPrivate.h>
21 #include <stdio.h>
22 #include <string.h>
25 const uint32 kMsgUpdateLook = 'uplk';
26 const uint32 kMsgUpdateFeel = 'upfe';
27 const uint32 kMsgUpdateFlags = 'upfl';
29 const uint32 kMsgAddWindow = 'adwn';
30 const uint32 kMsgAddSubsetWindow = 'adsw';
33 int32 gNormalWindowCount = 0;
36 class Window : public BWindow {
37 public:
38 Window(BRect frame, window_look look, window_feel feel);
39 virtual ~Window();
41 virtual void MessageReceived(BMessage* message);
42 virtual bool QuitRequested();
44 private:
45 BMessage* AddWindowMessage(window_look look, window_feel feel);
46 BString TitleForFeel(window_feel feel);
47 void _UpdateFlagsMenuLabel();
49 BMenuField* fFlagsField;
53 Window::Window(BRect frame, window_look look, window_feel feel)
54 : BWindow(frame, TitleForFeel(feel).String(), look, feel,
55 B_ASYNCHRONOUS_CONTROLS)
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);
62 if (!IsModal() && !IsFloating())
63 gNormalWindowCount++;
65 float labelWidth = view->StringWidth("Flags:") + 5.f;
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}
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);
81 menu->AddItem(item);
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);
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},
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);
110 menu->AddItem(item);
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);
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
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);
139 menu->AddItem(item);
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);
148 // normal
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);
160 // modal
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);
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);
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);
184 // floating
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);
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);
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);
208 // close
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);
218 ResizeTo(Bounds().Width(), button->Frame().bottom + 10);
222 Window::~Window()
227 void
228 Window::MessageReceived(BMessage* message)
230 switch (message->what) {
231 case kMsgUpdateLook:
233 int32 look;
234 if (message->FindInt32("look", &look) != B_OK)
235 break;
237 SetLook((window_look)look);
238 break;
241 case kMsgUpdateFeel:
243 int32 feel;
244 if (message->FindInt32("feel", &feel) != B_OK)
245 break;
247 if (!IsModal() && !IsFloating())
248 gNormalWindowCount--;
250 SetFeel((window_feel)feel);
251 SetTitle(TitleForFeel((window_feel)feel).String());
253 if (!IsModal() && !IsFloating())
254 gNormalWindowCount++;
255 break;
258 case kMsgUpdateFlags:
260 uint32 flag;
261 if (message->FindInt32("flag", (int32*)&flag) != B_OK)
262 break;
264 BMenuItem* item;
265 if (message->FindPointer("source", (void**)&item) != B_OK)
266 break;
268 item->SetMarked(!item->IsMarked());
270 uint32 flags = Flags();
271 if (item->IsMarked())
272 flags |= flag;
273 else
274 flags &= ~flag;
276 SetFlags(flags);
277 _UpdateFlagsMenuLabel();
278 break;
281 case kMsgAddWindow:
282 case kMsgAddSubsetWindow:
284 int32 look, feel;
285 if (message->FindInt32("look", &look) != B_OK
286 || message->FindInt32("feel", &feel) != B_OK)
287 break;
289 BWindow* window = new Window(Frame().OffsetByCopy(20, 20),
290 (window_look)look, (window_feel)feel);
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);
300 delete window;
301 break;
305 window->Show();
306 break;
309 default:
310 BWindow::MessageReceived(message);
315 bool
316 Window::QuitRequested()
318 if (!IsModal() && !IsFloating())
319 gNormalWindowCount--;
321 if (gNormalWindowCount < 1)
322 be_app->PostMessage(B_QUIT_REQUESTED);
324 return true;
328 BMessage*
329 Window::AddWindowMessage(window_look look, window_feel feel)
331 BMessage* message = new BMessage(kMsgAddWindow);
333 if (feel == B_FLOATING_SUBSET_WINDOW_FEEL
334 || feel == B_MODAL_SUBSET_WINDOW_FEEL)
335 message->what = kMsgAddSubsetWindow;
337 message->AddInt32("look", look);
338 message->AddInt32("feel", feel);
340 return message;
344 BString
345 Window::TitleForFeel(window_feel feel)
347 BString title = "Look&Feel - ";
349 switch ((uint32)feel) {
350 case B_NORMAL_WINDOW_FEEL:
351 title += "Normal";
352 break;
354 // modal feels
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;
366 // floating feels
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;
378 // special/private feels
380 case kMenuWindowFeel:
381 title += "Menu";
382 break;
383 case kWindowScreenFeel:
384 title += "WindowScreen";
385 break;
386 case kDesktopWindowFeel:
387 title += "Desktop";
388 break;
391 return title;
395 void
396 Window::_UpdateFlagsMenuLabel()
398 BString label;
399 BMenu* menu = fFlagsField->Menu();
401 for (int32 i = 0; i < menu->CountItems(); i++) {
402 BMenuItem* item = menu->ItemAt(i);
404 if (item->IsMarked()) {
405 if (label != "")
406 label += " + ";
407 label += item->Label();
411 if (label == "")
412 label = "none";
414 menu->Superitem()->SetLabel(label.String());
418 // #pragma mark -
421 class Application : public BApplication {
422 public:
423 Application();
425 virtual void ReadyToRun();
429 Application::Application()
430 : BApplication("application/x-vnd.haiku-looknfeel")
435 void
436 Application::ReadyToRun()
438 Window *window = new Window(BRect(100, 100, 400, 420),
439 B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL);
440 window->Show();
444 // #pragma mark -
447 int
448 main(int argc, char **argv)
450 Application app;// app;
452 app.Run();
453 return 0;