1 /* 2 * Copyright 2002-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jerome Duval (jerome.duval@free.fr) 7 * Axel Dörfler, axeld@pinc-software.de 8 */ 9 10 11 #include "BackgroundsView.h" 12 #include "ImageFilePanel.h" 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 17 #include <Debug.h> 18 #include <OS.h> 19 #include <MenuField.h> 20 #include <StorageKit.h> 21 #include <Window.h> 22 #include <Messenger.h> 23 #include <Bitmap.h> 24 #include <Point.h> 25 #include <TranslationKit.h> 26 #include <PopUpMenu.h> 27 28 #include <be_apps/Tracker/Background.h> 29 30 31 static const uint32 kMsgApplySettings = 'aply'; 32 static const uint32 kMsgRevertSettings = 'rvrt'; 33 34 static const uint32 kMsgUpdateColor = 'upcl'; 35 static const uint32 kMsgAllWorkspaces = 'alwk'; 36 static const uint32 kMsgCurrentWorkspace = 'crwk'; 37 static const uint32 kMsgDefaultFolder = 'dffl'; 38 static const uint32 kMsgOtherFolder = 'otfl'; 39 static const uint32 kMsgNoImage = 'noim'; 40 static const uint32 kMsgOtherImage = 'otim'; 41 static const uint32 kMsgImageSelected = 'imsl'; 42 static const uint32 kMsgFolderSelected = 'flsl'; 43 44 static const uint32 kMsgCenterPlacement = 'cnpl'; 45 static const uint32 kMsgManualPlacement = 'mnpl'; 46 static const uint32 kMsgScalePlacement = 'scpl'; 47 static const uint32 kMsgTilePlacement = 'tlpl'; 48 static const uint32 kMsgIconLabelOutline = 'ilol'; 49 50 static const uint32 kMsgImagePlacement = 'xypl'; 51 static const uint32 kMsgUpdatePreviewPlacement = 'pvpl'; 52 53 54 const uint8 kHandCursorData[68] = { 55 16, 1, 2, 2, 56 57 0, 0, // 0000000000000000 58 7, 128, // 0000011110000000 59 61, 112, // 0011110101110000 60 37, 40, // 0010010100101000 61 36, 168, // 0010010010101000 62 18, 148, // 0001001010010100 63 18, 84, // 0001001001010100 64 9, 42, // 0000100100101010 65 8, 1, // 0000100000000001 66 60, 1, // 0011110000000001 67 76, 1, // 0100110000000001 68 66, 1, // 0100001000000001 69 48, 1, // 0011000000000001 70 12, 1, // 0000110000000001 71 2, 0, // 0000001000000000 72 1, 0, // 0000000100000000 73 74 0, 0, // 0000000000000000 75 7, 128, // 0000011110000000 76 63, 240, // 0011111111110000 77 63, 248, // 0011111111111000 78 63, 248, // 0011111111111000 79 31, 252, // 0001111111111100 80 31, 252, // 0001111111111100 81 15, 254, // 0000111111111110 82 15, 255, // 0000111111111111 83 63, 255, // 0011111111111111 84 127, 255, // 0111111111111111 85 127, 255, // 0111111111111111 86 63, 255, // 0011111111111111 87 15, 255, // 0000111111111111 88 3, 254, // 0000001111111110 89 1, 248 // 0000000111111000 90 }; 91 92 93 BackgroundsView::BackgroundsView(BRect frame, const char *name, int32 resize, 94 int32 flags) 95 : BBox(frame, name, resize, flags | B_WILL_DRAW | B_FRAME_EVENTS, B_NO_BORDER), 96 fCurrent(NULL), 97 fCurrentInfo(NULL), 98 fLastImageIndex(-1), 99 fPathList(1, true), 100 fImageList(1, true) 101 { 102 // we need the "Current Workspace" first to get its height 103 104 BMenuItem *menuItem; 105 fWorkspaceMenu = new BPopUpMenu("pick one"); 106 fWorkspaceMenu->AddItem(menuItem = new BMenuItem("All Workspaces", 107 new BMessage(kMsgAllWorkspaces))); 108 fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Current Workspace", 109 new BMessage(kMsgCurrentWorkspace))); 110 menuItem->SetMarked(true); 111 fLastWorkspaceIndex = fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked()); 112 fWorkspaceMenu->AddSeparatorItem(); 113 fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Default folder", 114 new BMessage(kMsgDefaultFolder))); 115 fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Other folder" B_UTF8_ELLIPSIS, 116 new BMessage(kMsgOtherFolder))); 117 118 BMenuField *workspaceMenuField = new BMenuField(BRect(0, 0, 130, 18), 119 "workspaceMenuField", NULL, fWorkspaceMenu, true); 120 workspaceMenuField->ResizeToPreferred(); 121 122 /* the preview box */ 123 124 BFont font(be_plain_font); 125 font_height fontHeight; 126 font.GetHeight(&fontHeight); 127 128 fPreview = new PreviewBox(BRect(10, 8.0 + workspaceMenuField->Bounds().Height() / 2.0f 129 - ceilf(fontHeight.ascent + fontHeight.descent) / 2.0f, 160, 180), "preview"); 130 fPreview->SetFont(&font); 131 fPreview->SetLabel("Preview"); 132 AddChild(fPreview); 133 134 BRect rect(10, fPreview->Bounds().bottom - 30, 70, fPreview->Bounds().bottom - 10); 135 fXPlacementText = new BTextControl(rect, "xPlacementText", "X:", NULL, 136 new BMessage(kMsgImagePlacement), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 137 fXPlacementText->SetDivider(fXPlacementText->StringWidth(fXPlacementText->Label()) + 4.0f); 138 fXPlacementText->TextView()->SetMaxBytes(5); 139 float width, height; 140 fXPlacementText->GetPreferredSize(&width, &height); 141 float delta = fXPlacementText->Bounds().Height() - height; 142 fXPlacementText->MoveBy(0, delta); 143 fXPlacementText->ResizeTo(fXPlacementText->Bounds().Width(), height); 144 fPreview->AddChild(fXPlacementText); 145 146 rect.OffsetBy(70, delta); 147 fYPlacementText = new BTextControl(rect, "yPlacementText", "Y:", NULL, 148 new BMessage(kMsgImagePlacement), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); 149 fYPlacementText->SetDivider(fYPlacementText->StringWidth(fYPlacementText->Label()) + 4.0f); 150 fYPlacementText->TextView()->SetMaxBytes(5); 151 fXPlacementText->ResizeTo(fYPlacementText->Bounds().Width(), height); 152 fPreview->AddChild(fYPlacementText); 153 154 for (int32 i = 0; i < 256; i++) { 155 if ((i < '0' || i > '9') && i != '-') { 156 fXPlacementText->TextView()->DisallowChar(i); 157 fYPlacementText->TextView()->DisallowChar(i); 158 } 159 } 160 161 fPreView = new PreView(BRect(15, 25, 135, 115), "preView", 162 B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_SUBPIXEL_PRECISE); 163 fPreview->AddChild(fPreView); 164 165 /* the right box */ 166 167 BBox *rightbox = new BBox(BRect(fPreview->Frame().right + 10, 168 7, Frame().right - 10, fPreview->Frame().bottom), 169 "rightbox"); 170 rightbox->SetLabel(workspaceMenuField); 171 AddChild(rightbox); 172 173 float offset = be_plain_font->StringWidth("Placement:") + 5; 174 rect.Set(10, 0, rightbox->Bounds().right - 10, 30); 175 #ifdef __HAIKU__ 176 rect.top = 8 + rightbox->InnerFrame().top; 177 #else 178 rect.top = 5 + workspaceMenuField->Bounds().Height(); 179 rect.bottom = rect.top + workspaceMenuField->Bounds().Height(); 180 #endif 181 182 fImageMenu = new BPopUpMenu("pick one"); 183 fImageMenu->AddItem(new BGImageMenuItem("None", -1, new BMessage(kMsgNoImage))); 184 fImageMenu->AddSeparatorItem(); 185 fImageMenu->AddItem(new BMenuItem("Other" B_UTF8_ELLIPSIS, new BMessage(kMsgOtherImage))); 186 187 BMenuField *imageMenuField = new BMenuField(rect, "imageMenuField", 188 "Image:", fImageMenu); 189 imageMenuField->SetDivider(offset); 190 imageMenuField->SetAlignment(B_ALIGN_RIGHT); 191 imageMenuField->ResizeToPreferred(); 192 rightbox->AddChild(imageMenuField); 193 194 fPlacementMenu = new BPopUpMenu("pick one"); 195 fPlacementMenu->AddItem(new BMenuItem("Manual", 196 new BMessage(kMsgManualPlacement))); 197 fPlacementMenu->AddItem(new BMenuItem("Center", 198 new BMessage(kMsgCenterPlacement))); 199 fPlacementMenu->AddItem(new BMenuItem("Scale to fit", 200 new BMessage(kMsgScalePlacement))); 201 fPlacementMenu->AddItem(new BMenuItem("Tile", 202 new BMessage(kMsgTilePlacement))); 203 204 rect.OffsetBy(0, imageMenuField->Bounds().Height() + 5); 205 BMenuField *placementMenuField = new BMenuField(rect, "placementMenuField", 206 "Placement:", fPlacementMenu); 207 placementMenuField->SetDivider(offset); 208 placementMenuField->SetAlignment(B_ALIGN_RIGHT); 209 placementMenuField->ResizeToPreferred(); 210 rightbox->AddChild(placementMenuField); 211 212 rect.OffsetBy(offset, placementMenuField->Bounds().Height() + 5); 213 fIconLabelOutline = new BCheckBox(rect, "iconLabelOutline", 214 "Icon label outline", new BMessage(kMsgIconLabelOutline)); 215 fIconLabelOutline->SetValue(B_CONTROL_OFF); 216 fIconLabelOutline->ResizeToPreferred(); 217 rightbox->AddChild(fIconLabelOutline); 218 219 rect.top += fIconLabelOutline->Bounds().Height() + 15; 220 fPicker = new BColorControl(BPoint(10, rect.top), B_CELLS_32x8, 7.0, "Picker", 221 new BMessage(kMsgUpdateColor)); 222 rightbox->AddChild(fPicker); 223 224 float xDelta = max_c(fIconLabelOutline->Frame().right, fPicker->Frame().right) 225 + 10.0f - rightbox->Bounds().Width(); 226 delta = fPicker->Frame().bottom + 10.0f - rightbox->Bounds().Height(); 227 228 rightbox->ResizeBy(xDelta, delta); 229 fPreview->ResizeBy(0, delta); 230 231 // we're not yet attached to a view, so we need to move them manually 232 fXPlacementText->MoveBy(0, delta); 233 fYPlacementText->MoveBy(0, delta); 234 235 rect = fPreview->Frame(); 236 rect.top = rect.bottom + 10.0; 237 fRevert = new BButton(rect, "revert", "Revert", new BMessage(kMsgRevertSettings)); 238 AddChild(fRevert); 239 fRevert->ResizeToPreferred(); 240 241 rect.left = rightbox->Frame().right; 242 fApply = new BButton(rect, "apply", "Apply", new BMessage(kMsgApplySettings)); 243 AddChild(fApply); 244 fApply->ResizeToPreferred(); 245 fApply->MoveBy(-fApply->Bounds().Width(), 0); 246 fApply->MakeDefault(true); 247 } 248 249 250 BackgroundsView::~BackgroundsView() 251 { 252 delete fPanel; 253 delete fFolderPanel; 254 } 255 256 257 void 258 BackgroundsView::GetPreferredSize(float* _width, float* _height) 259 { 260 if (_width) 261 *_width = fApply->Frame().right + 10; 262 if (_height) 263 *_height = fApply->Frame().bottom + 10; 264 } 265 266 267 void 268 BackgroundsView::AllAttached() 269 { 270 fPlacementMenu->SetTargetForItems(this); 271 fImageMenu->SetTargetForItems(this); 272 fWorkspaceMenu->SetTargetForItems(this); 273 fXPlacementText->SetTarget(this); 274 fYPlacementText->SetTarget(this); 275 fIconLabelOutline->SetTarget(this); 276 fPicker->SetTarget(this); 277 fApply->SetTarget(this); 278 fRevert->SetTarget(this); 279 280 BPath path; 281 entry_ref ref; 282 if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) == B_OK) { 283 path.Append("artwork"); 284 get_ref_for_path(path.Path(), &ref); 285 } 286 287 BMessenger messenger(this); 288 fPanel = new ImageFilePanel(B_OPEN_PANEL, &messenger, &ref, 289 B_FILE_NODE, false, NULL, new CustomRefFilter(true)); 290 fPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); 291 292 fFolderPanel = new BFilePanel(B_OPEN_PANEL, &messenger, NULL, 293 B_DIRECTORY_NODE, false, NULL, new CustomRefFilter(false)); 294 fFolderPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); 295 296 LoadSettings(); 297 LoadDesktopFolder(); 298 299 float width, height; 300 GetPreferredSize(&width, &height); 301 302 BPoint point; 303 if (fSettings.FindPoint("pos", &point) != B_OK) { 304 BRect frame(BScreen().Frame()); 305 point.Set((frame.right - width) / 2, (frame.bottom - height) / 2); 306 } 307 308 ResizeTo(width, height); 309 Window()->MoveTo(point); 310 Window()->ResizeTo(width, height); 311 312 fApply->SetEnabled(false); 313 fRevert->SetEnabled(false); 314 } 315 316 317 void 318 BackgroundsView::MessageReceived(BMessage *msg) 319 { 320 switch (msg->what) { 321 case B_SIMPLE_DATA: 322 case B_REFS_RECEIVED: 323 RefsReceived(msg); 324 break; 325 326 case kMsgUpdatePreviewPlacement: 327 { 328 BString xstring, ystring; 329 xstring << (int)fPreView->fPoint.x; 330 ystring << (int)fPreView->fPoint.y; 331 fXPlacementText->SetText(xstring.String()); 332 fYPlacementText->SetText(ystring.String()); 333 UpdatePreview(); 334 UpdateButtons(); 335 break; 336 } 337 338 case kMsgManualPlacement: 339 UpdatePreview(); 340 UpdateButtons(); 341 break; 342 343 case kMsgTilePlacement: 344 case kMsgScalePlacement: 345 case kMsgCenterPlacement: 346 UpdatePreview(); 347 UpdateButtons(); 348 break; 349 350 case kMsgIconLabelOutline: 351 UpdateButtons(); 352 break; 353 354 case kMsgUpdateColor: 355 case kMsgImagePlacement: 356 UpdatePreview(); 357 UpdateButtons(); 358 break; 359 360 case kMsgCurrentWorkspace: 361 case kMsgAllWorkspaces: 362 fImageMenu->FindItem(kMsgNoImage)->SetLabel("None"); 363 fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( 364 fWorkspaceMenu->FindMarked()); 365 if (fCurrent && fCurrent->IsDesktop()) { 366 UpdateButtons(); 367 } else { 368 fPreview->SetDesktop(true); 369 LoadDesktopFolder(); 370 } 371 break; 372 373 case kMsgDefaultFolder: 374 fImageMenu->FindItem(kMsgNoImage)->SetLabel("None"); 375 fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( 376 fWorkspaceMenu->FindMarked()); 377 fPreview->SetDesktop(false); 378 LoadDefaultFolder(); 379 break; 380 381 case kMsgOtherFolder: 382 fFolderPanel->Show(); 383 break; 384 385 case kMsgOtherImage: 386 fPanel->Show(); 387 break; 388 389 case B_CANCEL: 390 { 391 PRINT(("cancel received\n")); 392 void* pointer; 393 msg->FindPointer("source", &pointer); 394 if (pointer == fPanel) { 395 if (fLastImageIndex >= 0) 396 FindImageItem(fLastImageIndex)->SetMarked(true); 397 else 398 fImageMenu->ItemAt(0)->SetMarked(true); 399 } else if (pointer == fFolderPanel) { 400 if (fLastWorkspaceIndex >= 0) 401 fWorkspaceMenu->ItemAt(fLastWorkspaceIndex)->SetMarked(true); 402 } 403 break; 404 } 405 406 case kMsgImageSelected: 407 case kMsgNoImage: 408 fLastImageIndex = ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex(); 409 UpdatePreview(); 410 UpdateButtons(); 411 break; 412 413 case kMsgFolderSelected: 414 fImageMenu->FindItem(kMsgNoImage)->SetLabel("Default"); 415 fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( 416 fWorkspaceMenu->FindMarked()); 417 fPreview->SetDesktop(false); 418 LoadRecentFolder(*fPathList.ItemAt(fWorkspaceMenu->IndexOf( 419 fWorkspaceMenu->FindMarked()) - 6)); 420 break; 421 422 case kMsgApplySettings: 423 { 424 Save(); 425 426 //NotifyServer(); 427 thread_id notify_thread; 428 notify_thread = spawn_thread(BackgroundsView::NotifyThread, "notifyServer", 429 B_NORMAL_PRIORITY, this); 430 resume_thread(notify_thread); 431 UpdateButtons(); 432 break; 433 } 434 case kMsgRevertSettings: 435 UpdateWithCurrent(); 436 break; 437 438 default: 439 BView::MessageReceived(msg); 440 break; 441 } 442 } 443 444 445 void 446 BackgroundsView::LoadDesktopFolder() 447 { 448 BPath path; 449 if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) { 450 status_t err; 451 err = get_ref_for_path(path.Path(), &fCurrentRef); 452 if (err != B_OK) 453 printf("error in LoadDesktopSettings\n"); 454 LoadFolder(true); 455 } 456 } 457 458 459 void 460 BackgroundsView::LoadDefaultFolder() 461 { 462 BPath path; 463 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 464 BString pathString = path.Path(); 465 pathString << "/Tracker/DefaultFolderTemplate"; 466 status_t err; 467 err = get_ref_for_path(pathString.String(), &fCurrentRef); 468 if (err != B_OK) 469 printf("error in LoadDefaultFolderSettings\n"); 470 LoadFolder(false); 471 } 472 } 473 474 475 void 476 BackgroundsView::LoadRecentFolder(BPath path) 477 { 478 status_t err; 479 err = get_ref_for_path(path.Path(), &fCurrentRef); 480 if (err != B_OK) 481 printf("error in LoadRecentFolder\n"); 482 LoadFolder(false); 483 } 484 485 486 void 487 BackgroundsView::LoadFolder(bool isDesktop) 488 { 489 if (fCurrent) { 490 delete fCurrent; 491 fCurrent = NULL; 492 } 493 494 BNode node(&fCurrentRef); 495 if (node.InitCheck() == B_OK) 496 fCurrent = BackgroundImage::GetBackgroundImage(&node, isDesktop, this); 497 498 UpdateWithCurrent(); 499 } 500 501 502 void 503 BackgroundsView::UpdateWithCurrent(void) 504 { 505 if (fCurrent == NULL) 506 return; 507 508 fPlacementMenu->FindItem(kMsgScalePlacement)->SetEnabled(fCurrent->IsDesktop()); 509 fPlacementMenu->FindItem(kMsgCenterPlacement)->SetEnabled(fCurrent->IsDesktop()); 510 511 if (fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked()) > 5) 512 fImageMenu->FindItem(kMsgNoImage)->SetLabel("Default"); 513 else 514 fImageMenu->FindItem(kMsgNoImage)->SetLabel("None"); 515 516 for (int32 i = fImageMenu->CountItems() - 5; i >= 0; i--) { 517 fImageMenu->RemoveItem(2); 518 } 519 520 for (int32 i = fImageList.CountItems() - 1; i >= 0; i--) { 521 BMessage *message = new BMessage(kMsgImageSelected); 522 AddItem(new BGImageMenuItem(GetImage(i)->GetName(), i, message)); 523 } 524 525 fImageMenu->SetTargetForItems(this); 526 527 fCurrentInfo = fCurrent->ImageInfoForWorkspace(current_workspace()); 528 529 if (!fCurrentInfo) { 530 fImageMenu->FindItem(kMsgNoImage)->SetMarked(true); 531 fPlacementMenu->FindItem(kMsgManualPlacement)->SetMarked(true); 532 fIconLabelOutline->SetValue(B_CONTROL_ON); 533 } else { 534 fIconLabelOutline->SetValue(fCurrentInfo->fTextWidgetLabelOutline 535 ? B_CONTROL_ON : B_CONTROL_OFF); 536 537 BString xtext, ytext; 538 int32 cmd = 0; 539 switch (fCurrentInfo->fMode) { 540 case BackgroundImage::kCentered: 541 cmd = kMsgCenterPlacement; 542 break; 543 case BackgroundImage::kScaledToFit: 544 cmd = kMsgScalePlacement; 545 break; 546 case BackgroundImage::kAtOffset: 547 cmd = kMsgManualPlacement; 548 xtext << (int)fCurrentInfo->fOffset.x; 549 ytext << (int)fCurrentInfo->fOffset.y; 550 break; 551 case BackgroundImage::kTiled: 552 cmd = kMsgTilePlacement; 553 break; 554 } 555 556 if (cmd != 0) 557 fPlacementMenu->FindItem(cmd)->SetMarked(true); 558 559 fXPlacementText->SetText(xtext.String()); 560 fYPlacementText->SetText(ytext.String()); 561 562 fLastImageIndex = fCurrentInfo->fImageIndex; 563 FindImageItem(fLastImageIndex)->SetMarked(true); 564 } 565 566 rgb_color color = {255, 255, 255, 255}; 567 if (fCurrent->IsDesktop()) { 568 color = BScreen().DesktopColor(); 569 fPicker->SetEnabled(true); 570 } else 571 fPicker->SetEnabled(false); 572 573 fPicker->SetValue(color); 574 575 UpdatePreview(); 576 UpdateButtons(); 577 } 578 579 580 void 581 BackgroundsView::Save() 582 { 583 bool textWidgetLabelOutline = 584 fIconLabelOutline->Value() == B_CONTROL_ON; 585 BackgroundImage::Mode mode = FindPlacementMode(); 586 BPoint offset(atoi(fXPlacementText->Text()), atoi(fYPlacementText->Text())); 587 588 if (!fCurrent->IsDesktop()) { 589 if (fCurrentInfo == NULL) { 590 fCurrentInfo = new BackgroundImage::BackgroundImageInfo(B_ALL_WORKSPACES, 591 fLastImageIndex, mode, offset, textWidgetLabelOutline, 0, 0); 592 fCurrent->Add(fCurrentInfo); 593 } else { 594 fCurrentInfo->fTextWidgetLabelOutline = textWidgetLabelOutline; 595 fCurrentInfo->fMode = mode; 596 if (fCurrentInfo->fMode == BackgroundImage::kAtOffset) 597 fCurrentInfo->fOffset = offset; 598 fCurrentInfo->fImageIndex = fLastImageIndex; 599 } 600 } else { 601 uint32 workspaceMask = 1; 602 int32 workspace = current_workspace(); 603 for (; workspace; workspace--) 604 workspaceMask *= 2; 605 606 if (fCurrentInfo != NULL) { 607 if (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) { 608 if (fCurrentInfo->fWorkspace & workspaceMask 609 && fCurrentInfo->fWorkspace != workspaceMask) { 610 fCurrentInfo->fWorkspace = fCurrentInfo->fWorkspace 611 ^ workspaceMask; 612 if (fLastImageIndex > -1) { 613 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 614 workspaceMask, fLastImageIndex, mode, offset, 615 textWidgetLabelOutline, fCurrentInfo->fImageSet, 616 fCurrentInfo->fCacheMode); 617 fCurrent->Add(fCurrentInfo); 618 } 619 } else if (fCurrentInfo->fWorkspace == workspaceMask) { 620 if (fLastImageIndex > -1) { 621 fCurrentInfo->fTextWidgetLabelOutline = 622 textWidgetLabelOutline; 623 fCurrentInfo->fMode = mode; 624 if (fCurrentInfo->fMode == BackgroundImage::kAtOffset) 625 fCurrentInfo->fOffset = offset; 626 627 fCurrentInfo->fImageIndex = fLastImageIndex; 628 } else { 629 fCurrent->Remove(fCurrentInfo); 630 fCurrentInfo = NULL; 631 } 632 } 633 } else { 634 fCurrent->RemoveAll(); 635 if (fLastImageIndex > -1) { 636 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 637 B_ALL_WORKSPACES, fLastImageIndex, mode, offset, 638 textWidgetLabelOutline, fCurrent->GetShowingImageSet(), 639 fCurrentInfo->fCacheMode); 640 fCurrent->Add(fCurrentInfo); 641 } 642 } 643 } else if (fLastImageIndex > -1) { 644 if (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) { 645 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 646 workspaceMask, fLastImageIndex, mode, offset, 647 textWidgetLabelOutline, fCurrent->GetShowingImageSet(), 0); 648 } else { 649 fCurrent->RemoveAll(); 650 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 651 B_ALL_WORKSPACES, fLastImageIndex, mode, offset, 652 textWidgetLabelOutline, fCurrent->GetShowingImageSet(), 0); 653 } 654 fCurrent->Add(fCurrentInfo); 655 } 656 657 if (!fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) { 658 for (int32 i = 0; i < count_workspaces(); i++) { 659 BScreen().SetDesktopColor(fPicker->ValueAsColor(), i, true); 660 } 661 } else 662 BScreen().SetDesktopColor(fPicker->ValueAsColor(), true); 663 } 664 665 BNode node(&fCurrentRef); 666 667 status_t status = fCurrent->SetBackgroundImage(&node); 668 if (status != B_OK) { 669 // TODO: this should be a BAlert! 670 printf("setting background image failed: %s\n", strerror(status)); 671 } 672 } 673 674 675 void 676 BackgroundsView::NotifyServer() 677 { 678 BMessenger tracker("application/x-vnd.Be-TRAK"); 679 680 if (fCurrent->IsDesktop()) { 681 tracker.SendMessage(new BMessage(B_RESTORE_BACKGROUND_IMAGE)); 682 } else { 683 int32 i = -1; 684 BMessage reply; 685 int32 err; 686 BEntry currentEntry(&fCurrentRef); 687 BPath currentPath(¤tEntry); 688 bool isCustomFolder = !fWorkspaceMenu->FindItem(kMsgDefaultFolder)->IsMarked(); 689 690 do { 691 BMessage msg(B_GET_PROPERTY); 692 i++; 693 694 // look at the "Poses" in every Tracker window 695 msg.AddSpecifier("Poses"); 696 msg.AddSpecifier("Window", i); 697 698 reply.MakeEmpty(); 699 tracker.SendMessage(&msg, &reply); 700 701 // break out of the loop when we're at the end of 702 // the windows 703 if (reply.what == B_MESSAGE_NOT_UNDERSTOOD 704 && reply.FindInt32("error", &err) == B_OK 705 && err == B_BAD_INDEX) 706 break; 707 708 // don't stop for windows that don't understand 709 // a request for "Poses"; they're not displaying 710 // folders 711 if (reply.what == B_MESSAGE_NOT_UNDERSTOOD 712 && reply.FindInt32("error", &err) == B_OK 713 && err != B_BAD_SCRIPT_SYNTAX) 714 continue; 715 716 BMessenger trackerWindow; 717 if (reply.FindMessenger("result", &trackerWindow) != B_OK) 718 continue; 719 720 if (isCustomFolder) { 721 // found a window with poses, ask for its path 722 msg.MakeEmpty(); 723 msg.what = B_GET_PROPERTY; 724 msg.AddSpecifier("Path"); 725 msg.AddSpecifier("Poses"); 726 msg.AddSpecifier("Window", i); 727 728 reply.MakeEmpty(); 729 tracker.SendMessage(&msg, &reply); 730 731 // go on with the next if this din't have a path 732 if (reply.what == B_MESSAGE_NOT_UNDERSTOOD) 733 continue; 734 735 entry_ref ref; 736 if (reply.FindRef("result", &ref) == B_OK) { 737 BEntry entry(&ref); 738 BPath path(&entry); 739 740 // these are not the paths you're looking for 741 if (currentPath != path) 742 continue; 743 } 744 } 745 746 trackerWindow.SendMessage(B_RESTORE_BACKGROUND_IMAGE); 747 } while (true); 748 } 749 } 750 751 752 int32 753 BackgroundsView::NotifyThread(void *data) 754 { 755 BackgroundsView *view = (BackgroundsView*)data; 756 757 view->NotifyServer(); 758 return B_OK; 759 } 760 761 762 void 763 BackgroundsView::SaveSettings(void) 764 { 765 BPath path; 766 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 767 path.Append(SETTINGS_FILE); 768 BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 769 770 BPoint point = Window()->Frame().LeftTop(); 771 if (fSettings.ReplacePoint("pos", point) != B_OK) 772 fSettings.AddPoint("pos", point); 773 774 entry_ref ref; 775 BEntry entry; 776 777 fPanel->GetPanelDirectory(&ref); 778 entry.SetTo(&ref); 779 entry.GetPath(&path); 780 if (fSettings.ReplaceString("paneldir", path.Path()) != B_OK) 781 fSettings.AddString("paneldir", path.Path()); 782 783 fFolderPanel->GetPanelDirectory(&ref); 784 entry.SetTo(&ref); 785 entry.GetPath(&path); 786 if (fSettings.ReplaceString("folderpaneldir", path.Path()) != B_OK) 787 fSettings.AddString("folderpaneldir", path.Path()); 788 789 fSettings.RemoveName("recentfolder"); 790 for (int32 i = 0; i < fPathList.CountItems(); i++) { 791 fSettings.AddString("recentfolder", fPathList.ItemAt(i)->Path()); 792 } 793 794 fSettings.Flatten(&file); 795 } 796 } 797 798 799 void 800 BackgroundsView::LoadSettings() 801 { 802 fSettings.MakeEmpty(); 803 804 BPath path; 805 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 806 return; 807 808 path.Append(SETTINGS_FILE); 809 BFile file(path.Path(), B_READ_ONLY); 810 if (file.InitCheck() != B_OK) 811 return; 812 813 if (fSettings.Unflatten(&file) != B_OK) { 814 printf("Error unflattening settings file %s\n", path.Path()); 815 return; 816 } 817 818 PRINT_OBJECT(fSettings); 819 820 BString string; 821 if (fSettings.FindString("paneldir", &string) == B_OK) 822 fPanel->SetPanelDirectory(string.String()); 823 824 if (fSettings.FindString("folderpaneldir", &string) == B_OK) 825 fFolderPanel->SetPanelDirectory(string.String()); 826 827 int32 index = 0; 828 while (fSettings.FindString("recentfolder", index, &string) == B_OK) { 829 if (index == 0) 830 fWorkspaceMenu->AddSeparatorItem(); 831 832 path.SetTo(string.String()); 833 int32 i = AddPath(path); 834 BString s; 835 s << "Folder: " << path.Leaf(); 836 BMenuItem *item = new BMenuItem(s.String(), 837 new BMessage(kMsgFolderSelected)); 838 fWorkspaceMenu->AddItem(item, -i - 1 + 6); 839 index++; 840 } 841 fWorkspaceMenu->SetTargetForItems(this); 842 843 PRINT(("Settings Loaded\n")); 844 } 845 846 847 void 848 BackgroundsView::WorkspaceActivated(uint32 oldWorkspaces, bool active) 849 { 850 UpdateWithCurrent(); 851 } 852 853 854 void 855 BackgroundsView::UpdatePreview() 856 { 857 bool imageEnabled = !(fImageMenu->FindItem(kMsgNoImage)->IsMarked()); 858 if (fPlacementMenu->IsEnabled() ^ imageEnabled) 859 fPlacementMenu->SetEnabled(imageEnabled); 860 if (fIconLabelOutline->IsEnabled() ^ imageEnabled) 861 fIconLabelOutline->SetEnabled(imageEnabled); 862 if (!imageEnabled) 863 fIconLabelOutline->SetValue(B_CONTROL_ON); 864 865 bool textEnabled = (fPlacementMenu->FindItem(kMsgManualPlacement)->IsMarked()) 866 && imageEnabled; 867 if (fXPlacementText->IsEnabled() ^ textEnabled) 868 fXPlacementText->SetEnabled(textEnabled); 869 if (fYPlacementText->IsEnabled() ^ textEnabled) 870 fYPlacementText->SetEnabled(textEnabled); 871 872 if (textEnabled && (strcmp(fXPlacementText->Text(), "") == 0)) { 873 fXPlacementText->SetText("0"); 874 fYPlacementText->SetText("0"); 875 } 876 if (!textEnabled) { 877 fXPlacementText->SetText(NULL); 878 fYPlacementText->SetText(NULL); 879 } 880 881 fXPlacementText->TextView()->MakeSelectable(textEnabled); 882 fYPlacementText->TextView()->MakeSelectable(textEnabled); 883 fXPlacementText->TextView()->MakeEditable(textEnabled); 884 fYPlacementText->TextView()->MakeEditable(textEnabled); 885 886 fPreView->ClearViewBitmap(); 887 888 int32 index = ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex(); 889 if (index >= 0) { 890 BBitmap *bitmap = GetImage(index)->GetBitmap(); 891 if (bitmap) { 892 BackgroundImage::BackgroundImageInfo *info = 893 new BackgroundImage::BackgroundImageInfo(0, index, 894 FindPlacementMode(), BPoint(atoi(fXPlacementText->Text()), 895 atoi(fYPlacementText->Text())), 896 fIconLabelOutline->Value() == B_CONTROL_ON, 0, 0); 897 if (info->fMode == BackgroundImage::kAtOffset) { 898 fPreView->SetEnabled(true); 899 fPreView->fPoint.x = atoi(fXPlacementText->Text()); 900 fPreView->fPoint.y = atoi(fYPlacementText->Text()); 901 } else 902 fPreView->SetEnabled(false); 903 904 fPreView->fImageBounds = BRect(bitmap->Bounds()); 905 fCurrent->Show(info, fPreView); 906 } 907 } else 908 fPreView->SetEnabled(false); 909 910 fPreView->SetViewColor(fPicker->ValueAsColor()); 911 fPreView->Invalidate(); 912 } 913 914 915 BackgroundImage::Mode 916 BackgroundsView::FindPlacementMode() 917 { 918 BackgroundImage::Mode mode = BackgroundImage::kAtOffset; 919 920 if (fPlacementMenu->FindItem(kMsgCenterPlacement)->IsMarked()) 921 mode = BackgroundImage::kCentered; 922 if (fPlacementMenu->FindItem(kMsgScalePlacement)->IsMarked()) 923 mode = BackgroundImage::kScaledToFit; 924 if (fPlacementMenu->FindItem(kMsgManualPlacement)->IsMarked()) 925 mode = BackgroundImage::kAtOffset; 926 if (fPlacementMenu->FindItem(kMsgTilePlacement)->IsMarked()) 927 mode = BackgroundImage::kTiled; 928 929 return mode; 930 } 931 932 933 #ifndef __HAIKU__ 934 inline bool operator!=(const rgb_color& x, const rgb_color& y) 935 { 936 return (x.red != y.red || x.blue != y.blue || x.green != y.green); 937 } 938 #endif 939 940 941 void 942 BackgroundsView::UpdateButtons() 943 { 944 bool hasChanged = false; 945 if (fPicker->IsEnabled() 946 && fPicker->ValueAsColor() != BScreen().DesktopColor()) { 947 hasChanged = true; 948 } else if (fCurrentInfo) { 949 if ((fIconLabelOutline->Value() == B_CONTROL_ON) ^ 950 fCurrentInfo->fTextWidgetLabelOutline) { 951 hasChanged = true; 952 } else if (FindPlacementMode() != fCurrentInfo->fMode) { 953 hasChanged = true; 954 } else if (fCurrentInfo->fImageIndex != 955 ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex()) { 956 hasChanged = true; 957 } else if (fCurrent->IsDesktop() 958 && ((fCurrentInfo->fWorkspace != B_ALL_WORKSPACES) 959 ^ (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()))) { 960 hasChanged = true; 961 } else if (fCurrentInfo->fMode == BackgroundImage::kAtOffset) { 962 BString oldString, newString; 963 oldString << (int)fCurrentInfo->fOffset.x; 964 if (oldString != BString(fXPlacementText->Text())) { 965 hasChanged = true; 966 } 967 oldString = ""; 968 oldString << (int)fCurrentInfo->fOffset.y; 969 if (oldString != BString(fYPlacementText->Text())) { 970 hasChanged = true; 971 } 972 } 973 } else if (fImageMenu->IndexOf(fImageMenu->FindMarked()) > 0) { 974 hasChanged = true; 975 } 976 977 fApply->SetEnabled(hasChanged); 978 fRevert->SetEnabled(hasChanged); 979 } 980 981 982 void 983 BackgroundsView::RefsReceived(BMessage *msg) 984 { 985 entry_ref ref; 986 int32 i = 0; 987 BMimeType imageType("image"); 988 BPath desktopPath; 989 find_directory(B_DESKTOP_DIRECTORY, &desktopPath); 990 991 while (msg->FindRef("refs", i++, &ref) == B_OK) { 992 BPath path; 993 BEntry entry(&ref, true); 994 path.SetTo(&entry); 995 BNode node(&entry); 996 997 if (node.IsFile()) { 998 BMimeType refType; 999 BMimeType::GuessMimeType(&ref, &refType); 1000 if (!imageType.Contains(&refType)) 1001 continue; 1002 1003 BGImageMenuItem *item; 1004 int32 index = AddImage(path); 1005 if (index >= 0) { 1006 item = FindImageItem(index); 1007 fLastImageIndex = index; 1008 } else { 1009 const char* name = GetImage(-index - 1)->GetName(); 1010 item = new BGImageMenuItem(name, -index - 1, 1011 new BMessage(kMsgImageSelected)); 1012 AddItem(item); 1013 item->SetTarget(this); 1014 fLastImageIndex = -index - 1; 1015 } 1016 1017 item->SetMarked(true); 1018 BMessenger(this).SendMessage(kMsgImageSelected); 1019 } else if (node.IsDirectory()) { 1020 if (desktopPath == path) { 1021 fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->SetMarked(true); 1022 BMessenger(this).SendMessage(kMsgCurrentWorkspace); 1023 break; 1024 } 1025 BMenuItem *item; 1026 int32 index = AddPath(path); 1027 if (index >= 0) { 1028 item = fWorkspaceMenu->ItemAt(index + 6); 1029 fLastWorkspaceIndex = index + 6; 1030 } else { 1031 if (fWorkspaceMenu->CountItems() <= 5) 1032 fWorkspaceMenu->AddSeparatorItem(); 1033 BString s; 1034 s << "Folder: " << path.Leaf(); 1035 item = new BMenuItem(s.String(), new BMessage(kMsgFolderSelected)); 1036 fWorkspaceMenu->AddItem(item, -index - 1 + 6); 1037 item->SetTarget(this); 1038 fLastWorkspaceIndex = -index - 1 + 6; 1039 } 1040 1041 item->SetMarked(true); 1042 BMessenger(this).SendMessage(kMsgFolderSelected); 1043 } 1044 } 1045 } 1046 1047 1048 int32 1049 BackgroundsView::AddPath(BPath path) 1050 { 1051 int32 count = fPathList.CountItems(); 1052 int32 index = 0; 1053 for (; index < count; index++) { 1054 BPath *p = fPathList.ItemAt(index); 1055 int c = BString(p->Path()).ICompare(path.Path()); 1056 if (c == 0) 1057 return index; 1058 1059 if (c > 0) 1060 break; 1061 } 1062 fPathList.AddItem(new BPath(path), index); 1063 return -index - 1; 1064 } 1065 1066 1067 int32 1068 BackgroundsView::AddImage(BPath path) 1069 { 1070 int32 count = fImageList.CountItems(); 1071 int32 index = 0; 1072 for (; index < count; index++) { 1073 Image *image = fImageList.ItemAt(index); 1074 if (image->GetPath() == path) 1075 return index; 1076 } 1077 1078 fImageList.AddItem(new Image(path)); 1079 return -index - 1; 1080 } 1081 1082 1083 void 1084 BackgroundsView::ProcessRefs(entry_ref dir, BMessage* refs) 1085 { 1086 fWorkspaceMenu->FindItem(kMsgDefaultFolder)->SetMarked(true); 1087 BMessenger messenger(this); 1088 messenger.SendMessage(kMsgDefaultFolder); 1089 1090 if (refs->CountNames(B_REF_TYPE) > 0) { 1091 messenger.SendMessage(refs); 1092 } else { 1093 BMessage message(B_REFS_RECEIVED); 1094 message.AddRef("refs", &dir); 1095 messenger.SendMessage(&message); 1096 } 1097 } 1098 1099 1100 Image* 1101 BackgroundsView::GetImage(int32 imageIndex) 1102 { 1103 return fImageList.ItemAt(imageIndex); 1104 } 1105 1106 1107 BGImageMenuItem* 1108 BackgroundsView::FindImageItem(const int32 imageIndex) 1109 { 1110 if (imageIndex < 0) 1111 return (BGImageMenuItem *)fImageMenu->ItemAt(0); 1112 1113 int32 count = fImageMenu->CountItems() - 2; 1114 int32 index = 2; 1115 for (; index < count; index++) { 1116 BGImageMenuItem *image = (BGImageMenuItem *)fImageMenu->ItemAt(index); 1117 if (image->ImageIndex() == imageIndex) 1118 return image; 1119 } 1120 return NULL; 1121 } 1122 1123 1124 bool 1125 BackgroundsView::AddItem(BGImageMenuItem *item) 1126 { 1127 int32 count = fImageMenu->CountItems() - 2; 1128 int32 index = 2; 1129 if (count < index) { 1130 fImageMenu->AddItem(new BSeparatorItem(), 1); 1131 count = fImageMenu->CountItems() - 2; 1132 } 1133 1134 for (; index < count; index++) { 1135 BGImageMenuItem* image = (BGImageMenuItem *)fImageMenu->ItemAt(index); 1136 int c = (BString(image->Label()).ICompare(BString(item->Label()))); 1137 if (c > 0) 1138 break; 1139 } 1140 return fImageMenu->AddItem(item, index); 1141 } 1142 1143 1144 // #pragma mark - 1145 1146 1147 PreView::PreView(BRect frame, const char *name, int32 resize, int32 flags) 1148 : BControl(frame, name, NULL, NULL, resize, flags), 1149 fMoveHandCursor(kHandCursorData) 1150 { 1151 } 1152 1153 1154 void 1155 PreView::AttachedToWindow() 1156 { 1157 rgb_color color = ViewColor(); 1158 BControl::AttachedToWindow(); 1159 SetViewColor(color); 1160 } 1161 1162 1163 void 1164 PreView::MouseDown(BPoint point) 1165 { 1166 if (IsEnabled() && Bounds().Contains(point)) { 1167 uint32 buttons; 1168 GetMouse(&point, &buttons); 1169 if (buttons & B_PRIMARY_MOUSE_BUTTON) { 1170 fOldPoint = point; 1171 SetTracking(true); 1172 BScreen().GetMode(&mode); 1173 x_ratio = Bounds().Width() / mode.virtual_width; 1174 y_ratio = Bounds().Height() / mode.virtual_height; 1175 SetMouseEventMask(B_POINTER_EVENTS, 1176 B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); 1177 } 1178 } 1179 } 1180 1181 1182 void 1183 PreView::MouseUp(BPoint point) 1184 { 1185 if (IsTracking()) 1186 SetTracking(false); 1187 } 1188 1189 1190 void 1191 PreView::MouseMoved(BPoint point, uint32 transit, const BMessage *message) 1192 { 1193 if (IsEnabled()) 1194 SetViewCursor(&fMoveHandCursor); 1195 else 1196 SetViewCursor(B_CURSOR_SYSTEM_DEFAULT); 1197 1198 if (IsTracking()) { 1199 float x, y; 1200 x = fPoint.x + (point.x - fOldPoint.x) / x_ratio; 1201 y = fPoint.y + (point.y - fOldPoint.y) / y_ratio; 1202 bool min, max, mustSend = false; 1203 min = (x > -fImageBounds.Width()); 1204 max = (x < mode.virtual_width); 1205 if (min && max) { 1206 fOldPoint.x = point.x; 1207 fPoint.x = x; 1208 mustSend = true; 1209 } else { 1210 if (!min && fPoint.x > -fImageBounds.Width()) { 1211 fPoint.x = -fImageBounds.Width(); 1212 fOldPoint.x = point.x - (x - fPoint.x) * x_ratio; 1213 mustSend = true; 1214 } 1215 if (!max && fPoint.x < mode.virtual_width) { 1216 fPoint.x = mode.virtual_width; 1217 fOldPoint.x = point.x - (x - fPoint.x) * x_ratio; 1218 mustSend = true; 1219 } 1220 } 1221 1222 min = (y > -fImageBounds.Height()); 1223 max = (y < mode.virtual_height); 1224 if (min && max) { 1225 fOldPoint.y = point.y; 1226 fPoint.y = y; 1227 mustSend = true; 1228 } else { 1229 if (!min && fPoint.y > -fImageBounds.Height()) { 1230 fPoint.y = -fImageBounds.Height(); 1231 fOldPoint.y = point.y - (y - fPoint.y) * y_ratio; 1232 mustSend = true; 1233 } 1234 if (!max && fPoint.y < mode.virtual_height) { 1235 fPoint.y = mode.virtual_height; 1236 fOldPoint.y = point.y - (y - fPoint.y) * y_ratio; 1237 mustSend = true; 1238 } 1239 } 1240 1241 if (mustSend) { 1242 BMessenger messenger(Parent()); 1243 messenger.SendMessage(kMsgUpdatePreviewPlacement); 1244 } 1245 } 1246 BControl::MouseMoved(point, transit, message); 1247 } 1248 1249 1250 // #pragma mark - 1251 1252 1253 PreviewBox::PreviewBox(BRect frame, const char *name) 1254 : BBox(frame, name) 1255 { 1256 fIsDesktop = true; 1257 } 1258 1259 1260 void 1261 PreviewBox::Draw(BRect rect) 1262 { 1263 // TODO: make view size dependent! 1264 rgb_color color = HighColor(); 1265 1266 SetHighColor(LowColor()); 1267 FillRect(BRect(9, 19, 141, 127)); 1268 1269 if (fIsDesktop) { 1270 BPoint points[] = { 1271 BPoint(11, 19), BPoint(139, 19), BPoint(141, 21), 1272 BPoint(141, 119), BPoint(139, 121), BPoint(118, 121), 1273 BPoint(118, 126), BPoint(117, 127), BPoint(33, 127), 1274 BPoint(32, 126), BPoint(32, 121), BPoint(11, 121), 1275 BPoint(9, 119), BPoint(9, 21), BPoint(11, 19) 1276 }; 1277 SetHighColor(184, 184, 184); 1278 FillPolygon(points, 15); 1279 SetHighColor(96, 96, 96); 1280 StrokePolygon(points, 15); 1281 FillRect(BRect(107, 121, 111, 123)); 1282 SetHighColor(0, 0, 0); 1283 StrokeRect(BRect(14, 24, 136, 116)); 1284 SetHighColor(0, 255, 0); 1285 FillRect(BRect(101, 122, 103, 123)); 1286 } else { 1287 SetHighColor(152, 152, 152); 1288 StrokeLine(BPoint(11, 13), BPoint(67, 13)); 1289 StrokeLine(BPoint(67, 21)); 1290 StrokeLine(BPoint(139, 21)); 1291 StrokeLine(BPoint(139, 119)); 1292 StrokeLine(BPoint(11, 119)); 1293 StrokeLine(BPoint(11, 13)); 1294 StrokeRect(BRect(14, 24, 136, 116)); 1295 SetHighColor(255, 203, 0); 1296 FillRect(BRect(12, 14, 66, 21)); 1297 SetHighColor(240, 240, 240); 1298 StrokeRect(BRect(12, 22, 137, 117)); 1299 StrokeLine(BPoint(138, 22), BPoint(138, 22)); 1300 StrokeLine(BPoint(12, 118), BPoint(12, 118)); 1301 SetHighColor(200, 200, 200); 1302 StrokeRect(BRect(13, 23, 138, 118)); 1303 } 1304 1305 SetHighColor(color); 1306 BBox::Draw(rect); 1307 } 1308 1309 1310 void 1311 PreviewBox::SetDesktop(bool isDesktop) 1312 { 1313 fIsDesktop = isDesktop; 1314 Invalidate(); 1315 } 1316 1317 1318 // #pragma mark - 1319 1320 1321 BGImageMenuItem::BGImageMenuItem(const char *label, int32 imageIndex, 1322 BMessage *message, char shortcut, uint32 modifiers) 1323 : BMenuItem(label, message, shortcut, modifiers), 1324 fImageIndex(imageIndex) 1325 { 1326 } 1327