// _AddStyle status_t StyledTextImporter::_AddStyle(Icon *icon, text_run *run) { CALLED(); if (!run) return EINVAL; rgb_color color = run->color; Style* style = new (nothrow) Style(color); if (!style) { delete style; return B_NO_MEMORY; } char name[30]; sprintf(name, "Color (#%02x%02x%02x)", color.red, color.green, color.blue); style->SetName(name); bool found = false; for (int i = 0; i < fStyleCount; i++) { if (*style == *(fStyleMap[i].style)) { delete style; style = fStyleMap[i].style; found = true; break; } } if (!found && !icon->Styles()->AddStyle(style)) { delete style; return B_NO_MEMORY; } fStyleMap[fStyleCount].run = run; fStyleMap[fStyleCount].style = style; fStyleCount++; return B_OK; }
void MainWindow::MessageReceived(BMessage* message) { bool discard = false; // Figure out if we need the write lock on the Document. For most // messages we do, but exporting takes place in another thread and // locking is taken care of there. bool requiresWriteLock = true; switch (message->what) { case MSG_SAVE: case MSG_EXPORT: case MSG_SAVE_AS: case MSG_EXPORT_AS: requiresWriteLock = false; break; default: break; } if (requiresWriteLock && !fDocument->WriteLock()) { BWindow::MessageReceived(message); return; } if (message->WasDropped()) { const rgb_color* color; ssize_t length; // create styles from dropped colors for (int32 i = 0; message->FindData("RGBColor", B_RGB_COLOR_TYPE, i, (const void**)&color, &length) == B_OK; i++) { if (length != sizeof(rgb_color)) continue; char name[30]; sprintf(name, B_TRANSLATE_CONTEXT("Color (#%02x%02x%02x)", "Style name after dropping a color"), color->red, color->green, color->blue); Style* style = new (nothrow) Style(*color); style->SetName(name); Style* styles[1] = { style }; AddStylesCommand* styleCommand = new (nothrow) AddStylesCommand( fDocument->Icon()->Styles(), styles, 1, fDocument->Icon()->Styles()->CountStyles()); fDocument->CommandStack()->Perform(styleCommand); // don't handle anything else, // or we might paste the clipboard on B_PASTE discard = true; } } switch (message->what) { case B_REFS_RECEIVED: case B_SIMPLE_DATA: // If our icon is empty, open the file in this window, // otherwise forward to the application which will open // it in another window, unless we append. message->what = B_REFS_RECEIVED; if (fDocument->Icon()->Styles()->CountStyles() == 0 && fDocument->Icon()->Paths()->CountPaths() == 0 && fDocument->Icon()->Shapes()->CountShapes() == 0) { entry_ref ref; if (message->FindRef("refs", &ref) == B_OK) Open(ref); break; } if (modifiers() & B_SHIFT_KEY) { // We want the icon appended to this window. message->AddBool("append", true); message->AddPointer("window", this); } be_app->PostMessage(message); break; case B_PASTE: case B_MIME_DATA: { BMessage* clip = message; status_t err; if (discard) break; if (message->what == B_PASTE) { if (!be_clipboard->Lock()) break; clip = be_clipboard->Data(); } if (!clip || !clip->HasData("text/plain", B_MIME_TYPE)) { if (message->what == B_PASTE) be_clipboard->Unlock(); break; } Icon* icon = new (std::nothrow) Icon(*fDocument->Icon()); if (icon != NULL) { StyledTextImporter importer; err = importer.Import(icon, clip); if (err >= B_OK) { AutoWriteLocker locker(fDocument); SetIcon(NULL); // incorporate the loaded icon into the document // (either replace it or append to it) fDocument->MakeEmpty(false); // if append, the document savers are preserved fDocument->SetIcon(icon); SetIcon(icon); } } if (message->what == B_PASTE) be_clipboard->Unlock(); break; } case MSG_OPEN: // If our icon is empty, we want the icon to open in this // window. if (fDocument->Icon()->Styles()->CountStyles() == 0 && fDocument->Icon()->Paths()->CountPaths() == 0 && fDocument->Icon()->Shapes()->CountShapes() == 0) { message->AddPointer("window", this); } be_app->PostMessage(message); break; case MSG_SAVE: case MSG_EXPORT: { DocumentSaver* saver; if (message->what == MSG_SAVE) saver = fDocument->NativeSaver(); else saver = fDocument->ExportSaver(); if (saver != NULL) { saver->Save(fDocument); _PickUpActionBeforeSave(); break; } // else fall through } case MSG_SAVE_AS: case MSG_EXPORT_AS: { int32 exportMode; if (message->FindInt32("export mode", &exportMode) < B_OK) exportMode = EXPORT_MODE_MESSAGE; entry_ref ref; const char* name; if (message->FindRef("directory", &ref) == B_OK && message->FindString("name", &name) == B_OK) { // this message comes from the file panel BDirectory dir(&ref); BEntry entry; if (dir.InitCheck() >= B_OK && entry.SetTo(&dir, name, true) >= B_OK && entry.GetRef(&ref) >= B_OK) { // create the document saver and remember it for later DocumentSaver* saver = _CreateSaver(ref, exportMode); if (saver != NULL) { if (fDocument->WriteLock()) { if (exportMode == EXPORT_MODE_MESSAGE) fDocument->SetNativeSaver(saver); else fDocument->SetExportSaver(saver); _UpdateWindowTitle(); fDocument->WriteUnlock(); } saver->Save(fDocument); _PickUpActionBeforeSave(); } } // TODO: ... // _SyncPanels(fSavePanel, fOpenPanel); } else { // configure the file panel uint32 requestRefWhat = MSG_SAVE_AS; bool isExportMode = message->what == MSG_EXPORT_AS || message->what == MSG_EXPORT; if (isExportMode) requestRefWhat = MSG_EXPORT_AS; const char* saveText = _FileName(isExportMode); BMessage requestRef(requestRefWhat); if (saveText != NULL) requestRef.AddString("save text", saveText); requestRef.AddMessenger("target", BMessenger(this, this)); be_app->PostMessage(&requestRef); } break; } case B_CANCEL: // FilePanel was canceled, do not execute the fMessageAfterSave // next time a file panel is used, in case it was set! delete fMessageAfterSave; fMessageAfterSave = NULL; break; case MSG_UNDO: fDocument->CommandStack()->Undo(); break; case MSG_REDO: fDocument->CommandStack()->Redo(); break; case MSG_UNDO_STACK_CHANGED: { // relable Undo item and update enabled status BString label(B_TRANSLATE("Undo")); fUndoMI->SetEnabled(fDocument->CommandStack()->GetUndoName(label)); if (fUndoMI->IsEnabled()) fUndoMI->SetLabel(label.String()); else { fUndoMI->SetLabel(B_TRANSLATE_CONTEXT("<nothing to undo>", "Icon-O-Matic-Menu-Edit")); } // relable Redo item and update enabled status label.SetTo(B_TRANSLATE("Redo")); fRedoMI->SetEnabled(fDocument->CommandStack()->GetRedoName(label)); if (fRedoMI->IsEnabled()) fRedoMI->SetLabel(label.String()); else { fRedoMI->SetLabel(B_TRANSLATE_CONTEXT("<nothing to redo>", "Icon-O-Matic-Menu-Edit")); } break; } case MSG_MOUSE_FILTER_MODE: { uint32 mode; if (message->FindInt32("mode", (int32*)&mode) == B_OK) fCanvasView->SetMouseFilterMode(mode); break; } case MSG_ADD_SHAPE: { AddStylesCommand* styleCommand = NULL; Style* style = NULL; if (message->HasBool("style")) { new_style(fCurrentColor->Color(), fDocument->Icon()->Styles(), &style, &styleCommand); } AddPathsCommand* pathCommand = NULL; VectorPath* path = NULL; if (message->HasBool("path")) { new_path(fDocument->Icon()->Paths(), &path, &pathCommand); } if (!style) { // use current or first style int32 currentStyle = fStyleListView->CurrentSelection(0); style = fDocument->Icon()->Styles()->StyleAt(currentStyle); if (!style) style = fDocument->Icon()->Styles()->StyleAt(0); } Shape* shape = new (nothrow) Shape(style); Shape* shapes[1]; shapes[0] = shape; AddShapesCommand* shapeCommand = new (nothrow) AddShapesCommand( fDocument->Icon()->Shapes(), shapes, 1, fDocument->Icon()->Shapes()->CountShapes(), fDocument->Selection()); if (path && shape) shape->Paths()->AddPath(path); ::Command* command = NULL; if (styleCommand || pathCommand) { if (styleCommand && pathCommand) { Command** commands = new Command*[3]; commands[0] = styleCommand; commands[1] = pathCommand; commands[2] = shapeCommand; command = new CompoundCommand(commands, 3, B_TRANSLATE_CONTEXT("Add shape with path & style", "Icon-O-Matic-Menu-Shape"), 0); } else if (styleCommand) { Command** commands = new Command*[2]; commands[0] = styleCommand; commands[1] = shapeCommand; command = new CompoundCommand(commands, 2, B_TRANSLATE_CONTEXT("Add shape with style", "Icon-O-Matic-Menu-Shape"), 0); } else { Command** commands = new Command*[2]; commands[0] = pathCommand; commands[1] = shapeCommand; command = new CompoundCommand(commands, 2, B_TRANSLATE_CONTEXT("Add shape with path", "Icon-O-Matic-Menu-Shape"), 0); } } else { command = shapeCommand; } fDocument->CommandStack()->Perform(command); break; } // TODO: listen to selection in CanvasView to add a manipulator case MSG_PATH_SELECTED: { VectorPath* path; if (message->FindPointer("path", (void**)&path) < B_OK) path = NULL; fPathListView->SetCurrentShape(NULL); fStyleListView->SetCurrentShape(NULL); fTransformerListView->SetShape(NULL); fState->DeleteManipulators(); if (fDocument->Icon()->Paths()->HasPath(path)) { PathManipulator* pathManipulator = new (nothrow) PathManipulator(path); fState->AddManipulator(pathManipulator); } break; } case MSG_STYLE_SELECTED: case MSG_STYLE_TYPE_CHANGED: { Style* style; if (message->FindPointer("style", (void**)&style) < B_OK) style = NULL; if (!fDocument->Icon()->Styles()->HasStyle(style)) style = NULL; fStyleView->SetStyle(style); fPathListView->SetCurrentShape(NULL); fStyleListView->SetCurrentShape(NULL); fTransformerListView->SetShape(NULL); fState->DeleteManipulators(); Gradient* gradient = style ? style->Gradient() : NULL; if (gradient != NULL) { TransformGradientBox* transformBox = new (nothrow) TransformGradientBox(fCanvasView, gradient, NULL); fState->AddManipulator(transformBox); } break; } case MSG_SHAPE_SELECTED: { Shape* shape; if (message->FindPointer("shape", (void**)&shape) < B_OK) shape = NULL; if (!fIcon || !fIcon->Shapes()->HasShape(shape)) shape = NULL; fPathListView->SetCurrentShape(shape); fStyleListView->SetCurrentShape(shape); fTransformerListView->SetShape(shape); BList selectedShapes; ShapeContainer* shapes = fDocument->Icon()->Shapes(); int32 count = shapes->CountShapes(); for (int32 i = 0; i < count; i++) { shape = shapes->ShapeAtFast(i); if (shape->IsSelected()) { selectedShapes.AddItem((void*)shape); } } fState->DeleteManipulators(); if (selectedShapes.CountItems() > 0) { TransformShapesBox* transformBox = new (nothrow) TransformShapesBox( fCanvasView, (const Shape**)selectedShapes.Items(), selectedShapes.CountItems()); fState->AddManipulator(transformBox); } break; } case MSG_RENAME_OBJECT: fPropertyListView->FocusNameProperty(); break; default: BWindow::MessageReceived(message); } if (requiresWriteLock) fDocument->WriteUnlock(); }