1 /* 2 * Copyright 2002-2015 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Jerome Duval, jerome.duval@free.fr 8 * Jonas Sundström, jonas@kirilla.se 9 * John Scipione, jscipione@gmail.com 10 */ 11 12 13 #include "BackgroundsView.h" 14 15 #include <algorithm> 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 20 #include <Bitmap.h> 21 #include <Catalog.h> 22 #include <ControlLook.h> 23 #include <Cursor.h> 24 #include <Debug.h> 25 #include <File.h> 26 #include <FindDirectory.h> 27 #include <LayoutBuilder.h> 28 #include <Locale.h> 29 #include <MenuField.h> 30 #include <Messenger.h> 31 #include <MimeType.h> 32 #include <Point.h> 33 #include <PopUpMenu.h> 34 35 #include <be_apps/Tracker/Background.h> 36 37 #include "ImageFilePanel.h" 38 39 40 #undef B_TRANSLATION_CONTEXT 41 #define B_TRANSLATION_CONTEXT "Main View" 42 43 44 static const uint32 kMsgApplySettings = 'aply'; 45 static const uint32 kMsgRevertSettings = 'rvrt'; 46 47 static const uint32 kMsgUpdateColor = 'upcl'; 48 static const uint32 kMsgAllWorkspaces = 'alwk'; 49 static const uint32 kMsgCurrentWorkspace = 'crwk'; 50 static const uint32 kMsgDefaultFolder = 'dffl'; 51 static const uint32 kMsgOtherFolder = 'otfl'; 52 static const uint32 kMsgNoImage = 'noim'; 53 static const uint32 kMsgOtherImage = 'otim'; 54 static const uint32 kMsgImageSelected = 'imsl'; 55 static const uint32 kMsgFolderSelected = 'flsl'; 56 57 static const uint32 kMsgCenterPlacement = 'cnpl'; 58 static const uint32 kMsgManualPlacement = 'mnpl'; 59 static const uint32 kMsgScalePlacement = 'scpl'; 60 static const uint32 kMsgTilePlacement = 'tlpl'; 61 static const uint32 kMsgIconLabelOutline = 'ilol'; 62 63 static const uint32 kMsgImagePlacement = 'xypl'; 64 static const uint32 kMsgUpdatePreviewPlacement = 'pvpl'; 65 66 67 BackgroundsView::BackgroundsView() 68 : 69 BBox("BackgroundsView"), 70 fCurrent(NULL), 71 fCurrentInfo(NULL), 72 fLastImageIndex(-1), 73 fPathList(1, true), 74 fImageList(1, true), 75 fFoundPositionSetting(false) 76 { 77 SetBorder(B_NO_BORDER); 78 79 BBox* previewBox = new BBox("preview"); 80 previewBox->SetLabel(B_TRANSLATE("Preview")); 81 82 fPreview = new Preview(); 83 84 fTopLeft = new FramePart(FRAME_TOP_LEFT); 85 fTop = new FramePart(FRAME_TOP); 86 fTopRight = new FramePart(FRAME_TOP_RIGHT); 87 fLeft = new FramePart(FRAME_LEFT_SIDE); 88 fRight = new FramePart(FRAME_RIGHT_SIDE); 89 fBottomLeft = new FramePart(FRAME_BOTTOM_LEFT); 90 fBottom = new FramePart(FRAME_BOTTOM); 91 fBottomRight = new FramePart(FRAME_BOTTOM_RIGHT); 92 93 fXPlacementText = new BTextControl(B_TRANSLATE("X:"), NULL, 94 new BMessage(kMsgImagePlacement)); 95 fYPlacementText = new BTextControl(B_TRANSLATE("Y:"), NULL, 96 new BMessage(kMsgImagePlacement)); 97 98 fXPlacementText->TextView()->SetMaxBytes(5); 99 fYPlacementText->TextView()->SetMaxBytes(5); 100 101 for (int32 i = 0; i < 256; i++) { 102 if ((i < '0' || i > '9') && i != '-') { 103 fXPlacementText->TextView()->DisallowChar(i); 104 fYPlacementText->TextView()->DisallowChar(i); 105 } 106 } 107 108 previewBox->AddChild(BLayoutBuilder::Group<>() 109 .AddGlue() 110 .AddGroup(B_VERTICAL, 0) 111 .AddGroup(B_HORIZONTAL, 0) 112 .AddGlue() 113 .AddGrid(0, 0, 1) 114 .Add(fTopLeft, 0, 0) 115 .Add(fTop, 1, 0) 116 .Add(fTopRight, 2, 0) 117 .Add(fLeft, 0, 1) 118 .Add(fPreview, 1, 1) 119 .Add(fRight, 2, 1) 120 .Add(fBottomLeft, 0, 2) 121 .Add(fBottom, 1, 2) 122 .Add(fBottomRight, 2, 2) 123 .End() 124 .AddGlue() 125 .End() 126 .AddStrut(be_control_look->DefaultItemSpacing() * 2) 127 .AddGroup(B_HORIZONTAL) 128 .Add(fXPlacementText) 129 .Add(fYPlacementText) 130 .End() 131 .AddGlue() 132 .SetInsets(B_USE_DEFAULT_SPACING) 133 .End() 134 .AddGlue() 135 .View()); 136 137 BBox* rightbox = new BBox("rightbox"); 138 139 fWorkspaceMenu = new BPopUpMenu(B_TRANSLATE("pick one")); 140 fWorkspaceMenu->AddItem(new BMenuItem(B_TRANSLATE("All workspaces"), 141 new BMessage(kMsgAllWorkspaces))); 142 BMenuItem* menuItem; 143 fWorkspaceMenu->AddItem(menuItem = new BMenuItem( 144 B_TRANSLATE("Current workspace"), 145 new BMessage(kMsgCurrentWorkspace))); 146 menuItem->SetMarked(true); 147 fLastWorkspaceIndex = 148 fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked()); 149 fWorkspaceMenu->AddSeparatorItem(); 150 fWorkspaceMenu->AddItem(new BMenuItem(B_TRANSLATE("Default folder"), 151 new BMessage(kMsgDefaultFolder))); 152 fWorkspaceMenu->AddItem(new BMenuItem( 153 B_TRANSLATE("Other folder" B_UTF8_ELLIPSIS), 154 new BMessage(kMsgOtherFolder))); 155 156 BMenuField* workspaceMenuField = new BMenuField("workspaceMenuField", 157 NULL, fWorkspaceMenu); 158 workspaceMenuField->ResizeToPreferred(); 159 rightbox->SetLabel(workspaceMenuField); 160 161 fImageMenu = new BPopUpMenu(B_TRANSLATE("pick one")); 162 fImageMenu->AddItem(new BGImageMenuItem(B_TRANSLATE("None"), -1, 163 new BMessage(kMsgNoImage))); 164 fImageMenu->AddSeparatorItem(); 165 fImageMenu->AddItem(new BMenuItem(B_TRANSLATE("Other" B_UTF8_ELLIPSIS), 166 new BMessage(kMsgOtherImage))); 167 168 BMenuField* imageMenuField = new BMenuField("image", 169 B_TRANSLATE("Image:"), fImageMenu); 170 imageMenuField->SetAlignment(B_ALIGN_RIGHT); 171 172 fPlacementMenu = new BPopUpMenu(B_TRANSLATE("pick one")); 173 fPlacementMenu->AddItem(new BMenuItem(B_TRANSLATE("Manual"), 174 new BMessage(kMsgManualPlacement))); 175 fPlacementMenu->AddItem(new BMenuItem(B_TRANSLATE("Center"), 176 new BMessage(kMsgCenterPlacement))); 177 fPlacementMenu->AddItem(new BMenuItem(B_TRANSLATE("Scale to fit"), 178 new BMessage(kMsgScalePlacement))); 179 fPlacementMenu->AddItem(new BMenuItem(B_TRANSLATE("Tile"), 180 new BMessage(kMsgTilePlacement))); 181 182 BMenuField* placementMenuField = new BMenuField("placement", 183 B_TRANSLATE("Placement:"), fPlacementMenu); 184 placementMenuField->SetAlignment(B_ALIGN_RIGHT); 185 186 fIconLabelOutline = new BCheckBox(B_TRANSLATE("Icon label outline"), 187 new BMessage(kMsgIconLabelOutline)); 188 fIconLabelOutline->SetValue(B_CONTROL_OFF); 189 190 fPicker = new BColorControl(BPoint(0, 0), B_CELLS_32x8, 8.0, "Picker", 191 new BMessage(kMsgUpdateColor)); 192 193 rightbox->AddChild(BLayoutBuilder::Group<>(B_VERTICAL) 194 .AddGroup(B_HORIZONTAL, 0.0f) 195 .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 196 .Add(imageMenuField->CreateLabelLayoutItem(), 0, 0) 197 .AddGroup(B_HORIZONTAL, 0.0f, 1, 0) 198 .Add(imageMenuField->CreateMenuBarLayoutItem(), 0.0f) 199 .AddGlue() 200 .End() 201 .Add(placementMenuField->CreateLabelLayoutItem(), 0, 1) 202 .AddGroup(B_HORIZONTAL, 0.0f, 1, 1) 203 .Add(placementMenuField->CreateMenuBarLayoutItem(), 0.0f) 204 .AddGlue() 205 .End() 206 .Add(fIconLabelOutline, 1, 2) 207 .End() 208 .AddGlue() 209 .End() 210 .AddGlue() 211 .Add(fPicker) 212 .SetInsets(B_USE_DEFAULT_SPACING) 213 .View()); 214 215 fRevert = new BButton(B_TRANSLATE("Revert"), 216 new BMessage(kMsgRevertSettings)); 217 fApply = new BButton(B_TRANSLATE("Apply"), 218 new BMessage(kMsgApplySettings)); 219 220 fRevert->SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, 221 B_ALIGN_NO_VERTICAL)); 222 fApply->SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, 223 B_ALIGN_NO_VERTICAL)); 224 225 BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 226 .SetInsets(B_USE_WINDOW_SPACING) 227 .AddGroup(B_HORIZONTAL, 0) 228 .AddGroup(B_VERTICAL, 0) 229 .AddStrut(floorf(rightbox->TopBorderOffset() 230 - previewBox->TopBorderOffset()) - 1) 231 .Add(previewBox) 232 .End() 233 .AddStrut(B_USE_DEFAULT_SPACING) 234 .Add(rightbox) 235 .End() 236 .AddGroup(B_HORIZONTAL, 0) 237 .Add(fRevert) 238 .Add(fApply) 239 .SetInsets(0, B_USE_DEFAULT_SPACING, 0, 0) 240 .End(); 241 242 fApply->MakeDefault(true); 243 } 244 245 246 BackgroundsView::~BackgroundsView() 247 { 248 // The order matter. The last panel saves the state 249 delete fFolderPanel; 250 delete fPanel; 251 } 252 253 254 void 255 BackgroundsView::AllAttached() 256 { 257 fPlacementMenu->SetTargetForItems(this); 258 fImageMenu->SetTargetForItems(this); 259 fWorkspaceMenu->SetTargetForItems(this); 260 fXPlacementText->SetTarget(this); 261 fYPlacementText->SetTarget(this); 262 fIconLabelOutline->SetTarget(this); 263 fPicker->SetTarget(this); 264 fApply->SetTarget(this); 265 fRevert->SetTarget(this); 266 267 BPath path; 268 entry_ref ref; 269 if (find_directory(B_SYSTEM_DATA_DIRECTORY, &path) == B_OK) { 270 path.Append("artwork"); 271 get_ref_for_path(path.Path(), &ref); 272 } 273 274 BMessenger messenger(this); 275 fPanel = new ImageFilePanel(B_OPEN_PANEL, &messenger, &ref, 276 B_FILE_NODE, false, NULL, new CustomRefFilter(true)); 277 fPanel->SetButtonLabel(B_DEFAULT_BUTTON, B_TRANSLATE("Select")); 278 279 fFolderPanel = new BFilePanel(B_OPEN_PANEL, &messenger, NULL, 280 B_DIRECTORY_NODE, false, NULL, new CustomRefFilter(false)); 281 fFolderPanel->SetButtonLabel(B_DEFAULT_BUTTON, B_TRANSLATE("Select")); 282 283 _LoadSettings(); 284 _LoadDesktopFolder(); 285 286 BPoint point; 287 if (fSettings.FindPoint("pos", &point) == B_OK) { 288 fFoundPositionSetting = true; 289 Window()->MoveTo(point); 290 } 291 292 fApply->SetEnabled(false); 293 fRevert->SetEnabled(false); 294 } 295 296 297 void 298 BackgroundsView::MessageReceived(BMessage* message) 299 { 300 // Color drop 301 if (message->WasDropped()) { 302 rgb_color *clr; 303 ssize_t out_size; 304 if (message->FindData("RGBColor", B_RGB_COLOR_TYPE, 305 (const void **)&clr, &out_size) == B_OK) { 306 fPicker->SetValue(*clr); 307 _UpdatePreview(); 308 _UpdateButtons(); 309 return; 310 } 311 } 312 313 switch (message->what) { 314 case B_SIMPLE_DATA: 315 case B_REFS_RECEIVED: 316 RefsReceived(message); 317 break; 318 319 case kMsgUpdatePreviewPlacement: 320 { 321 BString xstring, ystring; 322 xstring << (int)fPreview->fPoint.x; 323 ystring << (int)fPreview->fPoint.y; 324 fXPlacementText->SetText(xstring.String()); 325 fYPlacementText->SetText(ystring.String()); 326 _UpdatePreview(); 327 _UpdateButtons(); 328 break; 329 } 330 331 case kMsgManualPlacement: 332 case kMsgTilePlacement: 333 case kMsgScalePlacement: 334 case kMsgCenterPlacement: 335 _UpdatePreview(); 336 _UpdateButtons(); 337 break; 338 339 case kMsgIconLabelOutline: 340 _UpdateButtons(); 341 break; 342 343 case kMsgUpdateColor: 344 case kMsgImagePlacement: 345 _UpdatePreview(); 346 _UpdateButtons(); 347 break; 348 349 case kMsgCurrentWorkspace: 350 case kMsgAllWorkspaces: 351 fImageMenu->FindItem(kMsgNoImage)->SetLabel(B_TRANSLATE("None")); 352 fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( 353 fWorkspaceMenu->FindMarked()); 354 if (fCurrent && fCurrent->IsDesktop()) { 355 _UpdateButtons(); 356 } else { 357 _SetDesktop(true); 358 _LoadDesktopFolder(); 359 } 360 break; 361 362 case kMsgDefaultFolder: 363 fImageMenu->FindItem(kMsgNoImage)->SetLabel(B_TRANSLATE("None")); 364 fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( 365 fWorkspaceMenu->FindMarked()); 366 _SetDesktop(false); 367 _LoadDefaultFolder(); 368 break; 369 370 case kMsgOtherFolder: 371 fFolderPanel->Show(); 372 break; 373 374 case kMsgOtherImage: 375 fPanel->Show(); 376 break; 377 378 case B_CANCEL: 379 { 380 PRINT(("cancel received\n")); 381 void* pointer; 382 message->FindPointer("source", &pointer); 383 if (pointer == fPanel) { 384 if (fLastImageIndex >= 0) 385 _FindImageItem(fLastImageIndex)->SetMarked(true); 386 else 387 fImageMenu->ItemAt(0)->SetMarked(true); 388 } else if (pointer == fFolderPanel) { 389 if (fLastWorkspaceIndex >= 0) 390 fWorkspaceMenu->ItemAt(fLastWorkspaceIndex) 391 ->SetMarked(true); 392 } 393 break; 394 } 395 396 case kMsgImageSelected: 397 case kMsgNoImage: 398 fLastImageIndex = ((BGImageMenuItem*)fImageMenu->FindMarked()) 399 ->ImageIndex(); 400 _UpdatePreview(); 401 _UpdateButtons(); 402 break; 403 404 case kMsgFolderSelected: 405 fImageMenu->FindItem(kMsgNoImage)->SetLabel(B_TRANSLATE("Default")); 406 fLastWorkspaceIndex = fWorkspaceMenu->IndexOf( 407 fWorkspaceMenu->FindMarked()); 408 _SetDesktop(false); 409 410 _LoadRecentFolder(*fPathList.ItemAt(fWorkspaceMenu->IndexOf( 411 fWorkspaceMenu->FindMarked()) - 6)); 412 break; 413 414 case kMsgApplySettings: 415 { 416 _Save(); 417 418 //_NotifyServer(); 419 thread_id notify_thread; 420 notify_thread = spawn_thread(BackgroundsView::_NotifyThread, 421 "notifyServer", B_NORMAL_PRIORITY, this); 422 resume_thread(notify_thread); 423 _UpdateButtons(); 424 break; 425 } 426 case kMsgRevertSettings: 427 _UpdateWithCurrent(); 428 break; 429 430 default: 431 BView::MessageReceived(message); 432 break; 433 } 434 } 435 436 437 void 438 BackgroundsView::_LoadDesktopFolder() 439 { 440 BPath path; 441 if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) { 442 status_t err; 443 err = get_ref_for_path(path.Path(), &fCurrentRef); 444 if (err != B_OK) 445 printf("error in LoadDesktopSettings\n"); 446 _LoadFolder(true); 447 } 448 } 449 450 451 void 452 BackgroundsView::_LoadDefaultFolder() 453 { 454 BPath path; 455 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 456 BString pathString = path.Path(); 457 pathString << "/Tracker/DefaultFolderTemplate"; 458 status_t err; 459 err = get_ref_for_path(pathString.String(), &fCurrentRef); 460 if (err != B_OK) 461 printf("error in LoadDefaultFolderSettings\n"); 462 _LoadFolder(false); 463 } 464 } 465 466 467 void 468 BackgroundsView::_LoadRecentFolder(BPath path) 469 { 470 status_t err; 471 err = get_ref_for_path(path.Path(), &fCurrentRef); 472 if (err != B_OK) 473 printf("error in LoadRecentFolder\n"); 474 _LoadFolder(false); 475 } 476 477 478 void 479 BackgroundsView::_LoadFolder(bool isDesktop) 480 { 481 if (fCurrent) { 482 delete fCurrent; 483 fCurrent = NULL; 484 } 485 486 BNode node(&fCurrentRef); 487 if (node.InitCheck() == B_OK) 488 fCurrent = BackgroundImage::GetBackgroundImage(&node, isDesktop, this); 489 490 _UpdateWithCurrent(); 491 } 492 493 494 void 495 BackgroundsView::_UpdateWithCurrent(void) 496 { 497 if (fCurrent == NULL) 498 return; 499 500 fPlacementMenu->FindItem(kMsgScalePlacement) 501 ->SetEnabled(fCurrent->IsDesktop()); 502 fPlacementMenu->FindItem(kMsgCenterPlacement) 503 ->SetEnabled(fCurrent->IsDesktop()); 504 505 if (fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked()) > 5) 506 fImageMenu->FindItem(kMsgNoImage)->SetLabel(B_TRANSLATE("Default")); 507 else 508 fImageMenu->FindItem(kMsgNoImage)->SetLabel(B_TRANSLATE("None")); 509 510 for (int32 i = fImageMenu->CountItems() - 5; i >= 0; i--) { 511 fImageMenu->RemoveItem(2); 512 } 513 514 for (int32 i = fImageList.CountItems() - 1; i >= 0; i--) { 515 BMessage* message = new BMessage(kMsgImageSelected); 516 _AddItem(new BGImageMenuItem(GetImage(i)->GetName(), i, message)); 517 } 518 519 fImageMenu->SetTargetForItems(this); 520 521 fCurrentInfo = fCurrent->ImageInfoForWorkspace(current_workspace()); 522 523 if (!fCurrentInfo) { 524 fImageMenu->FindItem(kMsgNoImage)->SetMarked(true); 525 fPlacementMenu->FindItem(kMsgManualPlacement)->SetMarked(true); 526 fIconLabelOutline->SetValue(B_CONTROL_ON); 527 } else { 528 fIconLabelOutline->SetValue(fCurrentInfo->fTextWidgetLabelOutline 529 ? B_CONTROL_ON : B_CONTROL_OFF); 530 531 fLastImageIndex = fCurrentInfo->fImageIndex; 532 _FindImageItem(fLastImageIndex)->SetMarked(true); 533 534 if (fLastImageIndex > -1) { 535 536 BString xtext, ytext; 537 int32 cmd = 0; 538 switch (fCurrentInfo->fMode) { 539 case BackgroundImage::kCentered: 540 cmd = kMsgCenterPlacement; 541 break; 542 case BackgroundImage::kScaledToFit: 543 cmd = kMsgScalePlacement; 544 break; 545 case BackgroundImage::kAtOffset: 546 cmd = kMsgManualPlacement; 547 xtext << (int)fCurrentInfo->fOffset.x; 548 ytext << (int)fCurrentInfo->fOffset.y; 549 break; 550 case BackgroundImage::kTiled: 551 cmd = kMsgTilePlacement; 552 break; 553 } 554 555 if (cmd != 0) 556 fPlacementMenu->FindItem(cmd)->SetMarked(true); 557 558 fXPlacementText->SetText(xtext.String()); 559 fYPlacementText->SetText(ytext.String()); 560 } else { 561 fPlacementMenu->FindItem(kMsgManualPlacement)->SetMarked(true); 562 } 563 } 564 565 rgb_color color = {255, 255, 255, 255}; 566 if (fCurrent->IsDesktop()) { 567 color = BScreen().DesktopColor(); 568 fPicker->SetEnabled(true); 569 } else 570 fPicker->SetEnabled(false); 571 572 fPicker->SetValue(color); 573 574 _UpdatePreview(); 575 _UpdateButtons(); 576 } 577 578 579 void 580 BackgroundsView::_Save() 581 { 582 bool textWidgetLabelOutline 583 = fIconLabelOutline->Value() == B_CONTROL_ON; 584 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( 591 B_ALL_WORKSPACES, fLastImageIndex, mode, offset, 592 textWidgetLabelOutline, 0, 0); 593 fCurrent->Add(fCurrentInfo); 594 } else { 595 fCurrentInfo->fTextWidgetLabelOutline = textWidgetLabelOutline; 596 fCurrentInfo->fMode = mode; 597 if (fCurrentInfo->fMode == BackgroundImage::kAtOffset) 598 fCurrentInfo->fOffset = offset; 599 fCurrentInfo->fImageIndex = fLastImageIndex; 600 } 601 } else { 602 uint32 workspaceMask = 1; 603 int32 workspace = current_workspace(); 604 for (; workspace; workspace--) 605 workspaceMask *= 2; 606 607 if (fCurrentInfo != NULL) { 608 if (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) { 609 if (fCurrentInfo->fWorkspace & workspaceMask 610 && fCurrentInfo->fWorkspace != workspaceMask) { 611 fCurrentInfo->fWorkspace = fCurrentInfo->fWorkspace 612 ^ workspaceMask; 613 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 614 workspaceMask, fLastImageIndex, mode, offset, 615 textWidgetLabelOutline, fCurrentInfo->fImageSet, 616 fCurrentInfo->fCacheMode); 617 fCurrent->Add(fCurrentInfo); 618 } else if (fCurrentInfo->fWorkspace == workspaceMask) { 619 fCurrentInfo->fTextWidgetLabelOutline 620 = textWidgetLabelOutline; 621 fCurrentInfo->fMode = mode; 622 if (fCurrentInfo->fMode == BackgroundImage::kAtOffset) 623 fCurrentInfo->fOffset = offset; 624 625 fCurrentInfo->fImageIndex = fLastImageIndex; 626 } 627 } else { 628 fCurrent->RemoveAll(); 629 630 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 631 B_ALL_WORKSPACES, fLastImageIndex, mode, offset, 632 textWidgetLabelOutline, fCurrent->GetShowingImageSet(), 633 fCurrentInfo->fCacheMode); 634 fCurrent->Add(fCurrentInfo); 635 } 636 } else { 637 if (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) { 638 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 639 workspaceMask, fLastImageIndex, mode, offset, 640 textWidgetLabelOutline, fCurrent->GetShowingImageSet(), 0); 641 } else { 642 fCurrent->RemoveAll(); 643 fCurrentInfo = new BackgroundImage::BackgroundImageInfo( 644 B_ALL_WORKSPACES, fLastImageIndex, mode, offset, 645 textWidgetLabelOutline, fCurrent->GetShowingImageSet(), 0); 646 } 647 fCurrent->Add(fCurrentInfo); 648 } 649 650 if (!fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) { 651 for (int32 i = 0; i < count_workspaces(); i++) { 652 BScreen().SetDesktopColor(fPicker->ValueAsColor(), i, true); 653 } 654 } else 655 BScreen().SetDesktopColor(fPicker->ValueAsColor(), true); 656 } 657 658 BNode node(&fCurrentRef); 659 660 status_t status = fCurrent->SetBackgroundImage(&node); 661 if (status != B_OK) { 662 // TODO: this should be a BAlert! 663 printf("setting background image failed: %s\n", strerror(status)); 664 } 665 } 666 667 668 void 669 BackgroundsView::_NotifyServer() 670 { 671 BMessenger tracker("application/x-vnd.Be-TRAK"); 672 673 if (fCurrent->IsDesktop()) { 674 tracker.SendMessage(new BMessage(B_RESTORE_BACKGROUND_IMAGE)); 675 } else { 676 int32 i = -1; 677 BMessage reply; 678 int32 err; 679 BEntry currentEntry(&fCurrentRef); 680 BPath currentPath(¤tEntry); 681 bool isCustomFolder 682 = !fWorkspaceMenu->FindItem(kMsgDefaultFolder)->IsMarked(); 683 684 do { 685 BMessage msg(B_GET_PROPERTY); 686 i++; 687 688 // look at the "Poses" in every Tracker window 689 msg.AddSpecifier("Poses"); 690 msg.AddSpecifier("Window", i); 691 692 reply.MakeEmpty(); 693 tracker.SendMessage(&msg, &reply); 694 695 // break out of the loop when we're at the end of 696 // the windows 697 if (reply.what == B_MESSAGE_NOT_UNDERSTOOD 698 && reply.FindInt32("error", &err) == B_OK 699 && err == B_BAD_INDEX) 700 break; 701 702 // don't stop for windows that don't understand 703 // a request for "Poses"; they're not displaying 704 // folders 705 if (reply.what == B_MESSAGE_NOT_UNDERSTOOD 706 && reply.FindInt32("error", &err) == B_OK 707 && err != B_BAD_SCRIPT_SYNTAX) 708 continue; 709 710 BMessenger trackerWindow; 711 if (reply.FindMessenger("result", &trackerWindow) != B_OK) 712 continue; 713 714 if (isCustomFolder) { 715 // found a window with poses, ask for its path 716 msg.MakeEmpty(); 717 msg.what = B_GET_PROPERTY; 718 msg.AddSpecifier("Path"); 719 msg.AddSpecifier("Poses"); 720 msg.AddSpecifier("Window", i); 721 722 reply.MakeEmpty(); 723 tracker.SendMessage(&msg, &reply); 724 725 // go on with the next if this din't have a path 726 if (reply.what == B_MESSAGE_NOT_UNDERSTOOD) 727 continue; 728 729 entry_ref ref; 730 if (reply.FindRef("result", &ref) == B_OK) { 731 BEntry entry(&ref); 732 BPath path(&entry); 733 734 // these are not the paths you're looking for 735 if (currentPath != path) 736 continue; 737 } 738 } 739 740 trackerWindow.SendMessage(B_RESTORE_BACKGROUND_IMAGE); 741 } while (true); 742 } 743 } 744 745 746 int32 747 BackgroundsView::_NotifyThread(void* data) 748 { 749 BackgroundsView* view = (BackgroundsView*)data; 750 751 view->_NotifyServer(); 752 return B_OK; 753 } 754 755 756 void 757 BackgroundsView::SaveSettings(void) 758 { 759 BPath path; 760 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { 761 path.Append(SETTINGS_FILE); 762 BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); 763 764 BPoint point = Window()->Frame().LeftTop(); 765 if (fSettings.ReplacePoint("pos", point) != B_OK) 766 fSettings.AddPoint("pos", point); 767 768 entry_ref ref; 769 BEntry entry; 770 771 fPanel->GetPanelDirectory(&ref); 772 entry.SetTo(&ref); 773 entry.GetPath(&path); 774 if (fSettings.ReplaceString("paneldir", path.Path()) != B_OK) 775 fSettings.AddString("paneldir", path.Path()); 776 777 fFolderPanel->GetPanelDirectory(&ref); 778 entry.SetTo(&ref); 779 entry.GetPath(&path); 780 if (fSettings.ReplaceString("folderpaneldir", path.Path()) != B_OK) 781 fSettings.AddString("folderpaneldir", path.Path()); 782 783 fSettings.RemoveName("recentfolder"); 784 for (int32 i = 0; i < fPathList.CountItems(); i++) { 785 fSettings.AddString("recentfolder", fPathList.ItemAt(i)->Path()); 786 } 787 788 fSettings.Flatten(&file); 789 } 790 } 791 792 793 void 794 BackgroundsView::_LoadSettings() 795 { 796 fSettings.MakeEmpty(); 797 798 BPath path; 799 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 800 return; 801 802 path.Append(SETTINGS_FILE); 803 BFile file(path.Path(), B_READ_ONLY); 804 if (file.InitCheck() != B_OK) 805 return; 806 807 if (fSettings.Unflatten(&file) != B_OK) { 808 printf("Error unflattening settings file %s\n", path.Path()); 809 return; 810 } 811 812 PRINT_OBJECT(fSettings); 813 814 BString string; 815 if (fSettings.FindString("paneldir", &string) == B_OK) 816 fPanel->SetPanelDirectory(string.String()); 817 818 if (fSettings.FindString("folderpaneldir", &string) == B_OK) 819 fFolderPanel->SetPanelDirectory(string.String()); 820 821 int32 index = 0; 822 while (fSettings.FindString("recentfolder", index, &string) == B_OK) { 823 if (index == 0) 824 fWorkspaceMenu->AddSeparatorItem(); 825 826 path.SetTo(string.String()); 827 int32 i = _AddPath(path); 828 BString s; 829 s << B_TRANSLATE("Folder: ") << path.Leaf(); 830 BMenuItem* item = new BMenuItem(s.String(), 831 new BMessage(kMsgFolderSelected)); 832 fWorkspaceMenu->AddItem(item, -i - 1 + 6); 833 index++; 834 } 835 fWorkspaceMenu->SetTargetForItems(this); 836 837 PRINT(("Settings Loaded\n")); 838 } 839 840 841 void 842 BackgroundsView::WorkspaceActivated(uint32 oldWorkspaces, bool active) 843 { 844 _UpdateWithCurrent(); 845 } 846 847 848 void 849 BackgroundsView::_UpdatePreview() 850 { 851 bool imageEnabled = !(fImageMenu->FindItem(kMsgNoImage)->IsMarked()); 852 if (fPlacementMenu->IsEnabled() ^ imageEnabled) 853 fPlacementMenu->SetEnabled(imageEnabled); 854 855 bool textEnabled 856 = (fPlacementMenu->FindItem(kMsgManualPlacement)->IsMarked()) 857 && imageEnabled; 858 if (fXPlacementText->IsEnabled() ^ textEnabled) 859 fXPlacementText->SetEnabled(textEnabled); 860 if (fYPlacementText->IsEnabled() ^ textEnabled) 861 fYPlacementText->SetEnabled(textEnabled); 862 863 if (textEnabled && (strcmp(fXPlacementText->Text(), "") == 0)) { 864 fXPlacementText->SetText("0"); 865 fYPlacementText->SetText("0"); 866 } 867 if (!textEnabled) { 868 fXPlacementText->SetText(NULL); 869 fYPlacementText->SetText(NULL); 870 } 871 872 fXPlacementText->TextView()->MakeSelectable(textEnabled); 873 fYPlacementText->TextView()->MakeSelectable(textEnabled); 874 fXPlacementText->TextView()->MakeEditable(textEnabled); 875 fYPlacementText->TextView()->MakeEditable(textEnabled); 876 877 fPreview->ClearViewBitmap(); 878 879 int32 index = ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex(); 880 if (index >= 0) { 881 BBitmap* bitmap = GetImage(index)->GetBitmap(); 882 if (bitmap) { 883 BackgroundImage::BackgroundImageInfo* info 884 = new BackgroundImage::BackgroundImageInfo(0, index, 885 _FindPlacementMode(), BPoint(atoi(fXPlacementText->Text()), 886 atoi(fYPlacementText->Text())), 887 fIconLabelOutline->Value() == B_CONTROL_ON, 0, 0); 888 if (info->fMode == BackgroundImage::kAtOffset) { 889 fPreview->SetEnabled(true); 890 fPreview->fPoint.x = atoi(fXPlacementText->Text()); 891 fPreview->fPoint.y = atoi(fYPlacementText->Text()); 892 } else 893 fPreview->SetEnabled(false); 894 895 fPreview->fImageBounds = BRect(bitmap->Bounds()); 896 fCurrent->Show(info, fPreview); 897 898 delete info; 899 } 900 } else 901 fPreview->SetEnabled(false); 902 903 fPreview->SetViewColor(fPicker->ValueAsColor()); 904 fPreview->Invalidate(); 905 } 906 907 908 BackgroundImage::Mode 909 BackgroundsView::_FindPlacementMode() 910 { 911 BackgroundImage::Mode mode = BackgroundImage::kAtOffset; 912 913 if (fPlacementMenu->FindItem(kMsgCenterPlacement)->IsMarked()) 914 mode = BackgroundImage::kCentered; 915 if (fPlacementMenu->FindItem(kMsgScalePlacement)->IsMarked()) 916 mode = BackgroundImage::kScaledToFit; 917 if (fPlacementMenu->FindItem(kMsgManualPlacement)->IsMarked()) 918 mode = BackgroundImage::kAtOffset; 919 if (fPlacementMenu->FindItem(kMsgTilePlacement)->IsMarked()) 920 mode = BackgroundImage::kTiled; 921 922 return mode; 923 } 924 925 926 void 927 BackgroundsView::_UpdateButtons() 928 { 929 bool hasChanged = false; 930 if (fPicker->IsEnabled() 931 && fPicker->ValueAsColor() != BScreen().DesktopColor()) { 932 hasChanged = true; 933 } else if (fCurrentInfo) { 934 if ((fIconLabelOutline->Value() == B_CONTROL_ON) 935 ^ fCurrentInfo->fTextWidgetLabelOutline) { 936 hasChanged = true; 937 } else if (_FindPlacementMode() != fCurrentInfo->fMode) { 938 hasChanged = true; 939 } else if (fCurrentInfo->fImageIndex 940 != ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex()) { 941 hasChanged = true; 942 } else if (fCurrent->IsDesktop() 943 && ((fCurrentInfo->fWorkspace != B_ALL_WORKSPACES) 944 ^ (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()))) 945 { 946 hasChanged = true; 947 } else if (fCurrentInfo->fImageIndex > -1 948 && fCurrentInfo->fMode == BackgroundImage::kAtOffset) { 949 BString oldString, newString; 950 oldString << (int)fCurrentInfo->fOffset.x; 951 if (oldString != BString(fXPlacementText->Text())) { 952 hasChanged = true; 953 } 954 oldString = ""; 955 oldString << (int)fCurrentInfo->fOffset.y; 956 if (oldString != BString(fYPlacementText->Text())) { 957 hasChanged = true; 958 } 959 } 960 } else if (fImageMenu->IndexOf(fImageMenu->FindMarked()) > 0) { 961 hasChanged = true; 962 } else if (fIconLabelOutline->Value() == B_CONTROL_OFF) { 963 hasChanged = true; 964 } 965 966 fApply->SetEnabled(hasChanged); 967 fRevert->SetEnabled(hasChanged); 968 } 969 970 971 void 972 BackgroundsView::RefsReceived(BMessage* message) 973 { 974 if (!message->HasRef("refs") && message->HasRef("dir_ref")) { 975 entry_ref dirRef; 976 if (message->FindRef("dir_ref", &dirRef) == B_OK) 977 message->AddRef("refs", &dirRef); 978 } 979 980 entry_ref ref; 981 int32 i = 0; 982 BMimeType imageType("image"); 983 BPath desktopPath; 984 find_directory(B_DESKTOP_DIRECTORY, &desktopPath); 985 986 while (message->FindRef("refs", i++, &ref) == B_OK) { 987 BPath path; 988 BEntry entry(&ref, true); 989 path.SetTo(&entry); 990 BNode node(&entry); 991 992 if (node.IsFile()) { 993 BMimeType refType; 994 BMimeType::GuessMimeType(&ref, &refType); 995 if (!imageType.Contains(&refType)) 996 continue; 997 998 BGImageMenuItem* item; 999 int32 index = AddImage(path); 1000 if (index >= 0) { 1001 item = _FindImageItem(index); 1002 fLastImageIndex = index; 1003 } else { 1004 const char* name = GetImage(-index - 1)->GetName(); 1005 item = new BGImageMenuItem(name, -index - 1, 1006 new BMessage(kMsgImageSelected)); 1007 _AddItem(item); 1008 item->SetTarget(this); 1009 fLastImageIndex = -index - 1; 1010 } 1011 1012 // An optional placement may have been sent 1013 int32 placement = 0; 1014 if (message->FindInt32("placement", &placement) == B_OK) { 1015 BMenuItem* item = fPlacementMenu->FindItem(placement); 1016 if (item) 1017 item->SetMarked(true); 1018 } 1019 item->SetMarked(true); 1020 BMessenger(this).SendMessage(kMsgImageSelected); 1021 } else if (node.IsDirectory()) { 1022 if (desktopPath == path) { 1023 fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->SetMarked(true); 1024 BMessenger(this).SendMessage(kMsgCurrentWorkspace); 1025 break; 1026 } 1027 BMenuItem* item; 1028 int32 index = _AddPath(path); 1029 if (index >= 0) { 1030 item = fWorkspaceMenu->ItemAt(index + 6); 1031 fLastWorkspaceIndex = index + 6; 1032 } else { 1033 if (fWorkspaceMenu->CountItems() <= 5) 1034 fWorkspaceMenu->AddSeparatorItem(); 1035 BString s; 1036 s << B_TRANSLATE("Folder: ") << path.Leaf(); 1037 item = new BMenuItem(s.String(), 1038 new BMessage(kMsgFolderSelected)); 1039 fWorkspaceMenu->AddItem(item, -index - 1 + 6); 1040 item->SetTarget(this); 1041 fLastWorkspaceIndex = -index - 1 + 6; 1042 } 1043 1044 item->SetMarked(true); 1045 BMessenger(this).SendMessage(kMsgFolderSelected); 1046 } 1047 } 1048 } 1049 1050 1051 int32 1052 BackgroundsView::_AddPath(BPath path) 1053 { 1054 int32 count = fPathList.CountItems(); 1055 int32 index = 0; 1056 for (; index < count; index++) { 1057 BPath* p = fPathList.ItemAt(index); 1058 int c = BString(p->Path()).ICompare(path.Path()); 1059 if (c == 0) 1060 return index; 1061 1062 if (c > 0) 1063 break; 1064 } 1065 fPathList.AddItem(new BPath(path), index); 1066 return -index - 1; 1067 } 1068 1069 1070 int32 1071 BackgroundsView::AddImage(BPath path) 1072 { 1073 int32 count = fImageList.CountItems(); 1074 int32 index = 0; 1075 for (; index < count; index++) { 1076 Image* image = fImageList.ItemAt(index); 1077 if (image->GetPath() == path) 1078 return index; 1079 } 1080 1081 fImageList.AddItem(new Image(path)); 1082 return -index - 1; 1083 } 1084 1085 1086 Image* 1087 BackgroundsView::GetImage(int32 imageIndex) 1088 { 1089 return fImageList.ItemAt(imageIndex); 1090 } 1091 1092 1093 BGImageMenuItem* 1094 BackgroundsView::_FindImageItem(const int32 imageIndex) 1095 { 1096 if (imageIndex < 0) 1097 return (BGImageMenuItem*)fImageMenu->ItemAt(0); 1098 1099 int32 count = fImageMenu->CountItems() - 2; 1100 int32 index = 2; 1101 for (; index < count; index++) { 1102 BGImageMenuItem* image = (BGImageMenuItem*)fImageMenu->ItemAt(index); 1103 if (image->ImageIndex() == imageIndex) 1104 return image; 1105 } 1106 return NULL; 1107 } 1108 1109 1110 bool 1111 BackgroundsView::_AddItem(BGImageMenuItem* item) 1112 { 1113 int32 count = fImageMenu->CountItems() - 2; 1114 int32 index = 2; 1115 if (count < index) { 1116 fImageMenu->AddItem(new BSeparatorItem(), 1); 1117 count = fImageMenu->CountItems() - 2; 1118 } 1119 1120 for (; index < count; index++) { 1121 BGImageMenuItem* image = (BGImageMenuItem*)fImageMenu->ItemAt(index); 1122 int c = (BString(image->Label()).ICompare(BString(item->Label()))); 1123 if (c > 0) 1124 break; 1125 } 1126 return fImageMenu->AddItem(item, index); 1127 } 1128 1129 1130 void 1131 BackgroundsView::_SetDesktop(bool isDesktop) 1132 { 1133 fTopLeft->SetDesktop(isDesktop); 1134 fTop->SetDesktop(isDesktop); 1135 fTopRight->SetDesktop(isDesktop); 1136 fLeft->SetDesktop(isDesktop); 1137 fRight->SetDesktop(isDesktop); 1138 fBottomLeft->SetDesktop(isDesktop); 1139 fBottom->SetDesktop(isDesktop); 1140 fBottomRight->SetDesktop(isDesktop); 1141 1142 Invalidate(); 1143 } 1144 1145 1146 bool 1147 BackgroundsView::FoundPositionSetting() 1148 { 1149 return fFoundPositionSetting; 1150 } 1151 1152 1153 // #pragma mark - 1154 1155 1156 Preview::Preview() 1157 : 1158 BControl("PreView", NULL, NULL, B_WILL_DRAW | B_SUBPIXEL_PRECISE) 1159 { 1160 float aspectRatio = BScreen().Frame().Width() / BScreen().Frame().Height(); 1161 float previewWidth = 120.0f * std::max(1.0f, be_plain_font->Size() / 12.0f); 1162 float previewHeight = ceil(previewWidth / aspectRatio); 1163 1164 ResizeTo(previewWidth, previewHeight); 1165 SetExplicitMinSize(BSize(previewWidth, previewHeight)); 1166 SetExplicitMaxSize(BSize(previewWidth, previewHeight)); 1167 } 1168 1169 1170 void 1171 Preview::AttachedToWindow() 1172 { 1173 rgb_color color = ViewColor(); 1174 BControl::AttachedToWindow(); 1175 SetViewColor(color); 1176 } 1177 1178 1179 void 1180 Preview::MouseDown(BPoint point) 1181 { 1182 if (IsEnabled() && Bounds().Contains(point)) { 1183 uint32 buttons; 1184 GetMouse(&point, &buttons); 1185 if (buttons & B_PRIMARY_MOUSE_BUTTON) { 1186 fOldPoint = point; 1187 SetTracking(true); 1188 BScreen().GetMode(&fMode); 1189 fXRatio = Bounds().Width() / fMode.virtual_width; 1190 fYRatio = Bounds().Height() / fMode.virtual_height; 1191 SetMouseEventMask(B_POINTER_EVENTS, 1192 B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); 1193 1194 BCursor grabbingCursor(B_CURSOR_ID_GRABBING); 1195 SetViewCursor(&grabbingCursor); 1196 } 1197 } 1198 } 1199 1200 1201 void 1202 Preview::MouseUp(BPoint point) 1203 { 1204 if (IsTracking()) { 1205 SetTracking(false); 1206 BCursor grabCursor(B_CURSOR_ID_GRAB); 1207 SetViewCursor(&grabCursor); 1208 } 1209 } 1210 1211 1212 void 1213 Preview::MouseMoved(BPoint point, uint32 transit, const BMessage* message) 1214 { 1215 if (!IsTracking()) { 1216 BCursor cursor(IsEnabled() 1217 ? B_CURSOR_ID_GRAB : B_CURSOR_ID_SYSTEM_DEFAULT); 1218 SetViewCursor(&cursor); 1219 } else { 1220 float x, y; 1221 x = fPoint.x + (point.x - fOldPoint.x) / fXRatio; 1222 y = fPoint.y + (point.y - fOldPoint.y) / fYRatio; 1223 bool min, max, mustSend = false; 1224 min = (x > -fImageBounds.Width()); 1225 max = (x < fMode.virtual_width); 1226 if (min && max) { 1227 fOldPoint.x = point.x; 1228 fPoint.x = x; 1229 mustSend = true; 1230 } else { 1231 if (!min && fPoint.x > -fImageBounds.Width()) { 1232 fPoint.x = -fImageBounds.Width(); 1233 fOldPoint.x = point.x - (x - fPoint.x) * fXRatio; 1234 mustSend = true; 1235 } 1236 if (!max && fPoint.x < fMode.virtual_width) { 1237 fPoint.x = fMode.virtual_width; 1238 fOldPoint.x = point.x - (x - fPoint.x) * fXRatio; 1239 mustSend = true; 1240 } 1241 } 1242 1243 min = (y > -fImageBounds.Height()); 1244 max = (y < fMode.virtual_height); 1245 if (min && max) { 1246 fOldPoint.y = point.y; 1247 fPoint.y = y; 1248 mustSend = true; 1249 } else { 1250 if (!min && fPoint.y > -fImageBounds.Height()) { 1251 fPoint.y = -fImageBounds.Height(); 1252 fOldPoint.y = point.y - (y - fPoint.y) * fYRatio; 1253 mustSend = true; 1254 } 1255 if (!max && fPoint.y < fMode.virtual_height) { 1256 fPoint.y = fMode.virtual_height; 1257 fOldPoint.y = point.y - (y - fPoint.y) * fYRatio; 1258 mustSend = true; 1259 } 1260 } 1261 1262 if (mustSend) { 1263 BMessenger messenger(Parent()); 1264 messenger.SendMessage(kMsgUpdatePreviewPlacement); 1265 } 1266 } 1267 1268 BControl::MouseMoved(point, transit, message); 1269 } 1270 1271 1272 // #pragma mark - 1273 1274 1275 BGImageMenuItem::BGImageMenuItem(const char* label, int32 imageIndex, 1276 BMessage* message, char shortcut, uint32 modifiers) 1277 : BMenuItem(label, message, shortcut, modifiers), 1278 fImageIndex(imageIndex) 1279 { 1280 } 1281 1282 1283 // #pragma mark - 1284 1285 1286 FramePart::FramePart(int32 part) 1287 : 1288 BView(NULL, B_WILL_DRAW | B_FRAME_EVENTS), 1289 fFramePart(part), 1290 fIsDesktop(true) 1291 { 1292 _SetSizeAndAlignment(); 1293 } 1294 1295 1296 void 1297 FramePart::Draw(BRect rect) 1298 { 1299 rgb_color color = HighColor(); 1300 SetDrawingMode(B_OP_COPY); 1301 SetHighColor(Parent()->ViewColor()); 1302 1303 if (fIsDesktop) { 1304 switch (fFramePart) { 1305 case FRAME_TOP_LEFT: 1306 FillRect(rect); 1307 SetHighColor(160, 160, 160); 1308 FillRoundRect(BRect(0, 0, 8, 8), 3, 3); 1309 SetHighColor(96, 96, 96); 1310 StrokeRoundRect(BRect(0, 0, 8, 8), 3, 3); 1311 break; 1312 1313 case FRAME_TOP: 1314 SetHighColor(160, 160, 160); 1315 FillRect(BRect(0, 1, rect.right, 3)); 1316 SetHighColor(96, 96, 96); 1317 StrokeLine(BPoint(0, 0), BPoint(rect.right, 0)); 1318 SetHighColor(0, 0, 0); 1319 StrokeLine(BPoint(0, 4), BPoint(rect.right, 4)); 1320 break; 1321 1322 case FRAME_TOP_RIGHT: 1323 FillRect(rect); 1324 SetHighColor(160, 160, 160); 1325 FillRoundRect(BRect(-4, 0, 4, 8), 3, 3); 1326 SetHighColor(96, 96, 96); 1327 StrokeRoundRect(BRect(-4, 0, 4, 8), 3, 3); 1328 break; 1329 1330 case FRAME_LEFT_SIDE: 1331 SetHighColor(160, 160, 160); 1332 FillRect(BRect(1, 0, 3, rect.bottom)); 1333 SetHighColor(96, 96, 96); 1334 StrokeLine(BPoint(0, 0), BPoint(0, rect.bottom)); 1335 SetHighColor(0, 0, 0); 1336 StrokeLine(BPoint(4, 0), BPoint(4, rect.bottom)); 1337 break; 1338 1339 case FRAME_RIGHT_SIDE: 1340 SetHighColor(160, 160, 160); 1341 FillRect(BRect(1, 0, 3, rect.bottom)); 1342 SetHighColor(0, 0, 0); 1343 StrokeLine(BPoint(0, 0), BPoint(0, rect.bottom)); 1344 SetHighColor(96, 96, 96); 1345 StrokeLine(BPoint(4, 0), BPoint(4, rect.bottom)); 1346 break; 1347 1348 case FRAME_BOTTOM_LEFT: 1349 FillRect(rect); 1350 SetHighColor(160, 160, 160); 1351 FillRoundRect(BRect(0, -4, 8, 4), 3, 3); 1352 SetHighColor(96, 96, 96); 1353 StrokeRoundRect(BRect(0, -4, 8, 4), 3, 3); 1354 break; 1355 1356 case FRAME_BOTTOM: 1357 SetHighColor(160, 160, 160); 1358 FillRect(BRect(0, 1, rect.right, 3)); 1359 SetHighColor(0, 0, 0); 1360 StrokeLine(BPoint(0, 0), BPoint(rect.right, 0)); 1361 SetHighColor(96, 96, 96); 1362 StrokeLine(BPoint(0, 4), BPoint(rect.right, 4)); 1363 SetHighColor(228, 0, 0); 1364 StrokeLine(BPoint(5, 2), BPoint(7, 2)); 1365 break; 1366 1367 case FRAME_BOTTOM_RIGHT: 1368 FillRect(rect); 1369 SetHighColor(160, 160, 160); 1370 FillRoundRect(BRect(-4, -4, 4, 4), 3, 3); 1371 SetHighColor(96, 96, 96); 1372 StrokeRoundRect(BRect(-4, -4, 4, 4), 3, 3); 1373 break; 1374 1375 default: 1376 break; 1377 } 1378 } else { 1379 switch (fFramePart) { 1380 case FRAME_TOP_LEFT: 1381 SetHighColor(152, 152, 152); 1382 StrokeLine(BPoint(0, 0), BPoint(0, 12)); 1383 StrokeLine(BPoint(0, 0), BPoint(4, 0)); 1384 StrokeLine(BPoint(3, 12), BPoint(3, 12)); 1385 SetHighColor(255, 203, 0); 1386 FillRect(BRect(1, 1, 3, 9)); 1387 SetHighColor(240, 240, 240); 1388 StrokeLine(BPoint(1, 12), BPoint(1, 10)); 1389 StrokeLine(BPoint(2, 10), BPoint(3, 10)); 1390 SetHighColor(200, 200, 200); 1391 StrokeLine(BPoint(2, 12), BPoint(2, 11)); 1392 StrokeLine(BPoint(3, 11), BPoint(3, 11)); 1393 break; 1394 1395 case FRAME_TOP: 1396 FillRect(BRect(54, 0, rect.right, 8)); 1397 SetHighColor(255, 203, 0); 1398 FillRect(BRect(0, 1, 52, 9)); 1399 SetHighColor(152, 152, 152); 1400 StrokeLine(BPoint(0, 0), BPoint(53, 0)); 1401 StrokeLine(BPoint(53, 1), BPoint(53, 9)); 1402 StrokeLine(BPoint(54, 9), BPoint(rect.right, 9)); 1403 SetHighColor(240, 240, 240); 1404 StrokeLine(BPoint(0, 10), BPoint(rect.right, 10)); 1405 SetHighColor(200, 200, 200); 1406 StrokeLine(BPoint(0, 11), BPoint(rect.right, 11)); 1407 SetHighColor(152, 152, 152); 1408 StrokeLine(BPoint(0, 12), BPoint(rect.right, 12)); 1409 break; 1410 1411 case FRAME_TOP_RIGHT: 1412 FillRect(BRect(0, 0, 3, 8)); 1413 SetHighColor(152, 152, 152); 1414 StrokeLine(BPoint(0, 12), BPoint(0, 12)); 1415 StrokeLine(BPoint(0, 9), BPoint(3, 9)); 1416 StrokeLine(BPoint(3, 12), BPoint(3, 9)); 1417 SetHighColor(240, 240, 240); 1418 StrokeLine(BPoint(0, 10), BPoint(2, 10)); 1419 StrokeLine(BPoint(1, 12), BPoint(1, 12)); 1420 SetHighColor(200, 200, 200); 1421 StrokeLine(BPoint(2, 12), BPoint(2, 12)); 1422 StrokeLine(BPoint(0, 11), BPoint(2, 11)); 1423 break; 1424 1425 case FRAME_LEFT_SIDE: 1426 case FRAME_RIGHT_SIDE: 1427 SetHighColor(152, 152, 152); 1428 StrokeLine(BPoint(0, 0), BPoint(0, rect.bottom)); 1429 SetHighColor(240, 240, 240); 1430 StrokeLine(BPoint(1, 0), BPoint(1, rect.bottom)); 1431 SetHighColor(200, 200, 200); 1432 StrokeLine(BPoint(2, 0), BPoint(2, rect.bottom)); 1433 SetHighColor(152, 152, 152); 1434 StrokeLine(BPoint(3, 0), BPoint(3, rect.bottom)); 1435 break; 1436 1437 case FRAME_BOTTOM_LEFT: 1438 SetHighColor(152, 152, 152); 1439 StrokeLine(BPoint(0, 0), BPoint(0, 3)); 1440 StrokeLine(BPoint(0, 3), BPoint(3, 3)); 1441 StrokeLine(BPoint(3, 0), BPoint(3, 0)); 1442 SetHighColor(240, 240, 240); 1443 StrokeLine(BPoint(1, 0), BPoint(1, 2)); 1444 StrokeLine(BPoint(3, 1), BPoint(3, 1)); 1445 SetHighColor(200, 200, 200); 1446 StrokeLine(BPoint(2, 0), BPoint(2, 2)); 1447 StrokeLine(BPoint(3, 2), BPoint(3, 2)); 1448 break; 1449 1450 case FRAME_BOTTOM: 1451 SetHighColor(152, 152, 152); 1452 StrokeLine(BPoint(0, 0), BPoint(rect.right, 0)); 1453 SetHighColor(240, 240, 240); 1454 StrokeLine(BPoint(0, 1), BPoint(rect.right, 1)); 1455 SetHighColor(200, 200, 200); 1456 StrokeLine(BPoint(0, 2), BPoint(rect.right, 2)); 1457 SetHighColor(152, 152, 152); 1458 StrokeLine(BPoint(0, 3), BPoint(rect.right, 3)); 1459 break; 1460 1461 case FRAME_BOTTOM_RIGHT: 1462 SetHighColor(152, 152, 152); 1463 StrokeLine(BPoint(0, 0), BPoint(0, 0)); 1464 SetHighColor(240, 240, 240); 1465 StrokeLine(BPoint(1, 0), BPoint(1, 1)); 1466 StrokeLine(BPoint(0, 1), BPoint(0, 1)); 1467 SetHighColor(200, 200, 200); 1468 StrokeLine(BPoint(2, 0), BPoint(2, 2)); 1469 StrokeLine(BPoint(0, 2), BPoint(1, 2)); 1470 SetHighColor(152, 152, 152); 1471 StrokeLine(BPoint(3, 0), BPoint(3, 3)); 1472 StrokeLine(BPoint(0, 3), BPoint(2, 3)); 1473 break; 1474 1475 default: 1476 break; 1477 } 1478 } 1479 1480 SetHighColor(color); 1481 } 1482 1483 1484 void 1485 FramePart::SetDesktop(bool isDesktop) 1486 { 1487 fIsDesktop = isDesktop; 1488 1489 _SetSizeAndAlignment(); 1490 Invalidate(); 1491 } 1492 1493 1494 void 1495 FramePart::_SetSizeAndAlignment() 1496 { 1497 if (fIsDesktop) { 1498 switch (fFramePart) { 1499 case FRAME_TOP_LEFT: 1500 SetExplicitMinSize(BSize(4, 4)); 1501 SetExplicitMaxSize(BSize(4, 4)); 1502 break; 1503 1504 case FRAME_TOP: 1505 SetExplicitMinSize(BSize(1, 4)); 1506 SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 4)); 1507 break; 1508 1509 case FRAME_TOP_RIGHT: 1510 SetExplicitMinSize(BSize(4, 4)); 1511 SetExplicitMaxSize(BSize(4, 4)); 1512 break; 1513 1514 case FRAME_LEFT_SIDE: 1515 SetExplicitMinSize(BSize(4, 1)); 1516 SetExplicitMaxSize(BSize(4, B_SIZE_UNLIMITED)); 1517 break; 1518 1519 case FRAME_RIGHT_SIDE: 1520 SetExplicitMinSize(BSize(4, 1)); 1521 SetExplicitMaxSize(BSize(4, B_SIZE_UNLIMITED)); 1522 break; 1523 1524 case FRAME_BOTTOM_LEFT: 1525 SetExplicitMinSize(BSize(4, 4)); 1526 SetExplicitMaxSize(BSize(4, 4)); 1527 break; 1528 1529 case FRAME_BOTTOM: 1530 SetExplicitMinSize(BSize(1, 4)); 1531 SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 4)); 1532 break; 1533 1534 case FRAME_BOTTOM_RIGHT: 1535 SetExplicitMaxSize(BSize(4, 4)); 1536 SetExplicitMinSize(BSize(4, 4)); 1537 break; 1538 1539 default: 1540 break; 1541 } 1542 } else { 1543 switch (fFramePart) { 1544 case FRAME_TOP_LEFT: 1545 SetExplicitMinSize(BSize(3, 12)); 1546 SetExplicitMaxSize(BSize(3, 12)); 1547 break; 1548 1549 case FRAME_TOP: 1550 SetExplicitMinSize(BSize(1, 12)); 1551 SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 12)); 1552 break; 1553 1554 case FRAME_TOP_RIGHT: 1555 SetExplicitMinSize(BSize(3, 12)); 1556 SetExplicitMaxSize(BSize(3, 12)); 1557 break; 1558 1559 case FRAME_LEFT_SIDE: 1560 SetExplicitMinSize(BSize(3, 1)); 1561 SetExplicitMaxSize(BSize(3, B_SIZE_UNLIMITED)); 1562 break; 1563 1564 case FRAME_RIGHT_SIDE: 1565 SetExplicitMinSize(BSize(3, 1)); 1566 SetExplicitMaxSize(BSize(3, B_SIZE_UNLIMITED)); 1567 break; 1568 1569 case FRAME_BOTTOM_LEFT: 1570 SetExplicitMinSize(BSize(3, 3)); 1571 SetExplicitMaxSize(BSize(3, 3)); 1572 break; 1573 1574 case FRAME_BOTTOM: 1575 SetExplicitMinSize(BSize(1, 3)); 1576 SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 3)); 1577 break; 1578 1579 case FRAME_BOTTOM_RIGHT: 1580 SetExplicitMaxSize(BSize(3, 3)); 1581 SetExplicitMinSize(BSize(3, 3)); 1582 break; 1583 1584 default: 1585 break; 1586 } 1587 } 1588 1589 switch (fFramePart) { 1590 case FRAME_TOP_LEFT: 1591 SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_BOTTOM)); 1592 break; 1593 1594 case FRAME_TOP: 1595 SetExplicitAlignment(BAlignment(B_ALIGN_CENTER, B_ALIGN_BOTTOM)); 1596 break; 1597 1598 case FRAME_TOP_RIGHT: 1599 SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_BOTTOM)); 1600 break; 1601 1602 case FRAME_LEFT_SIDE: 1603 SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_MIDDLE)); 1604 break; 1605 1606 case FRAME_RIGHT_SIDE: 1607 SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); 1608 break; 1609 1610 case FRAME_BOTTOM_LEFT: 1611 SetExplicitAlignment(BAlignment(B_ALIGN_RIGHT, B_ALIGN_TOP)); 1612 break; 1613 1614 case FRAME_BOTTOM: 1615 SetExplicitAlignment(BAlignment(B_ALIGN_CENTER, B_ALIGN_TOP)); 1616 break; 1617 1618 case FRAME_BOTTOM_RIGHT: 1619 SetExplicitAlignment(BAlignment(B_ALIGN_LEFT, B_ALIGN_TOP)); 1620 break; 1621 1622 default: 1623 break; 1624 } 1625 } 1626 1627