1 /*
2 * Copyright 2006-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Mikael Konradson, mikael.konradson@gmail.com
7 */
8
9
10 #include "ControlView.h"
11 #include "messages.h"
12
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>
26
27 #include <stdio.h>
28
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "ControlView"
31
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)
50 {
51 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
52 GroupLayout()->SetInsets(B_USE_WINDOW_SPACING);
53 }
54
55
~ControlView()56 ControlView::~ControlView()
57 {
58 delete fMessenger;
59 delete fMessageRunner;
60 }
61
62
63 void
AttachedToWindow()64 ControlView::AttachedToWindow()
65 {
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);
70
71 _AddFontMenu();
72
73 BString label;
74
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);
81
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);
87
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);
94
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);
100
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);
105
106 fAliasingCheckBox = new BCheckBox("Aliasing",
107 B_TRANSLATE("Antialiased text"), new BMessage(ALIASING_MSG));
108 fAliasingCheckBox->SetValue(B_CONTROL_ON);
109 AddChild(fAliasingCheckBox);
110
111 _AddDrawingModeMenu();
112
113 fBoundingboxesCheckBox = new BCheckBox("BoundingBoxes",
114 B_TRANSLATE("Bounding boxes"), new BMessage(BOUNDING_BOX_MSG));
115 AddChild(fBoundingboxesCheckBox);
116
117 fCyclingFontButton = new BButton("Cyclefonts",
118 B_TRANSLATE("Cycle fonts"), new BMessage(CYCLING_FONTS_MSG));
119 AddChild(fCyclingFontButton);
120
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);
130 }
131
132
133 void
Draw(BRect updateRect)134 ControlView::Draw(BRect updateRect)
135 {
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());
140
141 SetHighColor(tint_color(ViewColor(), B_DARKEN_2_TINT));
142 StrokeLine(rect.LeftBottom(), rect.RightBottom());
143 StrokeLine(rect.RightBottom(), rect.RightTop());
144 }
145
146
147 void
MessageReceived(BMessage * msg)148 ControlView::MessageReceived(BMessage* msg)
149 {
150 if (!fMessenger) {
151 BView::MessageReceived(msg);
152 return;
153 }
154
155 switch (msg->what) {
156 case TEXT_CHANGED_MSG:
157 {
158 BMessage fontMsg(TEXT_CHANGED_MSG);
159 fontMsg.AddString("_text", fTextControl->Text());
160 fMessenger->SendMessage(&fontMsg);
161 break;
162 }
163
164 case FONTSTYLE_CHANGED_MSG:
165 _UpdateAndSendStyle(msg);
166 break;
167
168 case FONTFAMILY_CHANGED_MSG:
169 _UpdateAndSendFamily(msg);
170 break;
171
172 case FONTSIZE_MSG:
173 {
174 BString label;
175 label.SetToFormat(B_TRANSLATE("Size: %d"),
176 static_cast<int>(fFontsizeSlider->Value()));
177 fFontsizeSlider->SetLabel(label);
178
179 BMessage msg(FONTSIZE_MSG);
180 msg.AddFloat("_size", static_cast<float>(fFontsizeSlider->Value()));
181 fMessenger->SendMessage(&msg);
182 break;
183 }
184
185 case FONTSHEAR_MSG:
186 {
187 BString label;
188 label.SetToFormat(B_TRANSLATE("Shear: %d"),
189 static_cast<int>(fShearSlider->Value()));
190 fShearSlider->SetLabel(label);
191
192 BMessage msg(FONTSHEAR_MSG);
193 msg.AddFloat("_shear", static_cast<float>(fShearSlider->Value()));
194 fMessenger->SendMessage(&msg);
195 break;
196 }
197
198 case ROTATION_MSG:
199 {
200 BString label;
201 label.SetToFormat(B_TRANSLATE("Rotation: %d"),
202 static_cast<int>(fRotationSlider->Value()));
203 fRotationSlider->SetLabel(label);
204
205 BMessage msg(ROTATION_MSG);
206 msg.AddFloat("_rotation", static_cast<float>(fRotationSlider->Value()));
207 fMessenger->SendMessage(&msg);
208 break;
209 }
210
211 case SPACING_MSG:
212 {
213 BString label;
214 label.SetToFormat(B_TRANSLATE("Spacing: %d"),
215 (int)fSpacingSlider->Value());
216 fSpacingSlider->SetLabel(label);
217
218 BMessage msg(SPACING_MSG);
219 msg.AddFloat("_spacing", static_cast<float>(fSpacingSlider->Value()));
220 fMessenger->SendMessage(&msg);
221 break;
222 }
223
224 case ALIASING_MSG:
225 {
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;
234 }
235
236 case BOUNDING_BOX_MSG:
237 {
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;
246 }
247
248 case OUTLINE_MSG:
249 {
250 int8 outlineVal = (int8)fOutlineSlider->Value();
251
252 BString label;
253 label.SetToFormat(B_TRANSLATE("Outline: %d"), outlineVal);
254 fOutlineSlider->SetLabel(label);
255
256 fAliasingCheckBox->SetEnabled(outlineVal < 1);
257 fBoundingboxesCheckBox->SetEnabled(outlineVal < 1);
258
259 BMessage msg(OUTLINE_MSG);
260 msg.AddInt8("_outline", outlineVal);
261 fMessenger->SendMessage(&msg);
262 break;
263 }
264
265 case CYCLING_FONTS_MSG:
266 {
267 fCyclingFontButton->SetLabel(fCycleFonts ? \
268 B_TRANSLATE("Cycle fonts") : B_TRANSLATE("Stop cycling"));
269 fCycleFonts = !fCycleFonts;
270
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");
282 }
283 break;
284 }
285
286 case CYCLING_FONTS_UPDATE_MSG:
287 {
288 int32 familyindex = -1;
289 BMenuItem* currentFamilyItem = fFontFamilyMenu->FindMarked();
290
291 if (currentFamilyItem) {
292 familyindex = fFontFamilyMenu->IndexOf(currentFamilyItem);
293 const int32 installedStyles = count_font_styles(
294 const_cast<char*>(currentFamilyItem->Label()));
295
296 BMenu* submenu = currentFamilyItem->Submenu();
297 if (submenu == NULL) {
298 printf("Failed to get style.\n");
299 return;
300 }
301 BMenuItem* markedStyle = submenu->FindMarked();
302 fFontStyleindex = submenu->IndexOf(markedStyle);
303
304 if (fFontStyleindex < installedStyles - 1)
305 fFontStyleindex++;
306 else {
307 fFontStyleindex = 0;
308
309 if (familyindex < count_font_families() - 1)
310 familyindex++;
311 else
312 familyindex = 0;
313 }
314
315 BMenuItem* newFontFamilyItem = fFontFamilyMenu->ItemAt(familyindex);
316 BMenuItem* newstyleitem = submenu->ItemAt(fFontStyleindex);
317
318 if (newFontFamilyItem && newstyleitem) {
319 if (msg->AddString("_style", newstyleitem->Label()) != B_OK
320 || msg->AddString("_family", newFontFamilyItem->Label()) != B_OK) {
321 printf("Failed to add style or family to the message\n");
322 return;
323 }
324 printf("InstalledStyles(%" B_PRId32 "), Font(%s), Style(%s)\n",
325 installedStyles, newFontFamilyItem->Label(),
326 newstyleitem->Label());
327 _UpdateAndSendStyle(msg);
328 }
329 }
330 break;
331 }
332
333 default:
334 BView::MessageReceived(msg);
335 }
336 }
337
338
339 void
SetTarget(BHandler * handler)340 ControlView::SetTarget(BHandler* handler)
341 {
342 delete fMessenger;
343 fMessenger = new BMessenger(handler);
344 fDrawingModeMenu->SetTargetForItems(handler);
345 }
346
347
348 void
_UpdateFontmenus(bool setInitialfont)349 ControlView::_UpdateFontmenus(bool setInitialfont)
350 {
351 BFont font;
352 BMenu* stylemenu = NULL;
353
354 font_family fontFamilyName, currentFamily;
355 font_style fontStyleName, currentStyle;
356
357 GetFont(&font);
358 font.GetFamilyAndStyle(¤tFamily, ¤tStyle);
359
360 const int32 fontfamilies = count_font_families();
361
362 fFontFamilyMenu->RemoveItems(0, fFontFamilyMenu->CountItems(), true);
363
364 for (int32 i = 0; i < fontfamilies; i++) {
365 if (get_font_family(i, &fontFamilyName) == B_OK) {
366 stylemenu = new BMenu(fontFamilyName);
367 stylemenu->SetLabelFromMarked(false);
368 const int32 styles = count_font_styles(fontFamilyName);
369
370 BMessage* familyMsg = new BMessage(FONTFAMILY_CHANGED_MSG);
371 familyMsg->AddString("_family", fontFamilyName);
372 BMenuItem* familyItem = new BMenuItem(stylemenu, familyMsg);
373 fFontFamilyMenu->AddItem(familyItem);
374
375 for (int32 j = 0; j < styles; j++) {
376 if (get_font_style(fontFamilyName, j, &fontStyleName) == B_OK) {
377 BMessage* fontMsg = new BMessage(FONTSTYLE_CHANGED_MSG);
378 fontMsg->AddString("_family", fontFamilyName);
379 fontMsg->AddString("_style", fontStyleName);
380
381 BMenuItem* styleItem = new BMenuItem(fontStyleName, fontMsg);
382 styleItem->SetMarked(false);
383
384 // setInitialfont is used when we attach the FontField
385 if (!strcmp(fontStyleName, currentStyle)
386 && !strcmp(fontFamilyName, currentFamily)
387 && setInitialfont) {
388 styleItem->SetMarked(true);
389 familyItem->SetMarked(true);
390
391 BString string;
392 string << currentFamily << " " << currentStyle;
393
394 if (fFontMenuField)
395 fFontMenuField->MenuItem()->SetLabel(string.String());
396 }
397 stylemenu->AddItem(styleItem);
398 }
399 }
400
401 stylemenu->SetRadioMode(true);
402 stylemenu->SetTargetForItems(this);
403 }
404 }
405
406 fFontFamilyMenu->SetLabelFromMarked(false);
407 fFontFamilyMenu->SetTargetForItems(this);
408 }
409
410
411 void
_AddFontMenu()412 ControlView::_AddFontMenu()
413 {
414 fFontFamilyMenu = new BPopUpMenu("fontfamlilymenu");
415
416 fFontMenuField = new BMenuField("FontMenuField",
417 B_TRANSLATE("Font:"), fFontFamilyMenu);
418 AddChild(fFontMenuField);
419
420 _UpdateFontmenus(true);
421 }
422
423
424 void
_AddDrawingModeMenu()425 ControlView::_AddDrawingModeMenu()
426 {
427 fDrawingModeMenu = new BPopUpMenu("drawingmodemenu");
428
429 BMessage* drawingMsg = NULL;
430 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
431 drawingMsg->AddInt32("_mode", B_OP_COPY);
432 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_COPY", drawingMsg));
433 fDrawingModeMenu->ItemAt(0)->SetMarked(true);
434 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
435 drawingMsg->AddInt32("_mode", B_OP_OVER);
436 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_OVER", drawingMsg));
437 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
438 drawingMsg->AddInt32("_mode", B_OP_ERASE);
439 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_ERASE", drawingMsg));
440 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
441 drawingMsg->AddInt32("_mode", B_OP_INVERT);
442 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_INVERT", drawingMsg));
443 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
444 drawingMsg->AddInt32("_mode", B_OP_ADD);
445 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_ADD", drawingMsg));
446 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
447 drawingMsg->AddInt32("_mode", B_OP_SUBTRACT);
448 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_SUBTRACT", drawingMsg));
449 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
450 drawingMsg->AddInt32("_mode", B_OP_BLEND);
451 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_BLEND", drawingMsg));
452 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
453 drawingMsg->AddInt32("_mode", B_OP_MIN);
454 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_MIN", drawingMsg));
455 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
456 drawingMsg->AddInt32("_mode", B_OP_MAX);
457 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_MAX", drawingMsg));
458 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
459 drawingMsg->AddInt32("_mode", B_OP_SELECT);
460 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_SELECT", drawingMsg));
461 drawingMsg = new BMessage(DRAWINGMODE_CHANGED_MSG);
462 drawingMsg->AddInt32("_mode", B_OP_ALPHA);
463 fDrawingModeMenu->AddItem(new BMenuItem("B_OP_ALPHA", drawingMsg));
464
465 fDrawingModeMenu->SetLabelFromMarked(true);
466
467 BMenuField* drawingModeMenuField = new BMenuField("FontMenuField",
468 B_TRANSLATE("Drawing mode:"), fDrawingModeMenu);
469 AddChild(drawingModeMenuField);
470 }
471
472
473 void
_UpdateAndSendFamily(const BMessage * message)474 ControlView::_UpdateAndSendFamily(const BMessage* message)
475 {
476 _DeselectOldItems();
477
478 const char* family;
479 font_style style;
480
481 if (message->FindString("_family", &family) == B_OK) {
482 char* name;
483 type_code typeFound = 0;
484 int32 countFound = 0;
485 if (message->GetInfo(B_ANY_TYPE, 0, &name, &typeFound,
486 &countFound) == B_OK) {
487 if (typeFound == B_STRING_TYPE) {
488 BString string;
489 if (message->FindString(name, 0, &string) == B_OK)
490 printf("Family: %s\n", string.String());
491 }
492 }
493
494 BMenuItem* markedItem = fFontFamilyMenu->FindItem(family);
495 if (!markedItem)
496 return;
497
498 markedItem->SetMarked(true);
499
500 get_font_style((char*)family, 0, &style);
501
502 BString string;
503 string << family << " " << style;
504
505 if (fFontMenuField)
506 fFontMenuField->MenuItem()->SetLabel(string.String());
507
508 BMenu* submenu = markedItem->Submenu();
509
510 if (submenu) {
511 BMenuItem* styleItem = submenu->FindItem(style);
512 if (styleItem && !styleItem->IsMarked())
513 styleItem->SetMarked(true);
514 }
515
516 BMessage fontMsg(FONTFAMILY_CHANGED_MSG);
517 if (fontMsg.AddMessage("_fontMessage", message) == B_OK)
518 fMessenger->SendMessage(&fontMsg);
519 }
520 }
521
522
523 void
_UpdateAndSendStyle(const BMessage * message)524 ControlView::_UpdateAndSendStyle(const BMessage* message)
525 {
526 _DeselectOldItems();
527
528 const char* style;
529 const char* family;
530 if (message->FindString("_style", &style) == B_OK
531 && message->FindString("_family", &family) == B_OK) {
532 BMenuItem* familyItem = fFontFamilyMenu->FindItem(family);
533
534 if (familyItem && !familyItem->IsMarked()) {
535 familyItem->SetMarked(true);
536
537 BMenu* submenu = familyItem->Submenu();
538 if (submenu) {
539 BMenuItem* styleItem = submenu->FindItem(style);
540 if (styleItem && !styleItem->IsMarked())
541 styleItem->SetMarked(true);
542 }
543 printf("Family: %s, Style: %s\n", family, style);
544 }
545
546 BString string;
547 string << family << " " << style;
548
549 if (fFontMenuField)
550 fFontMenuField->MenuItem()->SetLabel(string.String());
551 }
552
553 BMessage fontMsg(FONTSTYLE_CHANGED_MSG);
554 if (fontMsg.AddMessage("_fontMessage", message) == B_OK)
555 fMessenger->SendMessage(&fontMsg);
556 }
557
558
559 void
_DeselectOldItems()560 ControlView::_DeselectOldItems()
561 {
562 BMenuItem* oldItem = fFontFamilyMenu->FindMarked();
563 if (oldItem) {
564 oldItem->SetMarked(false);
565
566 BMenu* submenu = oldItem->Submenu();
567 if (submenu) {
568 BMenuItem* marked = submenu->FindMarked();
569 if (marked)
570 marked->SetMarked(false);
571 }
572 }
573 }
574
575