1 /* 2 * Copyright 2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "MainWindow.h" 10 11 #include <new> 12 #include <stdio.h> 13 14 #include <Menu.h> 15 #include <MenuBar.h> 16 #include <MenuItem.h> 17 #include <Message.h> 18 #include <Screen.h> 19 #include <ScrollView.h> 20 21 #if __HAIKU__ 22 # include <GridLayout.h> 23 # include <GroupLayout.h> 24 # include <GroupView.h> 25 #endif 26 27 #include "support_ui.h" 28 29 #include "AddPathsCommand.h" 30 #include "AddShapesCommand.h" 31 #include "AddStylesCommand.h" 32 #include "CanvasView.h" 33 #include "CommandStack.h" 34 #include "CompoundCommand.h" 35 #include "CurrentColor.h" 36 #include "Document.h" 37 #include "Exporter.h" 38 #include "IconObjectListView.h" 39 #include "IconEditorApp.h" 40 #include "IconView.h" 41 #include "PathListView.h" 42 #include "ScrollView.h" 43 #include "ShapeListView.h" 44 #include "StyleListView.h" 45 #include "StyleView.h" 46 #include "SwatchGroup.h" 47 #include "TransformerListView.h" 48 #include "TransformGradientBox.h" 49 #include "TransformShapesBox.h" 50 #include "Util.h" 51 52 // TODO: just for testing 53 #include "AffineTransformer.h" 54 #include "Gradient.h" 55 #include "Icon.h" 56 #include "MultipleManipulatorState.h" 57 #include "PathManipulator.h" 58 #include "Shape.h" 59 #include "ShapeContainer.h" 60 #include "ShapeListView.h" 61 #include "StrokeTransformer.h" 62 #include "Style.h" 63 #include "StyleContainer.h" 64 #include "VectorPath.h" 65 66 using std::nothrow; 67 68 enum { 69 MSG_UNDO = 'undo', 70 MSG_REDO = 'redo', 71 72 MSG_PATH_SELECTED = 'vpsl', 73 MSG_STYLE_SELECTED = 'stsl', 74 MSG_SHAPE_SELECTED = 'spsl', 75 76 MSG_SHAPE_RESET_TRANSFORMATION = 'rtsh', 77 MSG_STYLE_RESET_TRANSFORMATION = 'rtst', 78 79 MSG_MOUSE_FILTER_MODE = 'mfmd', 80 }; 81 82 // constructor 83 MainWindow::MainWindow(IconEditorApp* app, Document* document) 84 : BWindow(BRect(50, 50, 900, 750), "Icon-O-Matic", 85 B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 86 B_ASYNCHRONOUS_CONTROLS), 87 fApp(app), 88 fDocument(document), 89 fIcon(NULL) 90 { 91 _Init(); 92 } 93 94 // destructor 95 MainWindow::~MainWindow() 96 { 97 delete fState; 98 99 if (fIcon) 100 fIcon->Release(); 101 102 fDocument->CommandStack()->RemoveObserver(this); 103 } 104 105 // #pragma mark - 106 107 // MessageReceived 108 void 109 MainWindow::MessageReceived(BMessage* message) 110 { 111 if (!fDocument || !fDocument->WriteLock()) { 112 BWindow::MessageReceived(message); 113 return; 114 } 115 116 switch (message->what) { 117 118 case B_REFS_RECEIVED: 119 case B_SIMPLE_DATA: 120 message->what = B_REFS_RECEIVED; 121 if (modifiers() & B_SHIFT_KEY) 122 message->AddBool("append", true); 123 be_app->PostMessage(message); 124 break; 125 126 case MSG_UNDO: 127 fDocument->CommandStack()->Undo(); 128 break; 129 case MSG_REDO: 130 fDocument->CommandStack()->Redo(); 131 break; 132 133 case MSG_MOUSE_FILTER_MODE: { 134 uint32 mode; 135 if (message->FindInt32("mode", (int32*)&mode) == B_OK) 136 fCanvasView->SetMouseFilterMode(mode); 137 break; 138 } 139 140 case MSG_SET_ICON: 141 SetIcon(fDocument->Icon()); 142 break; 143 144 case MSG_ADD_SHAPE: { 145 AddStylesCommand* styleCommand = NULL; 146 Style* style = NULL; 147 if (message->HasBool("style")) { 148 new_style(CurrentColor::Default()->Color(), 149 fDocument->Icon()->Styles(), &style, &styleCommand); 150 } 151 152 AddPathsCommand* pathCommand = NULL; 153 VectorPath* path = NULL; 154 if (message->HasBool("path")) { 155 new_path(fDocument->Icon()->Paths(), &path, &pathCommand); 156 } 157 158 if (!style) { 159 // use current or first style 160 int32 currentStyle = fStyleListView->CurrentSelection(0); 161 style = fDocument->Icon()->Styles()->StyleAt(currentStyle); 162 if (!style) 163 style = fDocument->Icon()->Styles()->StyleAt(0); 164 } 165 166 Shape* shape = new (nothrow) Shape(style); 167 Shape* shapes[1]; 168 shapes[0] = shape; 169 AddShapesCommand* shapeCommand = new (nothrow) AddShapesCommand( 170 fDocument->Icon()->Shapes(), shapes, 1, 171 fDocument->Icon()->Shapes()->CountShapes(), 172 fDocument->Selection()); 173 174 if (path && shape) 175 shape->Paths()->AddPath(path); 176 177 ::Command* command = NULL; 178 if (styleCommand || pathCommand) { 179 if (styleCommand && pathCommand) { 180 Command** commands = new Command*[3]; 181 commands[0] = styleCommand; 182 commands[1] = pathCommand; 183 commands[2] = shapeCommand; 184 command = new CompoundCommand(commands, 3, 185 "Add Shape With Path & Style", 0); 186 } else if (styleCommand) { 187 Command** commands = new Command*[2]; 188 commands[0] = styleCommand; 189 commands[1] = shapeCommand; 190 command = new CompoundCommand(commands, 2, 191 "Add Shape With Style", 0); 192 } else { 193 Command** commands = new Command*[2]; 194 commands[0] = pathCommand; 195 commands[1] = shapeCommand; 196 command = new CompoundCommand(commands, 2, 197 "Add Shape With Path", 0); 198 } 199 } else { 200 command = shapeCommand; 201 } 202 fDocument->CommandStack()->Perform(command); 203 break; 204 } 205 206 // TODO: listen to selection in CanvasView to add a manipulator 207 case MSG_PATH_SELECTED: { 208 VectorPath* path; 209 if (message->FindPointer("path", (void**)&path) < B_OK) 210 path = NULL; 211 212 fState->DeleteManipulators(); 213 if (fDocument->Icon()->Paths()->HasPath(path)) { 214 PathManipulator* pathManipulator = new (nothrow) PathManipulator(path); 215 fState->AddManipulator(pathManipulator); 216 } 217 break; 218 } 219 case MSG_STYLE_SELECTED: { 220 Style* style; 221 if (message->FindPointer("style", (void**)&style) < B_OK) 222 style = NULL; 223 if (!fDocument->Icon()->Styles()->HasStyle(style)) 224 style = NULL; 225 226 fStyleView->SetStyle(style); 227 break; 228 } 229 case MSG_GRADIENT_SELECTED: { 230 // if there is a gradient, add a transform box around it 231 Gradient* gradient; 232 if (message->FindPointer("gradient", (void**)&gradient) < B_OK) 233 gradient = NULL; 234 fState->DeleteManipulators(); 235 if (gradient) { 236 TransformGradientBox* transformBox 237 = new (nothrow) TransformGradientBox(fCanvasView, 238 gradient, 239 NULL); 240 fState->AddManipulator(transformBox); 241 } 242 break; 243 } 244 case MSG_SHAPE_SELECTED: { 245 Shape* shape; 246 if (message->FindPointer("shape", (void**)&shape) < B_OK) 247 shape = NULL; 248 if (!fIcon || !fIcon->Shapes()->HasShape(shape)) 249 shape = NULL; 250 251 fPathListView->SetCurrentShape(shape); 252 fStyleListView->SetCurrentShape(shape); 253 fTransformerListView->SetShape(shape); 254 255 BList selectedShapes; 256 ShapeContainer* shapes = fDocument->Icon()->Shapes(); 257 int32 count = shapes->CountShapes(); 258 for (int32 i = 0; i < count; i++) { 259 shape = shapes->ShapeAtFast(i); 260 if (shape->IsSelected()) { 261 selectedShapes.AddItem((void*)shape); 262 } 263 } 264 265 fState->DeleteManipulators(); 266 if (selectedShapes.CountItems() > 0) { 267 TransformShapesBox* transformBox = new (nothrow) TransformShapesBox( 268 fCanvasView, 269 (const Shape**)selectedShapes.Items(), 270 selectedShapes.CountItems()); 271 fState->AddManipulator(transformBox); 272 } 273 break; 274 } 275 default: 276 BWindow::MessageReceived(message); 277 } 278 279 fDocument->WriteUnlock(); 280 } 281 282 // QuitRequested 283 bool 284 MainWindow::QuitRequested() 285 { 286 // forward this to app but return "false" in order 287 // to have a single code path for quitting 288 be_app->PostMessage(B_QUIT_REQUESTED); 289 290 return false; 291 } 292 293 // WorkspaceActivated 294 void 295 MainWindow::WorkspaceActivated(int32 workspace, bool active) 296 { 297 BWindow::WorkspaceActivated(workspace, active); 298 299 // NOTE: hack to workaround buggy BScreen::DesktopColor() on R5 300 301 uint32 workspaces = Workspaces(); 302 if (!active || ((1 << workspace) & workspaces) == 0) 303 return; 304 305 WorkspacesChanged(workspaces, workspaces); 306 } 307 308 // WorkspacesChanged 309 void 310 MainWindow::WorkspacesChanged(uint32 oldWorkspaces, uint32 newWorkspaces) 311 { 312 if (oldWorkspaces != newWorkspaces) 313 BWindow::WorkspacesChanged(oldWorkspaces, newWorkspaces); 314 315 BScreen screen(this); 316 317 // Unfortunately, this is buggy on R5: screen.DesktopColor() 318 // as well as ui_color(B_DESKTOP_COLOR) return the color 319 // of the *active* screen, not the one on which this window 320 // is. So this trick only works when you drag this window 321 // from another workspace onto the current workspace, not 322 // when you drag the window from the current workspace onto 323 // another workspace and then switch to the other workspace. 324 325 fIconPreview32Desktop->SetIconBGColor(screen.DesktopColor()); 326 fIconPreview64->SetIconBGColor(screen.DesktopColor()); 327 } 328 329 // #pragma mark - 330 331 // ObjectChanged 332 void 333 MainWindow::ObjectChanged(const Observable* object) 334 { 335 if (!fDocument) 336 return; 337 338 if (!Lock()) 339 return; 340 341 if (object == fDocument->CommandStack()) { 342 // relable Undo item and update enabled status 343 BString label("Undo"); 344 fUndoMI->SetEnabled(fDocument->CommandStack()->GetUndoName(label)); 345 if (fUndoMI->IsEnabled()) 346 fUndoMI->SetLabel(label.String()); 347 else 348 fUndoMI->SetLabel("<nothing to undo>"); 349 350 // relable Redo item and update enabled status 351 label.SetTo("Redo"); 352 fRedoMI->SetEnabled(fDocument->CommandStack()->GetRedoName(label)); 353 if (fRedoMI->IsEnabled()) 354 fRedoMI->SetLabel(label.String()); 355 else 356 fRedoMI->SetLabel("<nothing to redo>"); 357 } 358 359 Unlock(); 360 } 361 362 // #pragma mark - 363 364 // MakeEmpty 365 void 366 MainWindow::MakeEmpty() 367 { 368 fPathListView->SetCurrentShape(NULL); 369 fStyleListView->SetCurrentShape(NULL); 370 fStyleView->SetStyle(NULL); 371 372 fTransformerListView->SetShape(NULL); 373 374 fState->DeleteManipulators(); 375 } 376 377 // SetIcon 378 void 379 MainWindow::SetIcon(Icon* icon) 380 { 381 if (fIcon == icon) 382 return; 383 384 Icon* oldIcon = fIcon; 385 386 fIcon = icon; 387 388 if (fIcon) 389 fIcon->Acquire(); 390 else 391 MakeEmpty(); 392 393 fCanvasView->SetIcon(fIcon); 394 395 fPathListView->SetPathContainer(fIcon ? fIcon->Paths() : NULL); 396 fPathListView->SetShapeContainer(fIcon ? fIcon->Shapes() : NULL); 397 398 fStyleListView->SetStyleContainer(fIcon ? fIcon->Styles() : NULL); 399 fStyleListView->SetShapeContainer(fIcon ? fIcon->Shapes() : NULL); 400 401 fShapeListView->SetShapeContainer(fIcon ? fIcon->Shapes() : NULL); 402 403 // icon previews 404 fIconPreview16Folder->SetIcon(fIcon); 405 fIconPreview16Menu->SetIcon(fIcon); 406 fIconPreview32Folder->SetIcon(fIcon); 407 fIconPreview32Desktop->SetIcon(fIcon); 408 // fIconPreview48->SetIcon(fIcon); 409 fIconPreview64->SetIcon(fIcon); 410 411 // keep this last 412 if (oldIcon) 413 oldIcon->Release(); 414 } 415 416 // #pragma mark - 417 418 // StoreSettings 419 void 420 MainWindow::StoreSettings(BMessage* archive) 421 { 422 if (archive->ReplaceRect("main window frame", Frame()) < B_OK) 423 archive->AddRect("main window frame", Frame()); 424 } 425 426 // RestoreSettings 427 void 428 MainWindow::RestoreSettings(BMessage* archive) 429 { 430 BRect frame; 431 if (archive->FindRect("main window frame", &frame) == B_OK) { 432 make_sure_frame_is_on_screen(frame, this); 433 MoveTo(frame.LeftTop()); 434 ResizeTo(frame.Width(), frame.Height()); 435 } 436 } 437 438 // #pragma mark - 439 440 // _Init 441 void 442 MainWindow::_Init() 443 { 444 // create the GUI 445 _CreateGUI(Bounds()); 446 447 // TODO: move this to CanvasView? 448 fState = new MultipleManipulatorState(fCanvasView); 449 fCanvasView->SetState(fState); 450 451 fCanvasView->SetCatchAllEvents(true); 452 fCanvasView->SetCommandStack(fDocument->CommandStack()); 453 // fCanvasView->SetSelection(fDocument->Selection()); 454 455 fPathListView->SetMenu(fPathMenu); 456 fPathListView->SetCommandStack(fDocument->CommandStack()); 457 fPathListView->SetSelection(fDocument->Selection()); 458 459 fStyleListView->SetMenu(fStyleMenu); 460 fStyleListView->SetCommandStack(fDocument->CommandStack()); 461 fStyleListView->SetSelection(fDocument->Selection()); 462 463 fStyleView->SetCommandStack(fDocument->CommandStack()); 464 fStyleView->SetCurrentColor(CurrentColor::Default()); 465 466 fShapeListView->SetMenu(fShapeMenu); 467 fShapeListView->SetCommandStack(fDocument->CommandStack()); 468 fShapeListView->SetSelection(fDocument->Selection()); 469 470 fTransformerListView->SetMenu(fTransformerMenu); 471 fTransformerListView->SetCommandStack(fDocument->CommandStack()); 472 fTransformerListView->SetSelection(fDocument->Selection()); 473 474 fPropertyListView->SetCommandStack(fDocument->CommandStack()); 475 fPropertyListView->SetSelection(fDocument->Selection()); 476 fPropertyListView->SetMenu(fPropertyMenu); 477 478 fDocument->CommandStack()->AddObserver(this); 479 480 fSwatchGroup->SetCurrentColor(CurrentColor::Default()); 481 482 SetIcon(fDocument->Icon()); 483 } 484 485 // _CreateGUI 486 void 487 MainWindow::_CreateGUI(BRect bounds) 488 { 489 const float splitWidth = 160; 490 491 #ifdef __HAIKU__ 492 493 SetLayout(new BGroupLayout(B_HORIZONTAL)); 494 495 BGridLayout* layout = new BGridLayout(); 496 BView* rootView = new BView("root view", 0, layout); 497 AddChild(rootView); 498 rootView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 499 500 BGroupView* leftTopView = new BGroupView(B_VERTICAL); 501 layout->AddView(leftTopView, 0, 0); 502 leftTopView->SetExplicitMinSize(BSize(splitWidth, B_SIZE_UNSET)); 503 504 // views along the left side 505 leftTopView->AddChild(_CreateMenuBar(bounds)); 506 507 BGroupView* iconPreviews = new BGroupView(B_HORIZONTAL); 508 iconPreviews->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 509 iconPreviews->GroupLayout()->SetSpacing(5); 510 511 // icon previews 512 fIconPreview16Folder = new IconView(BRect(0, 0, 15, 15), 513 "icon preview 16 folder"); 514 fIconPreview16Menu = new IconView(BRect(0, 0, 15, 15), 515 "icon preview 16 menu"); 516 fIconPreview16Menu->SetLowColor(ui_color(B_MENU_BACKGROUND_COLOR)); 517 518 fIconPreview32Folder = new IconView(BRect(0, 0, 31, 31), 519 "icon preview 32 folder"); 520 fIconPreview32Desktop = new IconView(BRect(0, 0, 31, 31), 521 "icon preview 32 desktop"); 522 fIconPreview32Desktop->SetLowColor(ui_color(B_DESKTOP_COLOR)); 523 524 // fIconPreview48 = new IconView(bounds, "icon preview 48"); 525 fIconPreview64 = new IconView(BRect(0, 0, 63, 63), "icon preview 64"); 526 fIconPreview64->SetLowColor(ui_color(B_DESKTOP_COLOR)); 527 528 529 BGroupView* smallPreviews = new BGroupView(B_VERTICAL); 530 smallPreviews->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 531 smallPreviews->GroupLayout()->SetSpacing(5); 532 533 smallPreviews->AddChild(fIconPreview16Folder); 534 smallPreviews->AddChild(fIconPreview16Menu); 535 536 BGroupView* mediumPreviews = new BGroupView(B_VERTICAL); 537 mediumPreviews->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 538 mediumPreviews->GroupLayout()->SetSpacing(5); 539 540 mediumPreviews->AddChild(fIconPreview32Folder); 541 mediumPreviews->AddChild(fIconPreview32Desktop); 542 543 // iconPreviews->AddChild(fIconPreview48); 544 545 iconPreviews->AddChild(smallPreviews); 546 iconPreviews->AddChild(mediumPreviews); 547 iconPreviews->AddChild(fIconPreview64); 548 iconPreviews->SetExplicitMaxSize(BSize(B_SIZE_UNSET, B_SIZE_UNLIMITED)); 549 550 leftTopView->AddChild(iconPreviews); 551 552 553 BGroupView* leftSideView = new BGroupView(B_VERTICAL); 554 layout->AddView(leftSideView, 0, 1); 555 leftSideView->SetExplicitMinSize(BSize(splitWidth, B_SIZE_UNSET)); 556 557 // path menu and list view 558 BMenuBar* menuBar = new BMenuBar(bounds, "path menu bar"); 559 menuBar->AddItem(fPathMenu); 560 leftSideView->AddChild(menuBar); 561 562 fPathListView = new PathListView(BRect(0, 0, splitWidth, 100), 563 "path list view", 564 new BMessage(MSG_PATH_SELECTED), this); 565 566 BView* scrollView = new BScrollView("path list scroll view", 567 fPathListView, 568 B_FOLLOW_NONE, 0, false, true, 569 B_NO_BORDER); 570 leftSideView->AddChild(scrollView); 571 572 // shape list view 573 menuBar = new BMenuBar(bounds, "shape menu bar"); 574 menuBar->AddItem(fShapeMenu); 575 leftSideView->AddChild(menuBar); 576 577 fShapeListView = new ShapeListView(BRect(0, 0, splitWidth, 100), 578 "shape list view", 579 new BMessage(MSG_SHAPE_SELECTED), this); 580 scrollView = new BScrollView("shape list scroll view", 581 fShapeListView, 582 B_FOLLOW_NONE, 0, false, true, 583 B_NO_BORDER); 584 leftSideView->AddChild(scrollView); 585 586 // transformer list view 587 menuBar = new BMenuBar(bounds, "transformer menu bar"); 588 menuBar->AddItem(fTransformerMenu); 589 leftSideView->AddChild(menuBar); 590 591 fTransformerListView = new TransformerListView(BRect(0, 0, splitWidth, 100), 592 "transformer list view"); 593 scrollView = new BScrollView("transformer list scroll view", 594 fTransformerListView, 595 B_FOLLOW_NONE, 0, false, true, 596 B_NO_BORDER); 597 leftSideView->AddChild(scrollView); 598 599 // property list view 600 menuBar = new BMenuBar(bounds, "property menu bar"); 601 menuBar->AddItem(fPropertyMenu); 602 leftSideView->AddChild(menuBar); 603 604 fPropertyListView = new IconObjectListView(); 605 606 // scroll view around property list view 607 ScrollView* propScrollView = new ScrollView(fPropertyListView, 608 SCROLL_VERTICAL | SCROLL_NO_FRAME, 609 BRect(0, 0, splitWidth, 100), 610 "property scroll view", 611 B_FOLLOW_NONE, 612 B_WILL_DRAW | B_FRAME_EVENTS); 613 leftSideView->AddChild(propScrollView); 614 615 BGroupLayout* topSide = new BGroupLayout(B_HORIZONTAL); 616 BView* topSideView = new BView("top side view", 0, topSide); 617 layout->AddView(topSideView, 1, 0); 618 619 // canvas view 620 BRect canvasBounds = BRect(0, 0, 200, 200); 621 fCanvasView = new CanvasView(canvasBounds); 622 623 // scroll view around canvas view 624 canvasBounds.bottom += B_H_SCROLL_BAR_HEIGHT; 625 canvasBounds.right += B_V_SCROLL_BAR_WIDTH; 626 ScrollView* canvasScrollView 627 = new ScrollView(fCanvasView, SCROLL_VERTICAL | SCROLL_HORIZONTAL 628 | SCROLL_NO_FRAME | SCROLL_VISIBLE_RECT_IS_CHILD_BOUNDS, 629 canvasBounds, "canvas scroll view", 630 B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS); 631 layout->AddView(canvasScrollView, 1, 1); 632 633 // views along the top 634 635 BGroupLayout* styleGroup = new BGroupLayout(B_VERTICAL); 636 BView* styleGroupView = new BView("style group", 0, styleGroup); 637 topSide->AddView(styleGroupView); 638 639 // style list view 640 menuBar = new BMenuBar(bounds, "style menu bar"); 641 menuBar->AddItem(fStyleMenu); 642 styleGroup->AddView(menuBar); 643 644 fStyleListView = new StyleListView(BRect(0, 0, splitWidth, 100), 645 "style list view", 646 new BMessage(MSG_STYLE_SELECTED), this); 647 scrollView = new BScrollView("style list scroll view", 648 fStyleListView, 649 B_FOLLOW_NONE, 0, false, true, 650 B_NO_BORDER); 651 scrollView->SetExplicitMaxSize(BSize(splitWidth, B_SIZE_UNLIMITED)); 652 styleGroup->AddView(scrollView); 653 654 // style view 655 fStyleView = new StyleView(BRect(0, 0, 200, 100)); 656 topSide->AddView(fStyleView); 657 658 // swatch group 659 BGroupLayout* swatchGroup = new BGroupLayout(B_VERTICAL); 660 BView* swatchGroupView = new BView("swatch group", 0, swatchGroup); 661 topSide->AddView(swatchGroupView); 662 663 menuBar = new BMenuBar(bounds, "swatches menu bar"); 664 menuBar->AddItem(fSwatchMenu); 665 swatchGroup->AddView(menuBar); 666 667 fSwatchGroup = new SwatchGroup(BRect(0, 0, 100, 100)); 668 swatchGroup->AddView(fSwatchGroup); 669 670 swatchGroupView->SetExplicitMaxSize(swatchGroupView->MinSize()); 671 672 // make sure the top side has fixed height 673 topSideView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 674 swatchGroupView->MinSize().height)); 675 676 #else // __HAIKU__ 677 678 BView* bg = new BView(bounds, "bg", B_FOLLOW_ALL, 0); 679 bg->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 680 AddChild(bg); 681 682 BRect menuFrame = bounds; 683 menuFrame.bottom = menuFrame.top + 15; 684 BMenuBar* menuBar = _CreateMenuBar(menuFrame); 685 bg->AddChild(menuBar); 686 float menuWidth; 687 float menuHeight; 688 menuBar->GetPreferredSize(&menuWidth, &menuHeight); 689 menuBar->ResizeTo(splitWidth - 1, menuHeight); 690 menuBar->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 691 692 bounds.top = menuBar->Frame().bottom + 1; 693 694 // swatch group 695 fSwatchGroup = new SwatchGroup(bounds); 696 // SwatchGroup auto resizes itself 697 fSwatchGroup->MoveTo(bounds.right - fSwatchGroup->Bounds().Width(), 698 bounds.top); 699 fSwatchGroup->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); 700 701 bounds.left = fSwatchGroup->Frame().left; 702 bounds.right = bg->Bounds().right; 703 bounds.top = bg->Bounds().top; 704 bounds.bottom = bounds.top + menuHeight; 705 menuBar = new BMenuBar(bounds, "swatches menu bar"); 706 menuBar->AddItem(fSwatchMenu); 707 bg->AddChild(menuBar); 708 menuBar->ResizeTo(bounds.Width(), menuHeight); 709 // menu bars resize themselves to window width 710 menuBar->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); 711 712 // canvas view 713 bounds.left = splitWidth; 714 bounds.top = fSwatchGroup->Frame().bottom + 1; 715 bounds.right = bg->Bounds().right - B_V_SCROLL_BAR_WIDTH; 716 bounds.bottom = bg->Bounds().bottom - B_H_SCROLL_BAR_HEIGHT; 717 fCanvasView = new CanvasView(bounds); 718 719 // scroll view around canvas view 720 bounds.bottom += B_H_SCROLL_BAR_HEIGHT; 721 bounds.right += B_V_SCROLL_BAR_WIDTH; 722 ScrollView* canvasScrollView 723 = new ScrollView(fCanvasView, 724 SCROLL_HORIZONTAL | SCROLL_VERTICAL 725 | SCROLL_VISIBLE_RECT_IS_CHILD_BOUNDS 726 | SCROLL_NO_FRAME, 727 bounds, "canvas scroll view", 728 B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS); 729 730 // icon previews 731 bounds.left = 5; 732 bounds.top = fSwatchGroup->Frame().top + 5; 733 bounds.right = bounds.left + 15; 734 bounds.bottom = bounds.top + 15; 735 fIconPreview16Folder = new IconView(bounds, "icon preview 16 folder"); 736 737 bounds.top = fIconPreview16Folder->Frame().bottom + 5; 738 bounds.bottom = bounds.top + 15; 739 fIconPreview16Menu = new IconView(bounds, "icon preview 16 menu"); 740 fIconPreview16Menu->SetLowColor(ui_color(B_MENU_BACKGROUND_COLOR)); 741 742 bounds.left = fIconPreview16Folder->Frame().right + 5; 743 bounds.top = fSwatchGroup->Frame().top + 5; 744 bounds.right = bounds.left + 31; 745 bounds.bottom = bounds.top + 31; 746 fIconPreview32Folder = new IconView(bounds, "icon preview 32 folder"); 747 748 bounds.top = fIconPreview32Folder->Frame().bottom + 5; 749 bounds.bottom = bounds.top + 31; 750 fIconPreview32Desktop = new IconView(bounds, "icon preview 32 desktop"); 751 fIconPreview32Desktop->SetLowColor(ui_color(B_DESKTOP_COLOR)); 752 753 // bounds.OffsetBy(bounds.Width() + 6, 0); 754 // bounds.right = bounds.left + 47; 755 // bounds.bottom = bounds.top + 47; 756 // fIconPreview48 = new IconView(bounds, "icon preview 48"); 757 758 bounds.left = fIconPreview32Folder->Frame().right + 5; 759 bounds.top = fSwatchGroup->Frame().top + 5; 760 bounds.right = bounds.left + 63; 761 bounds.bottom = bounds.top + 63; 762 fIconPreview64 = new IconView(bounds, "icon preview 64"); 763 fIconPreview64->SetLowColor(ui_color(B_DESKTOP_COLOR)); 764 765 // style list view 766 bounds.left = fCanvasView->Frame().left; 767 bounds.right = bounds.left + splitWidth; 768 bounds.top = bg->Bounds().top; 769 bounds.bottom = bounds.top + menuHeight; 770 menuBar = new BMenuBar(bounds, "style menu bar"); 771 menuBar->AddItem(fStyleMenu); 772 bg->AddChild(menuBar); 773 menuBar->ResizeTo(bounds.Width(), menuHeight); 774 // menu bars resize themselves to window width 775 menuBar->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 776 777 bounds.right -= B_V_SCROLL_BAR_WIDTH + 1; 778 bounds.top = menuBar->Frame().bottom + 1; 779 bounds.bottom = fCanvasView->Frame().top - 1; 780 781 fStyleListView = new StyleListView(bounds, "style list view", 782 new BMessage(MSG_STYLE_SELECTED), this); 783 784 785 // style view 786 bounds.left = menuBar->Frame().right + 1; 787 bounds.top = bg->Bounds().top; 788 bounds.right = fSwatchGroup->Frame().left - 1; 789 bounds.bottom = fCanvasView->Frame().top - 1; 790 fStyleView = new StyleView(bounds); 791 fStyleView->SetResizingMode(B_FOLLOW_TOP | B_FOLLOW_LEFT_RIGHT); 792 bg->AddChild(fStyleView); 793 794 // path list view 795 bounds.left = 0; 796 bounds.right = fCanvasView->Frame().left - 1; 797 bounds.top = fCanvasView->Frame().top; 798 bounds.bottom = bounds.top + menuHeight; 799 menuBar = new BMenuBar(bounds, "path menu bar"); 800 menuBar->AddItem(fPathMenu); 801 bg->AddChild(menuBar); 802 menuBar->ResizeTo(bounds.Width(), menuHeight); 803 // menu bars resize themselves to window width 804 menuBar->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 805 806 bounds.right -= B_V_SCROLL_BAR_WIDTH + 1; 807 bounds.top = menuBar->Frame().bottom + 1; 808 bounds.bottom = bounds.top + 130; 809 810 fPathListView = new PathListView(bounds, "path list view", 811 new BMessage(MSG_PATH_SELECTED), this); 812 813 814 // shape list view 815 bounds.right += B_V_SCROLL_BAR_WIDTH + 1; 816 bounds.top = fPathListView->Frame().bottom + 1; 817 bounds.bottom = bounds.top + menuHeight; 818 menuBar = new BMenuBar(bounds, "shape menu bar"); 819 menuBar->AddItem(fShapeMenu); 820 bg->AddChild(menuBar); 821 menuBar->ResizeTo(bounds.Width(), menuHeight); 822 // menu bars resize themselves to window width 823 menuBar->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 824 825 bounds.right -= B_V_SCROLL_BAR_WIDTH + 1; 826 bounds.top = menuBar->Frame().bottom + 1; 827 bounds.bottom = bounds.top + 130; 828 829 fShapeListView = new ShapeListView(bounds, "shape list view", 830 new BMessage(MSG_SHAPE_SELECTED), this); 831 832 // transformer list view 833 bounds.right += B_V_SCROLL_BAR_WIDTH + 1; 834 bounds.top = fShapeListView->Frame().bottom + 1; 835 bounds.bottom = bounds.top + menuHeight; 836 menuBar = new BMenuBar(bounds, "transformer menu bar"); 837 menuBar->AddItem(fTransformerMenu); 838 bg->AddChild(menuBar); 839 menuBar->ResizeTo(bounds.Width(), bounds.Height()); 840 // menu bars resize themselves to window width 841 menuBar->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 842 843 bounds.right -= B_V_SCROLL_BAR_WIDTH + 1; 844 bounds.top = menuBar->Frame().bottom + 1; 845 bounds.bottom = bounds.top + 80; 846 fTransformerListView = new TransformerListView(bounds, 847 "transformer list view"); 848 849 // property list view 850 bounds.right += B_V_SCROLL_BAR_WIDTH + 1; 851 bounds.top = fTransformerListView->Frame().bottom + 1; 852 bounds.bottom = bounds.top + menuHeight; 853 menuBar = new BMenuBar(bounds, "property menu bar"); 854 menuBar->AddItem(fPropertyMenu); 855 bg->AddChild(menuBar); 856 menuBar->ResizeTo(bounds.Width(), bounds.Height()); 857 // menu bars resize themselves to window width 858 menuBar->SetResizingMode(B_FOLLOW_LEFT | B_FOLLOW_TOP); 859 860 fPropertyListView = new IconObjectListView(); 861 862 bg->AddChild(fSwatchGroup); 863 864 bg->AddChild(fIconPreview16Folder); 865 bg->AddChild(fIconPreview16Menu); 866 bg->AddChild(fIconPreview32Folder); 867 bg->AddChild(fIconPreview32Desktop); 868 // bg->AddChild(fIconPreview48); 869 bg->AddChild(fIconPreview64); 870 871 bg->AddChild(new BScrollView("path list scroll view", 872 fPathListView, 873 B_FOLLOW_LEFT | B_FOLLOW_TOP, 874 0, false, true, 875 B_NO_BORDER)); 876 bg->AddChild(new BScrollView("style list scroll view", 877 fStyleListView, 878 B_FOLLOW_LEFT | B_FOLLOW_TOP, 879 0, false, true, 880 B_NO_BORDER)); 881 bg->AddChild(new BScrollView("shape list scroll view", 882 fShapeListView, 883 B_FOLLOW_LEFT | B_FOLLOW_TOP, 884 0, false, true, 885 B_NO_BORDER)); 886 bg->AddChild(new BScrollView("transformer list scroll view", 887 fTransformerListView, 888 B_FOLLOW_LEFT | B_FOLLOW_TOP, 889 0, false, true, 890 B_NO_BORDER)); 891 892 // scroll view around property list view 893 bounds.top = menuBar->Frame().bottom + 1; 894 bounds.bottom = bg->Bounds().bottom; 895 bg->AddChild(new ScrollView(fPropertyListView, 896 SCROLL_VERTICAL | SCROLL_NO_FRAME, 897 bounds, "property scroll view", 898 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM, 899 B_WILL_DRAW | B_FRAME_EVENTS)); 900 901 902 bg->AddChild(canvasScrollView); 903 #endif // __HAIKU__ 904 } 905 906 // _CreateMenuBar 907 BMenuBar* 908 MainWindow::_CreateMenuBar(BRect frame) 909 { 910 BMenuBar* menuBar = new BMenuBar(frame, "main menu"); 911 912 BMenu* fileMenu = new BMenu("File"); 913 BMenu* editMenu = new BMenu("Edit"); 914 BMenu* settingsMenu = new BMenu("Options"); 915 fPathMenu = new BMenu("Path"); 916 fStyleMenu = new BMenu("Style"); 917 fShapeMenu = new BMenu("Shape"); 918 fTransformerMenu = new BMenu("Transformer"); 919 fPropertyMenu = new BMenu("Property"); 920 fSwatchMenu = new BMenu("Swatches"); 921 922 menuBar->AddItem(fileMenu); 923 menuBar->AddItem(editMenu); 924 menuBar->AddItem(settingsMenu); 925 926 // File 927 fileMenu->AddItem(new BMenuItem("New", 928 new BMessage(MSG_NEW), 929 'N')); 930 fileMenu->AddItem(new BMenuItem("Open", 931 new BMessage(MSG_OPEN), 932 'O')); 933 fileMenu->AddItem(new BMenuItem("Append", 934 new BMessage(MSG_APPEND), 935 'O', B_SHIFT_KEY)); 936 fileMenu->AddSeparatorItem(); 937 fileMenu->AddItem(new BMenuItem("Save", 938 new BMessage(MSG_SAVE), 939 'S')); 940 fileMenu->AddItem(new BMenuItem("Save As", 941 new BMessage(MSG_SAVE_AS), 942 'S', B_SHIFT_KEY)); 943 fileMenu->AddSeparatorItem(); 944 fileMenu->AddItem(new BMenuItem("Export", 945 new BMessage(MSG_EXPORT), 946 'E')); 947 fileMenu->AddItem(new BMenuItem("Export As", 948 new BMessage(MSG_EXPORT_AS), 949 'E', B_SHIFT_KEY)); 950 fileMenu->AddSeparatorItem(); 951 fileMenu->AddItem(new BMenuItem("Quit", 952 new BMessage(B_QUIT_REQUESTED), 953 'Q')); 954 fileMenu->SetTargetForItems(be_app); 955 956 // Edit 957 fUndoMI = new BMenuItem("<nothing to undo>", 958 new BMessage(MSG_UNDO), 'Z'); 959 fRedoMI = new BMenuItem("<nothing to redo>", 960 new BMessage(MSG_REDO), 'Z', B_SHIFT_KEY); 961 962 fUndoMI->SetEnabled(false); 963 fRedoMI->SetEnabled(false); 964 965 editMenu->AddItem(fUndoMI); 966 editMenu->AddItem(fRedoMI); 967 968 // Settings 969 BMenu* filterModeMenu = new BMenu("Snap to Grid"); 970 BMessage* message = new BMessage(MSG_MOUSE_FILTER_MODE); 971 message->AddInt32("mode", SNAPPING_OFF); 972 filterModeMenu->AddItem(new BMenuItem("Off", message)); 973 974 message = new BMessage(MSG_MOUSE_FILTER_MODE); 975 message->AddInt32("mode", SNAPPING_64); 976 filterModeMenu->AddItem(new BMenuItem("64 x 64", message)); 977 978 message = new BMessage(MSG_MOUSE_FILTER_MODE); 979 message->AddInt32("mode", SNAPPING_32); 980 filterModeMenu->AddItem(new BMenuItem("32 x 32", message)); 981 982 message = new BMessage(MSG_MOUSE_FILTER_MODE); 983 message->AddInt32("mode", SNAPPING_16); 984 filterModeMenu->AddItem(new BMenuItem("16 x 16", message)); 985 986 filterModeMenu->ItemAt(0)->SetMarked(true); 987 filterModeMenu->SetRadioMode(true); 988 989 settingsMenu->AddItem(filterModeMenu); 990 991 return menuBar; 992 } 993 994 //// _CreateDefaultIcon 995 //void 996 //MainWindow::_CreateDefaultIcon() 997 //{ 998 // // add some stuff to an empty document (NOTE: for testing only) 999 // VectorPath* path = new VectorPath(); 1000 // 1001 // fDocument->Icon()->Paths()->AddPath(path); 1002 // 1003 // Style* style1 = new Style(); 1004 // style1->SetName("Style White"); 1005 // style1->SetColor((rgb_color){ 255, 255, 255, 255 }); 1006 // 1007 // fDocument->Icon()->Styles()->AddStyle(style1); 1008 // 1009 // Style* style2 = new Style(); 1010 // style2->SetName("Style Gradient"); 1011 // Gradient gradient(true); 1012 // gradient.AddColor((rgb_color){ 255, 211, 6, 255 }, 0.0); 1013 // gradient.AddColor((rgb_color){ 255, 238, 160, 255 }, 0.5); 1014 // gradient.AddColor((rgb_color){ 208, 43, 92, 255 }, 1.0); 1015 // style2->SetGradient(&gradient); 1016 // 1017 // fDocument->Icon()->Styles()->AddStyle(style2); 1018 // 1019 // Shape* shape = new Shape(style2); 1020 // shape->Paths()->AddPath(path); 1021 // 1022 // shape->SetName("Gradient"); 1023 // fDocument->Icon()->Shapes()->AddShape(shape); 1024 // 1025 // shape = new Shape(style1); 1026 // shape->Paths()->AddPath(path); 1027 // StrokeTransformer* transformer 1028 // = new StrokeTransformer(shape->VertexSource()); 1029 // transformer->width(5.0); 1030 // shape->AddTransformer(transformer); 1031 // 1032 // shape->SetName("Outline"); 1033 // fDocument->Icon()->Shapes()->AddShape(shape); 1034 // 1035 // Style* style3 = new Style(); 1036 // style3->SetName("Style Red"); 1037 // style3->SetColor((rgb_color){ 255, 0, 169,200 }); 1038 // 1039 // fDocument->Icon()->Styles()->AddStyle(style3); 1040 // 1041 // shape = new Shape(style3); 1042 // shape->Paths()->AddPath(path); 1043 // AffineTransformer* transformer2 1044 // = new AffineTransformer(shape->VertexSource()); 1045 // *transformer2 *= agg::trans_affine_translation(10.0, 6.0); 1046 // *transformer2 *= agg::trans_affine_rotation(0.2); 1047 // *transformer2 *= agg::trans_affine_scaling(0.8, 0.6); 1048 // shape->AddTransformer(transformer2); 1049 // 1050 // shape->SetName("Transformed"); 1051 // fDocument->Icon()->Shapes()->AddShape(shape); 1052 // 1053 // PathManipulator* pathManipulator = new PathManipulator(path); 1054 // fState->AddManipulator(pathManipulator); 1055 //} 1056