void MainWindow::clickTab(Tabs* tabs, TabView* tabView, ui::MouseButtons buttons) { if (!tabView) return; WorkspaceView* workspaceView = dynamic_cast<WorkspaceView*>(tabView); if (m_workspace->getActiveView() != workspaceView) m_workspace->setActiveView(workspaceView); DocumentView* docView = dynamic_cast<DocumentView*>(workspaceView); if (!docView) return; UIContext* context = UIContext::instance(); context->setActiveView(docView); context->updateFlags(); // Right-button: popup-menu if (buttons & kButtonRight) { Menu* popup_menu = AppMenus::instance()->getDocumentTabPopupMenu(); if (popup_menu != NULL) { popup_menu->showPopup(jmouse_x(0), jmouse_y(0)); } } // Middle-button: close the sprite else if (buttons & kButtonMiddle) { Command* close_file_cmd = CommandsModule::instance()->getCommandByName(CommandId::CloseFile); context->executeCommand(close_file_cmd, NULL); } }
bool PlayState::onMouseDown(Editor* editor, MouseMessage* msg) { if (editor->hasCapture()) return true; // When an editor is clicked the current view is changed. UIContext* context = UIContext::instance(); context->setActiveView(editor->getDocumentView()); // A click with right-button stops the animation if (msg->buttons() == kButtonRight) { editor->stop(); return true; } // Set this flag to indicate that we are going to ScrollingState for // some time, so we don't change the current frame. m_toScroll = true; // Start scroll loop EditorStatePtr newState(new ScrollingState()); editor->setState(newState); newState->onMouseDown(editor, msg); return true; }
bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg) { if (editor->hasCapture()) return true; UIContext* context = UIContext::instance(); tools::Ink* clickedInk = editor->getCurrentEditorInk(); Site site; editor->getSite(&site); app::Document* document = static_cast<app::Document*>(site.document()); Layer* layer = site.layer(); // When an editor is clicked the current view is changed. context->setActiveView(editor->getDocumentView()); // Start scroll loop if (checkForScroll(editor, msg) || checkForZoom(editor, msg)) return true; // Move cel X,Y coordinates if (clickedInk->isCelMovement()) { // Handle "Auto Select Layer" if (editor->isAutoSelectLayer()) { gfx::Point cursor = editor->screenToEditor(msg->position()); ColorPicker picker; picker.pickColor(site, cursor, ColorPicker::FromComposition); if (layer != picker.layer()) { layer = picker.layer(); if (layer) { editor->setLayer(layer); editor->flashCurrentLayer(); } } } if ((layer) && (layer->type() == ObjectType::LayerImage)) { // TODO we should be able to move the `Background' with tiled mode if (layer->isBackground()) { StatusBar::instance()->showTip(1000, "The background layer cannot be moved"); } else if (!layer->isVisible()) { StatusBar::instance()->showTip(1000, "Layer '%s' is hidden", layer->name().c_str()); } else if (!layer->isMovable() || !layer->isEditable()) { StatusBar::instance()->showTip(1000, "Layer '%s' is locked", layer->name().c_str()); } else { // Change to MovingCelState editor->setState(EditorStatePtr(new MovingCelState(editor, msg))); } } return true; } // Call the eyedropper command if (clickedInk->isEyedropper()) { callEyedropper(editor); return true; } if (clickedInk->isSelection()) { // Transform selected pixels if (document->isMaskVisible() && m_decorator->getTransformHandles(editor)) { TransformHandles* transfHandles = m_decorator->getTransformHandles(editor); // Get the handle covered by the mouse. HandleType handle = transfHandles->getHandleAtPoint(editor, msg->position(), document->getTransformation()); if (handle != NoHandle) { int x, y, opacity; Image* image = site.image(&x, &y, &opacity); if (layer && image) { if (!layer->isEditable()) { StatusBar::instance()->showTip(1000, "Layer '%s' is locked", layer->name().c_str()); return true; } // Change to MovingPixelsState transformSelection(editor, msg, handle); } return true; } } // Move selected pixels if (layer && editor->isInsideSelection() && msg->left()) { if (!layer->isEditable()) { StatusBar::instance()->showTip(1000, "Layer '%s' is locked", layer->name().c_str()); return true; } // Change to MovingPixelsState transformSelection(editor, msg, MoveHandle); return true; } } // Start the Tool-Loop if (layer) { tools::ToolLoop* toolLoop = create_tool_loop(editor, context); if (toolLoop) { EditorStatePtr newState(new DrawingState(toolLoop)); editor->setState(newState); static_cast<DrawingState*>(newState.get()) ->initToolLoop(editor, msg); } return true; } return true; }
// Manager event handler. bool CustomizedGuiManager::onProcessMessage(Message* msg) { switch (msg->type()) { case kCloseDisplayMessage: { // Execute the "Exit" command. Command* command = CommandsModule::instance()->getCommandByName(CommandId::Exit); UIContext::instance()->executeCommand(command); } break; case kDropFilesMessage: { // If the main window is not the current foreground one. We // discard the drop-files event. if (getForegroundWindow() != App::instance()->getMainWindow()) break; const DropFilesMessage::Files& files = static_cast<DropFilesMessage*>(msg)->files(); // Open all files Command* cmd_open_file = CommandsModule::instance()->getCommandByName(CommandId::OpenFile); Params params; UIContext* ctx = UIContext::instance(); for (const auto& fn : files) { // If the document is already open, select it. Document* doc = static_cast<Document*>(ctx->documents().getByFileName(fn)); if (doc) { DocumentView* docView = ctx->getFirstDocumentView(doc); if (docView) ctx->setActiveView(docView); else { ASSERT(false); // Must be some DocumentView available } } // Load the file else { params.set("filename", fn.c_str()); ctx->executeCommand(cmd_open_file, params); } } } break; case kKeyDownMessage: { #ifdef _DEBUG // Left Shift+Ctrl+Q generates a crash (useful to test the anticrash feature) if (msg->ctrlPressed() && msg->shiftPressed() && static_cast<KeyMessage*>(msg)->scancode() == kKeyQ) { int* p = nullptr; *p = 0; } #endif // Call base impl to check if there is a foreground window as // top level that needs keys. (In this way we just do not // process keyboard shortcuts for menus and tools). if (Manager::onProcessMessage(msg)) return true; for (const Key* key : *KeyboardShortcuts::instance()) { if (key->isPressed(msg)) { // Cancel menu-bar loops (to close any popup menu) App::instance()->getMainWindow()->getMenuBar()->cancelMenuLoop(); switch (key->type()) { case KeyType::Tool: { tools::Tool* current_tool = App::instance()->activeTool(); tools::Tool* select_this_tool = key->tool(); tools::ToolBox* toolbox = App::instance()->getToolBox(); std::vector<tools::Tool*> possibles; // Collect all tools with the pressed keyboard-shortcut for (tools::Tool* tool : *toolbox) { Key* key = KeyboardShortcuts::instance()->tool(tool); if (key && key->isPressed(msg)) possibles.push_back(tool); } if (possibles.size() >= 2) { bool done = false; for (size_t i=0; i<possibles.size(); ++i) { if (possibles[i] != current_tool && ToolBar::instance()->isToolVisible(possibles[i])) { select_this_tool = possibles[i]; done = true; break; } } if (!done) { for (size_t i=0; i<possibles.size(); ++i) { // If one of the possibilities is the current tool if (possibles[i] == current_tool) { // We select the next tool in the possibilities select_this_tool = possibles[(i+1) % possibles.size()]; break; } } } } ToolBar::instance()->selectTool(select_this_tool); return true; } case KeyType::Command: { Command* command = key->command(); // Commands are executed only when the main window is // the current window running at foreground. UI_FOREACH_WIDGET(getChildren(), it) { Window* child = static_cast<Window*>(*it); // There are a foreground window executing? if (child->isForeground()) { break; } // Is it the desktop and the top-window= else if (child->isDesktop() && child == App::instance()->getMainWindow()) { // OK, so we can execute the command represented // by the pressed-key in the message... UIContext::instance()->executeCommand( command, key->params()); return true; } } break; } case KeyType::Quicktool: { // Do nothing, it is used in the editor through the // KeyboardShortcuts::getCurrentQuicktool() function. break; } } break; } } break; }
bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg) { if (editor->hasCapture()) return true; UIContext* context = UIContext::instance(); tools::Ink* clickedInk = editor->getCurrentEditorInk(); Site site; editor->getSite(&site); app::Document* document = static_cast<app::Document*>(site.document()); Layer* layer = site.layer(); // When an editor is clicked the current view is changed. context->setActiveView(editor->getDocumentView()); // Start scroll loop if (checkForScroll(editor, msg) || checkForZoom(editor, msg)) return true; // Move cel X,Y coordinates if (clickedInk->isCelMovement()) { // Handle "Auto Select Layer" if (editor->isAutoSelectLayer()) { gfx::Point cursor = editor->screenToEditor(msg->position()); ColorPicker picker; picker.pickColor(site, cursor, ColorPicker::FromComposition); DocumentRange range = App::instance()->getMainWindow()->getTimeline()->range(); // Change layer only when the layer is diffrent from current one, and // the range we selected is not with multiple cels. bool layerChanged = (layer != picker.layer()); bool rangeEnabled = range.enabled(); bool rangeSingleCel = ((range.type() == DocumentRange::kCels) && (range.layers() == 1) && (range.frames() == 1)); if (layerChanged && (!rangeEnabled || rangeSingleCel)) { layer = picker.layer(); if (layer) { editor->setLayer(layer); editor->flashCurrentLayer(); } } } if ((layer) && (layer->type() == ObjectType::LayerImage)) { // TODO we should be able to move the `Background' with tiled mode if (layer->isBackground()) { StatusBar::instance()->showTip(1000, "The background layer cannot be moved"); } else if (!layer->isVisible()) { StatusBar::instance()->showTip(1000, "Layer '%s' is hidden", layer->name().c_str()); } else if (!layer->isMovable() || !layer->isEditable()) { StatusBar::instance()->showTip(1000, "Layer '%s' is locked", layer->name().c_str()); } else if (!layer->cel(editor->frame())) { StatusBar::instance()->showTip(1000, "Cel is empty, nothing to move"); } else { // Change to MovingCelState editor->setState(EditorStatePtr(new MovingCelState(editor, msg))); } } return true; } // Call the eyedropper command if (clickedInk->isEyedropper()) { editor->captureMouse(); callEyedropper(editor); return true; } if (clickedInk->isSelection()) { // Transform selected pixels if (editor->isActive() && document->isMaskVisible() && m_decorator->getTransformHandles(editor)) { TransformHandles* transfHandles = m_decorator->getTransformHandles(editor); // Get the handle covered by the mouse. HandleType handle = transfHandles->getHandleAtPoint(editor, msg->position(), document->getTransformation()); if (handle != NoHandle) { int x, y, opacity; Image* image = site.image(&x, &y, &opacity); if (layer && image) { if (!layer->isEditable()) { StatusBar::instance()->showTip(1000, "Layer '%s' is locked", layer->name().c_str()); return true; } // Change to MovingPixelsState transformSelection(editor, msg, handle); } return true; } } // Move selected pixels if (layer && editor->isInsideSelection() && msg->left()) { if (!layer->isEditable()) { StatusBar::instance()->showTip(1000, "Layer '%s' is locked", layer->name().c_str()); return true; } // Change to MovingPixelsState transformSelection(editor, msg, MoveHandle); return true; } } // Move symmetry gfx::Rect box1, box2; if (m_decorator->getSymmetryHandles(editor, box1, box2) && (box1.contains(msg->position()) || box2.contains(msg->position()))) { auto& symmetry = Preferences::instance().document(editor->document()).symmetry; auto mode = symmetry.mode(); bool horz = (mode == app::gen::SymmetryMode::HORIZONTAL); auto& axis = (horz ? symmetry.xAxis: symmetry.yAxis); editor->setState( EditorStatePtr(new MovingSymmetryState(editor, msg, mode, axis))); return true; } // Start the Tool-Loop if (layer) { tools::ToolLoop* toolLoop = create_tool_loop(editor, context); if (toolLoop) { EditorStatePtr newState(new DrawingState(toolLoop)); editor->setState(newState); static_cast<DrawingState*>(newState.get()) ->initToolLoop(editor, msg); } return true; } return true; }
bool MovingPixelsState::onMouseDown(Editor* editor, MouseMessage* msg) { ASSERT(m_pixelsMovement != NULL); // Set this editor as the active one and setup the ContextBar for // moving pixels. This is needed in case that the user is working // with a couple of Editors, in one is moving pixels and the other // one not. UIContext* ctx = UIContext::instance(); ctx->setActiveView(editor->getDocumentView()); ContextBar* contextBar = App::instance()->getMainWindow()->getContextBar(); contextBar->updateForMovingPixels(); // Start scroll loop if (checkForScroll(editor, msg)) return true; Decorator* decorator = static_cast<Decorator*>(editor->decorator()); Document* document = editor->document(); // Transform selected pixels if (document->isMaskVisible() && decorator->getTransformHandles(editor)) { TransformHandles* transfHandles = decorator->getTransformHandles(editor); // Get the handle covered by the mouse. HandleType handle = transfHandles->getHandleAtPoint(editor, msg->position(), getTransformation(editor)); if (handle != NoHandle) { // Re-catch the image int x, y; editor->screenToEditor(msg->position().x, msg->position().y, &x, &y); m_pixelsMovement->catchImageAgain(x, y, handle); editor->captureMouse(); return true; } } // Start "moving pixels" loop if (editor->isInsideSelection() && (msg->left() || msg->right())) { // In case that the user is pressing the copy-selection keyboard shortcut. EditorCustomizationDelegate* customization = editor->getCustomizationDelegate(); if (customization && customization->isCopySelectionKeyPressed()) { // Stamp the pixels to create the copy. m_pixelsMovement->stampImage(); } // Re-catch the image int x, y; editor->screenToEditor(msg->position().x, msg->position().y, &x, &y); m_pixelsMovement->catchImageAgain(x, y, MoveHandle); editor->captureMouse(); return true; } // End "moving pixels" loop else { // Drop pixels (e.g. to start drawing) dropPixels(editor); } // Use StandbyState implementation return StandbyState::onMouseDown(editor, msg); }
bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg) { if (editor->hasCapture()) return true; UIContext* context = UIContext::instance(); tools::Tool* currentTool = editor->getCurrentEditorTool(); tools::Ink* clickedInk = editor->getCurrentEditorInk(); DocumentLocation location; editor->getDocumentLocation(&location); Document* document = location.document(); Layer* layer = location.layer(); // When an editor is clicked the current view is changed. context->setActiveView(editor->getDocumentView()); // Start scroll loop if (checkForScroll(editor, msg) || checkForZoom(editor, msg)) return true; // Move cel X,Y coordinates if (clickedInk->isCelMovement()) { if ((layer) && (layer->type() == OBJECT_LAYER_IMAGE)) { // TODO you can move the `Background' with tiled mode if (layer->isBackground()) { Alert::show(PACKAGE "<<You can't move the `Background' layer." "||&Close"); } else if (!layer->isMoveable()) { Alert::show(PACKAGE "<<The layer movement is locked.||&Close"); } else { // Change to MovingCelState editor->setState(EditorStatePtr(new MovingCelState(editor, msg))); } } return true; } // Transform selected pixels if (document->isMaskVisible() && m_decorator->getTransformHandles(editor)) { TransformHandles* transfHandles = m_decorator->getTransformHandles(editor); // Get the handle covered by the mouse. HandleType handle = transfHandles->getHandleAtPoint(editor, msg->position(), document->getTransformation()); if (handle != NoHandle) { int x, y, opacity; Image* image = location.image(&x, &y, &opacity); if (image) { if (!layer->isWritable()) { Alert::show(PACKAGE "<<The layer is locked.||&Close"); return true; } // Change to MovingPixelsState transformSelection(editor, msg, handle); } return true; } } // Move selected pixels if (editor->isInsideSelection() && currentTool->getInk(0)->isSelection() && msg->left()) { if (!layer->isWritable()) { Alert::show(PACKAGE "<<The layer is locked.||&Close"); return true; } // Change to MovingPixelsState transformSelection(editor, msg, MoveHandle); return true; } // Call the eyedropper command if (clickedInk->isEyedropper()) { onMouseMove(editor, msg); return true; } // Start the Tool-Loop if (layer) { tools::ToolLoop* toolLoop = create_tool_loop(editor, context); if (toolLoop) editor->setState(EditorStatePtr(new DrawingState(toolLoop, editor, msg))); return true; } return true; }