vfs: check userland buffers before reading them.
[haiku.git] / src / apps / fontdemo / ControlView.cpp
blobb84c444700de62404f789ce38e285502be674951
1 /*
2 * Copyright 2006-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Mikael Konradson, mikael.konradson@gmail.com
7 */
10 #include "ControlView.h"
11 #include "messages.h"
13 #include <Button.h>
14 #include <Catalog.h>
15 #include <CheckBox.h>
16 #include <Menu.h>
17 #include <MenuField.h>
18 #include <MenuItem.h>
19 #include <MessageRunner.h>
20 #include <Messenger.h>
21 #include <PopUpMenu.h>
22 #include <Slider.h>
23 #include <String.h>
24 #include <TextControl.h>
25 #include <Window.h>
27 #include <stdio.h>
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "ControlView"
32 ControlView::ControlView()
33 : BGroupView("ControlView", B_VERTICAL),
34 fMessenger(NULL),
35 fMessageRunner(NULL),
36 fTextControl(NULL),
37 fFontMenuField(NULL),
38 fFontsizeSlider(NULL),
39 fShearSlider(NULL),
40 fRotationSlider(NULL),
41 fSpacingSlider(NULL),
42 fOutlineSlider(NULL),
43 fAliasingCheckBox(NULL),
44 fBoundingboxesCheckBox(NULL),
45 fCyclingFontButton(NULL),
46 fFontFamilyMenu(NULL),
47 fDrawingModeMenu(NULL),
48 fCycleFonts(false),
49 fFontStyleindex(0)
51 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
52 GroupLayout()->SetInsets(B_USE_WINDOW_SPACING);
56 ControlView::~ControlView()
58 delete fMessenger;
59 delete fMessageRunner;
63 void
64 ControlView::AttachedToWindow()
66 fTextControl = new BTextControl("TextInput", B_TRANSLATE("Text:"),
67 B_TRANSLATE("Haiku, Inc."), NULL);
68 fTextControl->SetModificationMessage(new BMessage(TEXT_CHANGED_MSG));
69 AddChild(fTextControl);
71 _AddFontMenu();
73 BString label;
75 label.SetToFormat(B_TRANSLATE("Size: %d"), 50);
76 fFontsizeSlider = new BSlider("Fontsize", label, NULL, 4, 360,
77 B_HORIZONTAL);
78 fFontsizeSlider->SetModificationMessage(new BMessage(FONTSIZE_MSG));
79 fFontsizeSlider->SetValue(50);
80 AddChild(fFontsizeSlider);
82 label.SetToFormat(B_TRANSLATE("Shear: %d"), 90);
83 fShearSlider = new BSlider("Shear", label, NULL, 45, 135, B_HORIZONTAL);
84 fShearSlider->SetModificationMessage(new BMessage(FONTSHEAR_MSG));
85 fShearSlider->SetValue(90);
86 AddChild(fShearSlider);
88 label.SetToFormat(B_TRANSLATE("Rotation: %d"), 0);
89 fRotationSlider = new BSlider("Rotation", label, NULL, 0, 360,
90 B_HORIZONTAL);
91 fRotationSlider->SetModificationMessage( new BMessage(ROTATION_MSG));
92 fRotationSlider->SetValue(0);
93 AddChild(fRotationSlider);
95 label.SetToFormat(B_TRANSLATE("Spacing: %d"), 0);
96 fSpacingSlider = new BSlider("Spacing", label, NULL, -5, 50, B_HORIZONTAL);
97 fSpacingSlider->SetModificationMessage(new BMessage(SPACING_MSG));
98 fSpacingSlider->SetValue(0);
99 AddChild(fSpacingSlider);
101 label.SetToFormat(B_TRANSLATE("Outline: %d"), 0);
102 fOutlineSlider = new BSlider("Outline", label, NULL, 0, 20, B_HORIZONTAL);
103 fOutlineSlider->SetModificationMessage(new BMessage(OUTLINE_MSG));
104 AddChild(fOutlineSlider);
106 fAliasingCheckBox = new BCheckBox("Aliasing",
107 B_TRANSLATE("Antialiased text"), new BMessage(ALIASING_MSG));
108 fAliasingCheckBox->SetValue(B_CONTROL_ON);
109 AddChild(fAliasingCheckBox);
111 _AddDrawingModeMenu();
113 fBoundingboxesCheckBox = new BCheckBox("BoundingBoxes",
114 B_TRANSLATE("Bounding boxes"), new BMessage(BOUNDING_BOX_MSG));
115 AddChild(fBoundingboxesCheckBox);
117 fCyclingFontButton = new BButton("Cyclefonts",
118 B_TRANSLATE("Cycle fonts"), new BMessage(CYCLING_FONTS_MSG));
119 AddChild(fCyclingFontButton);
121 fTextControl->SetTarget(this);
122 fFontsizeSlider->SetTarget(this);
123 fShearSlider->SetTarget(this);
124 fRotationSlider->SetTarget(this);
125 fSpacingSlider->SetTarget(this);
126 fOutlineSlider->SetTarget(this);
127 fAliasingCheckBox->SetTarget(this);
128 fBoundingboxesCheckBox->SetTarget(this);
129 fCyclingFontButton->SetTarget(this);
133 void
134 ControlView::Draw(BRect updateRect)
136 BRect rect(Bounds());
137 SetHighColor(tint_color(ViewColor(), B_LIGHTEN_2_TINT));
138 StrokeLine(rect.LeftTop(), rect.RightTop());
139 StrokeLine(rect.LeftTop(), rect.LeftBottom());
141 SetHighColor(tint_color(ViewColor(), B_DARKEN_2_TINT));
142 StrokeLine(rect.LeftBottom(), rect.RightBottom());
143 StrokeLine(rect.RightBottom(), rect.RightTop());
147 void
148 ControlView::MessageReceived(BMessage* msg)
150 if (!fMessenger) {
151 BView::MessageReceived(msg);
152 return;
155 switch (msg->what) {
156 case TEXT_CHANGED_MSG:
158 BMessage fontMsg(TEXT_CHANGED_MSG);
159 fontMsg.AddString("_text", fTextControl->Text());
160 fMessenger->SendMessage(&fontMsg);
161 break;
164 case FONTSTYLE_CHANGED_MSG:
165 _UpdateAndSendStyle(msg);
166 break;
168 case FONTFAMILY_CHANGED_MSG:
169 _UpdateAndSendFamily(msg);
170 break;
172 case FONTSIZE_MSG:
174 BString label;
175 label.SetToFormat(B_TRANSLATE("Size: %d"),
176 static_cast<int>(fFontsizeSlider->Value()));
177 fFontsizeSlider->SetLabel(label);
179 BMessage msg(FONTSIZE_MSG);
180 msg.AddFloat("_size", static_cast<float>(fFontsizeSlider->Value()));
181 fMessenger->SendMessage(&msg);
182 break;
185 case FONTSHEAR_MSG:
187 BString label;
188 label.SetToFormat(B_TRANSLATE("Shear: %d"),
189 static_cast<int>(fShearSlider->Value()));
190 fShearSlider->SetLabel(label);
192 BMessage msg(FONTSHEAR_MSG);
193 msg.AddFloat("_shear", static_cast<float>(fShearSlider->Value()));
194 fMessenger->SendMessage(&msg);
195 break;
198 case ROTATION_MSG:
200 BString label;
201 label.SetToFormat(B_TRANSLATE("Rotation: %d"),
202 static_cast<int>(fRotationSlider->Value()));
203 fRotationSlider->SetLabel(label);
205 BMessage msg(ROTATION_MSG);
206 msg.AddFloat("_rotation", static_cast<float>(fRotationSlider->Value()));
207 fMessenger->SendMessage(&msg);
208 break;
211 case SPACING_MSG:
213 BString label;
214 label.SetToFormat(B_TRANSLATE("Spacing: %d"),
215 (int)fSpacingSlider->Value());
216 fSpacingSlider->SetLabel(label);
218 BMessage msg(SPACING_MSG);
219 msg.AddFloat("_spacing", static_cast<float>(fSpacingSlider->Value()));
220 fMessenger->SendMessage(&msg);
221 break;
224 case ALIASING_MSG:
226 BMessage msg(ALIASING_MSG);
227 msg.AddBool("_aliased", static_cast<bool>(fAliasingCheckBox->Value()));
228 fMessenger->SendMessage(&msg);
229 if (static_cast<bool>(fAliasingCheckBox->Value()) == true)
230 printf("Aliasing: true\n");
231 else
232 printf("Aliasing: false\n");
233 break;
236 case BOUNDING_BOX_MSG:
238 BMessage msg(BOUNDING_BOX_MSG);
239 msg.AddBool("_boundingbox", static_cast<bool>(fBoundingboxesCheckBox->Value()));
240 fMessenger->SendMessage(&msg);
241 if (static_cast<bool>(fBoundingboxesCheckBox->Value()))
242 printf("Bounding: true\n");
243 else
244 printf("Bounding: false\n");
245 break;
248 case OUTLINE_MSG:
250 int8 outlineVal = (int8)fOutlineSlider->Value();
252 BString label;
253 label.SetToFormat(B_TRANSLATE("Outline: %d"), outlineVal);
254 fOutlineSlider->SetLabel(label);
256 fAliasingCheckBox->SetEnabled(outlineVal < 1);
257 fBoundingboxesCheckBox->SetEnabled(outlineVal < 1);
259 BMessage msg(OUTLINE_MSG);
260 msg.AddInt8("_outline", outlineVal);
261 fMessenger->SendMessage(&msg);
262 break;
265 case CYCLING_FONTS_MSG:
267 fCyclingFontButton->SetLabel(fCycleFonts ? \
268 B_TRANSLATE("Cycle fonts") : B_TRANSLATE("Stop cycling"));
269 fCycleFonts = !fCycleFonts;
271 if (fCycleFonts) {
272 delete fMessageRunner;
273 fMessageRunner = new BMessageRunner(this,
274 new BMessage(CYCLING_FONTS_UPDATE_MSG), 360000*2, -1);
275 printf("Cycle fonts enabled\n");
276 } else {
277 // Delete our MessageRunner and reset the style index
278 delete fMessageRunner;
279 fMessageRunner = NULL;
280 fFontStyleindex = 0;
281 printf("Cycle fonts disabled\n");
283 break;
286 case CYCLING_FONTS_UPDATE_MSG:
288 int32 familyindex = -1;
289 BMenuItem* currentFamilyItem = fFontFamilyMenu->FindMarked();
291 if (currentFamilyItem) {
292 familyindex = fFontFamilyMenu->IndexOf(currentFamilyItem);
293 const int32 installedStyles = count_font_styles(
294 const_cast<char*>(currentFamilyItem->Label()));
296 BMenu* submenu = currentFamilyItem->Submenu();
297 if (submenu) {
298 BMenuItem* markedStyle = submenu->FindMarked();
299 fFontStyleindex = submenu->IndexOf(markedStyle);
302 if (fFontStyleindex < installedStyles - 1)
303 fFontStyleindex++;
304 else {
305 fFontStyleindex = 0;
307 if (familyindex < count_font_families() - 1)
308 familyindex++;
309 else
310 familyindex = 0;
313 BMenuItem* newFontFamilyItem = fFontFamilyMenu->ItemAt(familyindex);
314 BMenuItem* newstyleitem = submenu->ItemAt(fFontStyleindex);
316 if (newFontFamilyItem && newstyleitem) {
317 if (msg->AddString("_style", newstyleitem->Label()) != B_OK
318 || msg->AddString("_family", newFontFamilyItem->Label()) != B_OK) {
319 printf("Failed to add style or family to the message\n");
320 return;
322 printf("InstalledStyles(%" B_PRId32 "), Font(%s), Style(%s)\n",
323 installedStyles, newFontFamilyItem->Label(),
324 newstyleitem->Label());
325 _UpdateAndSendStyle(msg);
328 break;
331 default:
332 BView::MessageReceived(msg);
337 void
338 ControlView::SetTarget(BHandler* handler)
340 delete fMessenger;
341 fMessenger = new BMessenger(handler);
342 fDrawingModeMenu->SetTargetForItems(handler);
346 void
347 ControlView::_UpdateFontmenus(bool setInitialfont)
349 BFont font;
350 BMenu* stylemenu = NULL;
352 font_family fontFamilyName, currentFamily;
353 font_style fontStyleName, currentStyle;
355 GetFont(&font);
356 font.GetFamilyAndStyle(&currentFamily, &currentStyle);
358 const int32 fontfamilies = count_font_families();
360 fFontFamilyMenu->RemoveItems(0, fFontFamilyMenu->CountItems(), true);
362 for (int32 i = 0; i < fontfamilies; i++) {
363 if (get_font_family(i, &fontFamilyName) == B_OK) {
364 stylemenu = new BPopUpMenu(fontFamilyName);
365 stylemenu->SetLabelFromMarked(false);
366 const int32 styles = count_font_styles(fontFamilyName);
368 BMessage* familyMsg = new BMessage(FONTFAMILY_CHANGED_MSG);
369 familyMsg->AddString("_family", fontFamilyName);
370 BMenuItem* familyItem = new BMenuItem(stylemenu, familyMsg);
371 fFontFamilyMenu->AddItem(familyItem);
373 for (int32 j = 0; j < styles; j++) {
374 if (get_font_style(fontFamilyName, j, &fontStyleName) == B_OK) {
375 BMessage* fontMsg = new BMessage(FONTSTYLE_CHANGED_MSG);
376 fontMsg->AddString("_family", fontFamilyName);
377 fontMsg->AddString("_style", fontStyleName);
379 BMenuItem* styleItem = new BMenuItem(fontStyleName, fontMsg);
380 styleItem->SetMarked(false);
382 // setInitialfont is used when we attach the FontField
383 if (!strcmp(fontStyleName, currentStyle)
384 && !strcmp(fontFamilyName, currentFamily)
385 && setInitialfont) {
386 styleItem->SetMarked(true);
387 familyItem->SetMarked(true);
389 BString string;
390 string << currentFamily << " " << currentStyle;
392 if (fFontMenuField)
393 fFontMenuField->MenuItem()->SetLabel(string.String());
395 stylemenu->AddItem(styleItem);
399 stylemenu->SetRadioMode(true);
400 stylemenu->SetTargetForItems(this);
404 fFontFamilyMenu->SetLabelFromMarked(false);
405 fFontFamilyMenu->SetTargetForItems(this);
409 void
410 ControlView::_AddFontMenu()
412 fFontFamilyMenu = new BPopUpMenu("fontfamlilymenu");
414 fFontMenuField = new BMenuField("FontMenuField",
415 B_TRANSLATE("Font:"), fFontFamilyMenu);
416 AddChild(fFontMenuField);
418 _UpdateFontmenus(true);
422 void
423 ControlView::_AddDrawingModeMenu()
425 fDrawingModeMenu = new BPopUpMenu("drawingmodemenu");
427 BMessage* drawingMsg = NULL;
428 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
429 drawingMsg->AddInt32("_mode", B_OP_COPY);
430 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_COPY", drawingMsg));
431 fDrawingModeMenu->ItemAt(0)->SetMarked(true);
432 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
433 drawingMsg->AddInt32("_mode", B_OP_OVER);
434 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_OVER", drawingMsg));
435 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
436 drawingMsg->AddInt32("_mode", B_OP_ERASE);
437 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_ERASE", drawingMsg));
438 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
439 drawingMsg->AddInt32("_mode", B_OP_INVERT);
440 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_INVERT", drawingMsg));
441 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
442 drawingMsg->AddInt32("_mode", B_OP_ADD);
443 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_ADD", drawingMsg));
444 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
445 drawingMsg->AddInt32("_mode", B_OP_SUBTRACT);
446 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_SUBTRACT", drawingMsg));
447 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
448 drawingMsg->AddInt32("_mode", B_OP_BLEND);
449 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_BLEND", drawingMsg));
450 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
451 drawingMsg->AddInt32("_mode", B_OP_MIN);
452 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_MIN", drawingMsg));
453 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
454 drawingMsg->AddInt32("_mode", B_OP_MAX);
455 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_MAX", drawingMsg));
456 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
457 drawingMsg->AddInt32("_mode", B_OP_SELECT);
458 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_SELECT", drawingMsg));
459 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
460 drawingMsg->AddInt32("_mode", B_OP_ALPHA);
461 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_ALPHA", drawingMsg));
463 fDrawingModeMenu->SetLabelFromMarked(true);
465 BMenuField* drawingModeMenuField = new BMenuField("FontMenuField",
466 B_TRANSLATE("Drawing mode:"), fDrawingModeMenu);
467 AddChild(drawingModeMenuField);
471 void
472 ControlView::_UpdateAndSendFamily(const BMessage* message)
474 _DeselectOldItems();
476 font_family family;
477 font_style style;
479 if (message->FindString("_family", (const char **)&family) == B_OK) {
480 char* name;
481 type_code typeFound = 0;
482 int32 countFound = 0;
483 if (message->GetInfo(B_ANY_TYPE, 0, &name, &typeFound,
484 &countFound) == B_OK) {
485 if (typeFound == B_STRING_TYPE) {
486 BString string;
487 if (message->FindString(name, 0, &string) == B_OK)
488 printf("Family: %s\n", string.String());
492 BMenuItem* markedItem = fFontFamilyMenu->FindItem(family);
493 if (!markedItem)
494 return;
496 markedItem->SetMarked(true);
498 get_font_style(family, 0, &style);
500 BString string;
501 string << family << " " << style;
503 if (fFontMenuField)
504 fFontMenuField->MenuItem()->SetLabel(string.String());
506 BMenu* submenu = markedItem->Submenu();
508 if (submenu) {
509 BMenuItem* styleItem = submenu->FindItem(style);
510 if (styleItem && !styleItem->IsMarked())
511 styleItem->SetMarked(true);
514 BMessage fontMsg(FONTFAMILY_CHANGED_MSG);
515 if (fontMsg.AddMessage("_fontMessage", message) == B_OK)
516 fMessenger->SendMessage(&fontMsg);
521 void
522 ControlView::_UpdateAndSendStyle(const BMessage* message)
524 _DeselectOldItems();
526 const char* style;
527 const char* family;
528 if (message->FindString("_style", &style) == B_OK
529 && message->FindString("_family", &family) == B_OK) {
530 BMenuItem* familyItem = fFontFamilyMenu->FindItem(family);
532 if (familyItem && !familyItem->IsMarked()) {
533 familyItem->SetMarked(true);
535 BMenu* submenu = familyItem->Submenu();
536 if (submenu) {
537 BMenuItem* styleItem = submenu->FindItem(style);
538 if (styleItem && !styleItem->IsMarked())
539 styleItem->SetMarked(true);
541 printf("Family: %s, Style: %s\n", family, style);
544 BString string;
545 string << family << " " << style;
547 if (fFontMenuField)
548 fFontMenuField->MenuItem()->SetLabel(string.String());
551 BMessage fontMsg(FONTSTYLE_CHANGED_MSG);
552 if (fontMsg.AddMessage("_fontMessage", message) == B_OK)
553 fMessenger->SendMessage(&fontMsg);
557 void
558 ControlView::_DeselectOldItems()
560 BMenuItem* oldItem = fFontFamilyMenu->FindMarked();
561 if (oldItem) {
562 oldItem->SetMarked(false);
564 BMenu* submenu = oldItem->Submenu();
565 if (submenu) {
566 BMenuItem* marked = submenu->FindMarked();
567 if (marked)
568 marked->SetMarked(false);