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