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