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