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