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 == 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 340 ControlView::SetTarget(BHandler* handler) 341 { 342 delete fMessenger; 343 fMessenger = new BMessenger(handler); 344 fDrawingModeMenu->SetTargetForItems(handler); 345 } 346 347 348 void 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 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 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 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 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 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