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