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 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 56 ControlView::~ControlView() 57 { 58 delete fMessenger; 59 delete fMessageRunner; 60 } 61 62 63 void 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 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 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) { 298 BMenuItem* markedStyle = submenu->FindMarked(); 299 fFontStyleindex = submenu->IndexOf(markedStyle); 300 } 301 302 if (fFontStyleindex < installedStyles - 1) 303 fFontStyleindex++; 304 else { 305 fFontStyleindex = 0; 306 307 if (familyindex < count_font_families() - 1) 308 familyindex++; 309 else 310 familyindex = 0; 311 } 312 313 BMenuItem* newFontFamilyItem = fFontFamilyMenu->ItemAt(familyindex); 314 BMenuItem* newstyleitem = submenu->ItemAt(fFontStyleindex); 315 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; 321 } 322 printf("InstalledStyles(%" B_PRId32 "), Font(%s), Style(%s)\n", 323 installedStyles, newFontFamilyItem->Label(), 324 newstyleitem->Label()); 325 _UpdateAndSendStyle(msg); 326 } 327 } 328 break; 329 } 330 331 default: 332 BView::MessageReceived(msg); 333 } 334 } 335 336 337 void 338 ControlView::SetTarget(BHandler* handler) 339 { 340 delete fMessenger; 341 fMessenger = new BMessenger(handler); 342 fDrawingModeMenu->SetTargetForItems(handler); 343 } 344 345 346 void 347 ControlView::_UpdateFontmenus(bool setInitialfont) 348 { 349 BFont font; 350 BMenu* stylemenu = NULL; 351 352 font_family fontFamilyName, currentFamily; 353 font_style fontStyleName, currentStyle; 354 355 GetFont(&font); 356 font.GetFamilyAndStyle(¤tFamily, ¤tStyle); 357 358 const int32 fontfamilies = count_font_families(); 359 360 fFontFamilyMenu->RemoveItems(0, fFontFamilyMenu->CountItems(), true); 361 362 for (int32 i = 0; i < fontfamilies; i++) { 363 if (get_font_family(i, &fontFamilyName) == B_OK) { 364 stylemenu = new BMenu(fontFamilyName); 365 stylemenu->SetLabelFromMarked(false); 366 const int32 styles = count_font_styles(fontFamilyName); 367 368 BMessage* familyMsg = new BMessage(FONTFAMILY_CHANGED_MSG); 369 familyMsg->AddString("_family", fontFamilyName); 370 BMenuItem* familyItem = new BMenuItem(stylemenu, familyMsg); 371 fFontFamilyMenu->AddItem(familyItem); 372 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); 378 379 BMenuItem* styleItem = new BMenuItem(fontStyleName, fontMsg); 380 styleItem->SetMarked(false); 381 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); 388 389 BString string; 390 string << currentFamily << " " << currentStyle; 391 392 if (fFontMenuField) 393 fFontMenuField->MenuItem()->SetLabel(string.String()); 394 } 395 stylemenu->AddItem(styleItem); 396 } 397 } 398 399 stylemenu->SetRadioMode(true); 400 stylemenu->SetTargetForItems(this); 401 } 402 } 403 404 fFontFamilyMenu->SetLabelFromMarked(false); 405 fFontFamilyMenu->SetTargetForItems(this); 406 } 407 408 409 void 410 ControlView::_AddFontMenu() 411 { 412 fFontFamilyMenu = new BPopUpMenu("fontfamlilymenu"); 413 414 fFontMenuField = new BMenuField("FontMenuField", 415 B_TRANSLATE("Font:"), fFontFamilyMenu); 416 AddChild(fFontMenuField); 417 418 _UpdateFontmenus(true); 419 } 420 421 422 void 423 ControlView::_AddDrawingModeMenu() 424 { 425 fDrawingModeMenu = new BPopUpMenu("drawingmodemenu"); 426 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)); 462 463 fDrawingModeMenu->SetLabelFromMarked(true); 464 465 BMenuField* drawingModeMenuField = new BMenuField("FontMenuField", 466 B_TRANSLATE("Drawing mode:"), fDrawingModeMenu); 467 AddChild(drawingModeMenuField); 468 } 469 470 471 void 472 ControlView::_UpdateAndSendFamily(const BMessage* message) 473 { 474 _DeselectOldItems(); 475 476 font_family family; 477 font_style style; 478 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()); 489 } 490 } 491 492 BMenuItem* markedItem = fFontFamilyMenu->FindItem(family); 493 if (!markedItem) 494 return; 495 496 markedItem->SetMarked(true); 497 498 get_font_style(family, 0, &style); 499 500 BString string; 501 string << family << " " << style; 502 503 if (fFontMenuField) 504 fFontMenuField->MenuItem()->SetLabel(string.String()); 505 506 BMenu* submenu = markedItem->Submenu(); 507 508 if (submenu) { 509 BMenuItem* styleItem = submenu->FindItem(style); 510 if (styleItem && !styleItem->IsMarked()) 511 styleItem->SetMarked(true); 512 } 513 514 BMessage fontMsg(FONTFAMILY_CHANGED_MSG); 515 if (fontMsg.AddMessage("_fontMessage", message) == B_OK) 516 fMessenger->SendMessage(&fontMsg); 517 } 518 } 519 520 521 void 522 ControlView::_UpdateAndSendStyle(const BMessage* message) 523 { 524 _DeselectOldItems(); 525 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); 531 532 if (familyItem && !familyItem->IsMarked()) { 533 familyItem->SetMarked(true); 534 535 BMenu* submenu = familyItem->Submenu(); 536 if (submenu) { 537 BMenuItem* styleItem = submenu->FindItem(style); 538 if (styleItem && !styleItem->IsMarked()) 539 styleItem->SetMarked(true); 540 } 541 printf("Family: %s, Style: %s\n", family, style); 542 } 543 544 BString string; 545 string << family << " " << style; 546 547 if (fFontMenuField) 548 fFontMenuField->MenuItem()->SetLabel(string.String()); 549 } 550 551 BMessage fontMsg(FONTSTYLE_CHANGED_MSG); 552 if (fontMsg.AddMessage("_fontMessage", message) == B_OK) 553 fMessenger->SendMessage(&fontMsg); 554 } 555 556 557 void 558 ControlView::_DeselectOldItems() 559 { 560 BMenuItem* oldItem = fFontFamilyMenu->FindMarked(); 561 if (oldItem) { 562 oldItem->SetMarked(false); 563 564 BMenu* submenu = oldItem->Submenu(); 565 if (submenu) { 566 BMenuItem* marked = submenu->FindMarked(); 567 if (marked) 568 marked->SetMarked(false); 569 } 570 } 571 } 572 573