mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-27 06:35:16 +00:00
Fix synchronization of different UI elements depending on the active tool
With this patch now the context bar shows the real active tool preferences. For example, if we choose the option to use the Eraser tool with right-click, now right-clicking will draw with the Eraser brush size (instead of using the selected tool/left-click tool brush size). Changes: * Removed the toolBox.activeTool() field from preferences (as the option isn't persisted between sessions) * Added an observable app::tools::ActiveToolManager class to sync all UI elements that depend on the active tool and ink. * Moved a lot of "active tool" logic from app::Editor to the new ActiveToolManager * Moved app::tools::ToolLoopManager::Pointer as an indepedent app::tools::Pointer class
This commit is contained in:
parent
f87cf93a55
commit
a09b00dba8
@ -128,9 +128,6 @@
|
||||
<option id="wheel_model" type="int" default="0" />
|
||||
<option id="harmony" type="int" default="0" />
|
||||
</section>
|
||||
<section id="tool_box">
|
||||
<option id="active_tool" type="std::string" default=""pencil"" />
|
||||
</section>
|
||||
<section id="updater">
|
||||
<option id="inits" type="int" default="0" migrate="Updater.Inits" />
|
||||
<option id="exits" type="int" default="0" migrate="Updater.Exits" />
|
||||
|
@ -330,6 +330,7 @@ add_library(app-lib
|
||||
shell.cpp
|
||||
snap_to_grid.cpp
|
||||
thumbnail_generator.cpp
|
||||
tools/active_tool.cpp
|
||||
tools/ink_type.cpp
|
||||
tools/intertwine.cpp
|
||||
tools/pick_ink.cpp
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "app/script/app_scripting.h"
|
||||
#include "app/send_crash.h"
|
||||
#include "app/shell.h"
|
||||
#include "app/tools/active_tool.h"
|
||||
#include "app/tools/tool_box.h"
|
||||
#include "app/ui/color_bar.h"
|
||||
#include "app/ui/document_view.h"
|
||||
@ -89,12 +90,6 @@ class App::CoreModules {
|
||||
public:
|
||||
ConfigModule m_configModule;
|
||||
Preferences m_preferences;
|
||||
|
||||
CoreModules() {
|
||||
// Reset the active tool ("pencil" is the default one).
|
||||
// We don't want to keep the selected tool from previous session.
|
||||
m_preferences.toolBox.activeTool(tools::WellKnownTools::Pencil);
|
||||
}
|
||||
};
|
||||
|
||||
class App::Modules {
|
||||
@ -102,6 +97,7 @@ public:
|
||||
LoggerModule m_loggerModule;
|
||||
FileSystemModule m_file_system_module;
|
||||
tools::ToolBox m_toolbox;
|
||||
tools::ActiveToolManager m_activeToolManager;
|
||||
CommandsModule m_commands_modules;
|
||||
UIContext m_ui_context;
|
||||
RecentFiles m_recent_files;
|
||||
@ -112,6 +108,7 @@ public:
|
||||
|
||||
Modules(bool createLogInDesktop)
|
||||
: m_loggerModule(createLogInDesktop)
|
||||
, m_activeToolManager(&m_toolbox)
|
||||
, m_recovery(nullptr) {
|
||||
}
|
||||
|
||||
@ -793,7 +790,12 @@ tools::ToolBox* App::toolBox() const
|
||||
|
||||
tools::Tool* App::activeTool() const
|
||||
{
|
||||
return toolBox()->getToolById(preferences().toolBox.activeTool());
|
||||
return m_modules->m_activeToolManager.activeTool();
|
||||
}
|
||||
|
||||
tools::ActiveToolManager* App::activeToolManager() const
|
||||
{
|
||||
return &m_modules->m_activeToolManager;
|
||||
}
|
||||
|
||||
RecentFiles* App::recentFiles() const
|
||||
|
@ -42,6 +42,7 @@ namespace app {
|
||||
class Workspace;
|
||||
|
||||
namespace tools {
|
||||
class ActiveToolManager;
|
||||
class Tool;
|
||||
class ToolBox;
|
||||
}
|
||||
@ -69,6 +70,7 @@ namespace app {
|
||||
|
||||
tools::ToolBox* toolBox() const;
|
||||
tools::Tool* activeTool() const;
|
||||
tools::ActiveToolManager* activeToolManager() const;
|
||||
RecentFiles* recentFiles() const;
|
||||
MainWindow* mainWindow() const { return m_mainWindow; }
|
||||
Workspace* workspace() const;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "app/console.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/tools/active_tool.h"
|
||||
#include "app/tools/ink.h"
|
||||
#include "app/tools/tool_box.h"
|
||||
#include "app/transaction.h"
|
||||
@ -126,7 +127,7 @@ void NewBrushCommand::onQuickboxEnd(Editor* editor, const gfx::Rect& rect, ui::M
|
||||
// Update the context bar
|
||||
// TODO find a way to avoid all these singletons. Maybe a simple
|
||||
// signal in the context like "brush has changed" could be enough.
|
||||
App::instance()->contextBar()->updateForCurrentTool();
|
||||
App::instance()->contextBar()->updateForActiveTool();
|
||||
|
||||
editor->backToPreviousState();
|
||||
}
|
||||
@ -168,8 +169,11 @@ void NewBrushCommand::createBrush(const Site& site, const Mask* mask)
|
||||
|
||||
void NewBrushCommand::selectPencilTool()
|
||||
{
|
||||
if (App::instance()->activeTool()->getInk(0)->isSelection())
|
||||
Preferences::instance().toolBox.activeTool(tools::WellKnownTools::Pencil);
|
||||
App* app = App::instance();
|
||||
if (app->activeToolManager()->selectedTool()->getInk(0)->isSelection()) {
|
||||
app->activeToolManager()->setSelectedTool(
|
||||
app->toolBox()->getToolById(tools::WellKnownTools::Pencil));
|
||||
}
|
||||
}
|
||||
|
||||
Command* CommandFactory::createNewBrushCommand()
|
||||
|
220
src/app/tools/active_tool.cpp
Normal file
220
src/app/tools/active_tool.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/tools/active_tool.h"
|
||||
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tools/active_tool_observer.h"
|
||||
#include "app/tools/ink.h"
|
||||
#include "app/tools/pointer.h"
|
||||
#include "app/tools/tool_box.h"
|
||||
#include "app/ui/color_bar.h"
|
||||
|
||||
namespace app {
|
||||
namespace tools {
|
||||
|
||||
class ActiveToolChangeTrigger {
|
||||
public:
|
||||
ActiveToolChangeTrigger(ActiveToolManager* manager)
|
||||
: m_manager(manager)
|
||||
, m_oldTool(manager->activeTool()) {
|
||||
}
|
||||
|
||||
~ActiveToolChangeTrigger() {
|
||||
Tool* newTool = m_manager->activeTool();
|
||||
if (m_oldTool != newTool) {
|
||||
m_manager->notifyObservers(
|
||||
&ActiveToolObserver::onActiveToolChange, newTool);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ActiveToolManager* m_manager;
|
||||
Tool* m_oldTool;
|
||||
};
|
||||
|
||||
ActiveToolManager::ActiveToolManager(ToolBox* toolbox)
|
||||
: m_toolbox(toolbox)
|
||||
, m_quickTool(nullptr)
|
||||
, m_rightClick(false)
|
||||
, m_rightClickTool(nullptr)
|
||||
, m_rightClickInk(nullptr)
|
||||
, m_proximityTool(nullptr)
|
||||
, m_selectedTool(m_toolbox->getToolById(WellKnownTools::Pencil)) // "pencil" is the active tool by default
|
||||
{
|
||||
}
|
||||
|
||||
Tool* ActiveToolManager::activeTool() const
|
||||
{
|
||||
if (m_quickTool)
|
||||
return m_quickTool;
|
||||
|
||||
if (m_rightClickTool)
|
||||
return m_rightClickTool;
|
||||
|
||||
if (m_proximityTool)
|
||||
return m_proximityTool;
|
||||
|
||||
// Active tool should never returns null
|
||||
ASSERT(m_selectedTool);
|
||||
return m_selectedTool;
|
||||
}
|
||||
|
||||
Ink* ActiveToolManager::activeInk() const
|
||||
{
|
||||
if (!m_quickTool && m_rightClickInk)
|
||||
return m_rightClickInk;
|
||||
|
||||
Tool* tool = activeTool();
|
||||
Ink* ink = tool->getInk(m_rightClick ? 1: 0);
|
||||
if (ink->isPaint() && !ink->isEffect()) {
|
||||
tools::InkType inkType = Preferences::instance().tool(tool).ink();
|
||||
const char* id = nullptr;
|
||||
|
||||
switch (inkType) {
|
||||
|
||||
case tools::InkType::SIMPLE: {
|
||||
id = tools::WellKnownInks::Paint;
|
||||
|
||||
ColorBar* colorbar = ColorBar::instance();
|
||||
app::Color color = (m_rightClick ? colorbar->getBgColor():
|
||||
colorbar->getFgColor());
|
||||
if (color.getAlpha() == 0)
|
||||
id = tools::WellKnownInks::PaintCopy;
|
||||
break;
|
||||
}
|
||||
|
||||
case tools::InkType::ALPHA_COMPOSITING:
|
||||
id = tools::WellKnownInks::Paint;
|
||||
break;
|
||||
case tools::InkType::COPY_COLOR:
|
||||
id = tools::WellKnownInks::PaintCopy;
|
||||
break;
|
||||
case tools::InkType::LOCK_ALPHA:
|
||||
id = tools::WellKnownInks::PaintLockAlpha;
|
||||
break;
|
||||
case tools::InkType::SHADING:
|
||||
id = tools::WellKnownInks::Shading;
|
||||
break;
|
||||
}
|
||||
|
||||
if (id)
|
||||
ink = m_toolbox->getInkById(id);
|
||||
}
|
||||
|
||||
return ink;
|
||||
}
|
||||
|
||||
Tool* ActiveToolManager::quickTool() const
|
||||
{
|
||||
return m_quickTool;
|
||||
}
|
||||
|
||||
Tool* ActiveToolManager::selectedTool() const
|
||||
{
|
||||
return m_selectedTool;
|
||||
}
|
||||
|
||||
void ActiveToolManager::newToolSelectedInToolBar(Tool* tool)
|
||||
{
|
||||
ActiveToolChangeTrigger trigger(this);
|
||||
m_selectedTool = tool;
|
||||
}
|
||||
|
||||
void ActiveToolManager::newQuickToolSelectedFromEditor(Tool* tool)
|
||||
{
|
||||
ActiveToolChangeTrigger trigger(this);
|
||||
m_quickTool = tool;
|
||||
}
|
||||
|
||||
void ActiveToolManager::regularTipProximity()
|
||||
{
|
||||
if (m_proximityTool != nullptr) {
|
||||
ActiveToolChangeTrigger trigger(this);
|
||||
m_proximityTool = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveToolManager::eraserTipProximity()
|
||||
{
|
||||
Tool* eraser = m_toolbox->getToolById(WellKnownTools::Eraser);
|
||||
if (m_proximityTool != eraser) {
|
||||
ActiveToolChangeTrigger trigger(this);
|
||||
m_proximityTool = eraser;
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveToolManager::pressButton(const Pointer& pointer)
|
||||
{
|
||||
ActiveToolChangeTrigger trigger(this);
|
||||
Tool* tool = nullptr;
|
||||
Ink* ink = nullptr;
|
||||
|
||||
if (pointer.button() == Pointer::Right) {
|
||||
m_rightClick = true;
|
||||
|
||||
if (isToolAffectedByRightClickMode(activeTool())) {
|
||||
switch (Preferences::instance().editor.rightClickMode()) {
|
||||
case app::gen::RightClickMode::PAINT_BGCOLOR:
|
||||
// Do nothing, use the active tool
|
||||
break;
|
||||
case app::gen::RightClickMode::PICK_FGCOLOR:
|
||||
tool = m_toolbox->getToolById(WellKnownTools::Eyedropper);
|
||||
ink = m_toolbox->getInkById(tools::WellKnownInks::PickFg);
|
||||
break;
|
||||
case app::gen::RightClickMode::ERASE:
|
||||
tool = m_toolbox->getToolById(WellKnownTools::Eraser);
|
||||
ink = m_toolbox->getInkById(tools::WellKnownInks::Eraser);
|
||||
break;
|
||||
case app::gen::RightClickMode::SCROLL:
|
||||
tool = m_toolbox->getToolById(WellKnownTools::Hand);
|
||||
ink = m_toolbox->getInkById(tools::WellKnownInks::Scroll);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_rightClick = false;
|
||||
}
|
||||
|
||||
m_rightClickTool = tool;
|
||||
m_rightClickInk = ink;
|
||||
}
|
||||
|
||||
void ActiveToolManager::releaseButtons()
|
||||
{
|
||||
ActiveToolChangeTrigger trigger(this);
|
||||
|
||||
m_rightClick = false;
|
||||
m_rightClickTool = nullptr;
|
||||
m_rightClickInk = nullptr;
|
||||
}
|
||||
|
||||
void ActiveToolManager::setSelectedTool(Tool* tool)
|
||||
{
|
||||
ActiveToolChangeTrigger trigger(this);
|
||||
|
||||
m_selectedTool = tool;
|
||||
notifyObservers(&ActiveToolObserver::onSelectedToolChange, tool);
|
||||
}
|
||||
|
||||
// static
|
||||
bool ActiveToolManager::isToolAffectedByRightClickMode(Tool* tool)
|
||||
{
|
||||
bool shadingMode = (Preferences::instance().tool(tool).ink() == InkType::SHADING);
|
||||
return
|
||||
((tool->getInk(0)->isPaint() && !shadingMode) ||
|
||||
(tool->getInk(0)->isEffect())) &&
|
||||
(!tool->getInk(0)->isEraser());
|
||||
}
|
||||
|
||||
} // namespace tools
|
||||
} // namespace app
|
72
src/app/tools/active_tool.h
Normal file
72
src/app/tools/active_tool.h
Normal file
@ -0,0 +1,72 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
|
||||
#ifndef APP_TOOLS_ACTIVE_TOOL_H_INCLUDED
|
||||
#define APP_TOOLS_ACTIVE_TOOL_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/observable.h"
|
||||
|
||||
namespace app {
|
||||
namespace tools {
|
||||
|
||||
class ActiveToolObserver;
|
||||
class Ink;
|
||||
class Pointer;
|
||||
class Tool;
|
||||
class ToolBox;
|
||||
|
||||
// Manages the coordination between different UI elements that show
|
||||
// information about the active tool.
|
||||
class ActiveToolManager : public base::Observable<ActiveToolObserver> {
|
||||
public:
|
||||
ActiveToolManager(ToolBox* toolbox);
|
||||
|
||||
Tool* activeTool() const;
|
||||
Ink* activeInk() const;
|
||||
|
||||
// Returns the quick tool.
|
||||
Tool* quickTool() const;
|
||||
|
||||
// Returns the selected tool in the toolbar/box.
|
||||
Tool* selectedTool() const;
|
||||
|
||||
// These are different events that came from UI elements and
|
||||
// modify the active tool.
|
||||
void newToolSelectedInToolBar(Tool* tool);
|
||||
void newQuickToolSelectedFromEditor(Tool* tool);
|
||||
void regularTipProximity();
|
||||
void eraserTipProximity();
|
||||
void pressButton(const Pointer& pointer);
|
||||
void releaseButtons();
|
||||
void setSelectedTool(Tool* tool);
|
||||
|
||||
private:
|
||||
static bool isToolAffectedByRightClickMode(Tool* tool);
|
||||
|
||||
ToolBox* m_toolbox;
|
||||
|
||||
// Quick tool in the active sprite editor (activated by keyboard
|
||||
// shortuts).
|
||||
Tool* m_quickTool;
|
||||
|
||||
// Special tool by stylus proximity.
|
||||
bool m_rightClick;
|
||||
Tool* m_rightClickTool;
|
||||
Ink* m_rightClickInk;
|
||||
|
||||
// Special tool by stylus proximity (e.g. eraser).
|
||||
Tool* m_proximityTool;
|
||||
|
||||
// Selected tool in the toolbar/toolbox.
|
||||
Tool* m_selectedTool;
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
} // namespace app
|
||||
|
||||
#endif
|
31
src/app/tools/active_tool_observer.h
Normal file
31
src/app/tools/active_tool_observer.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
|
||||
#ifndef APP_TOOLS_ACTIVE_TOOL_OBSERVER_H_INCLUDED
|
||||
#define APP_TOOLS_ACTIVE_TOOL_OBSERVER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace app {
|
||||
namespace tools {
|
||||
|
||||
class Tool;
|
||||
|
||||
class ActiveToolObserver {
|
||||
public:
|
||||
virtual ~ActiveToolObserver() { }
|
||||
|
||||
// Called when a new tool is active.
|
||||
virtual void onActiveToolChange(tools::Tool* tool) { }
|
||||
|
||||
// Called when a new tool is selected in the tool box.
|
||||
virtual void onSelectedToolChange(tools::Tool* tool) { }
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
} // namespace app
|
||||
|
||||
#endif
|
39
src/app/tools/pointer.h
Normal file
39
src/app/tools/pointer.h
Normal file
@ -0,0 +1,39 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
|
||||
#ifndef APP_TOOLS_POINTER_H_INCLUDED
|
||||
#define APP_TOOLS_POINTER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/point.h"
|
||||
|
||||
namespace app {
|
||||
namespace tools {
|
||||
|
||||
// Simple container of mouse events information.
|
||||
class Pointer {
|
||||
public:
|
||||
enum Button { None, Left, Middle, Right };
|
||||
|
||||
Pointer()
|
||||
: m_point(0, 0), m_button(None) { }
|
||||
|
||||
Pointer(const gfx::Point& point, Button button)
|
||||
: m_point(point), m_button(button) { }
|
||||
|
||||
const gfx::Point& point() const { return m_point; }
|
||||
Button button() const { return m_button; }
|
||||
|
||||
private:
|
||||
gfx::Point m_point;
|
||||
Button m_button;
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -64,7 +64,7 @@ void ToolLoopManager::notifyToolLoopModifiersChange()
|
||||
if (isCanceled())
|
||||
return;
|
||||
|
||||
if (m_lastPointer.getButton() != Pointer::None)
|
||||
if (m_lastPointer.button() != Pointer::None)
|
||||
movement(m_lastPointer);
|
||||
}
|
||||
|
||||
@ -76,8 +76,8 @@ void ToolLoopManager::pressButton(const Pointer& pointer)
|
||||
return;
|
||||
|
||||
// If the user pressed the other mouse button...
|
||||
if ((m_toolLoop->getMouseButton() == ToolLoop::Left && pointer.getButton() == Pointer::Right) ||
|
||||
(m_toolLoop->getMouseButton() == ToolLoop::Right && pointer.getButton() == Pointer::Left)) {
|
||||
if ((m_toolLoop->getMouseButton() == ToolLoop::Left && pointer.button() == Pointer::Right) ||
|
||||
(m_toolLoop->getMouseButton() == ToolLoop::Right && pointer.button() == Pointer::Left)) {
|
||||
// Cancel the tool-loop (the destination image should be completelly discarded)
|
||||
m_toolLoop->cancel();
|
||||
return;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define APP_TOOLS_TOOL_LOOP_MANAGER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/tools/pointer.h"
|
||||
#include "app/tools/stroke.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/region.h"
|
||||
@ -18,88 +19,68 @@
|
||||
namespace gfx { class Region; }
|
||||
|
||||
namespace app {
|
||||
namespace tools {
|
||||
namespace tools {
|
||||
|
||||
class ToolLoop;
|
||||
class ToolLoop;
|
||||
|
||||
// Class to manage the drawing tool (editor <-> tool interface).
|
||||
//
|
||||
// The flow is this:
|
||||
// 1. The user press a mouse button in a Editor widget
|
||||
// 2. The Editor creates an implementation of ToolLoop and use it
|
||||
// with the ToolLoopManager constructor
|
||||
// 3. The ToolLoopManager is used to call
|
||||
// the following methods:
|
||||
// - ToolLoopManager::prepareLoop
|
||||
// - ToolLoopManager::pressButton
|
||||
// 4. If the user moves the mouse, the method
|
||||
// - ToolLoopManager::movement
|
||||
// is called.
|
||||
// 5. When the user release the mouse:
|
||||
// - ToolLoopManager::releaseButton
|
||||
//
|
||||
class ToolLoopManager {
|
||||
public:
|
||||
// Class to manage the drawing tool (editor <-> tool interface).
|
||||
//
|
||||
// The flow is this:
|
||||
// 1. The user press a mouse button in a Editor widget
|
||||
// 2. The Editor creates an implementation of ToolLoop and use it
|
||||
// with the ToolLoopManager constructor
|
||||
// 3. The ToolLoopManager is used to call
|
||||
// the following methods:
|
||||
// - ToolLoopManager::prepareLoop
|
||||
// - ToolLoopManager::pressButton
|
||||
// 4. If the user moves the mouse, the method
|
||||
// - ToolLoopManager::movement
|
||||
// is called.
|
||||
// 5. When the user release the mouse:
|
||||
// - ToolLoopManager::releaseButton
|
||||
//
|
||||
class ToolLoopManager {
|
||||
public:
|
||||
// Contructs a manager for the ToolLoop delegate.
|
||||
ToolLoopManager(ToolLoop* toolLoop);
|
||||
virtual ~ToolLoopManager();
|
||||
|
||||
// Simple container of mouse events information.
|
||||
class Pointer {
|
||||
public:
|
||||
enum Button { None, Left, Middle, Right };
|
||||
bool isCanceled() const;
|
||||
|
||||
Pointer()
|
||||
: m_point(0, 0), m_button(None) { }
|
||||
// Should be called when the user start a tool-trace (pressing the
|
||||
// left or right button for first time in the editor).
|
||||
void prepareLoop(const Pointer& pointer);
|
||||
|
||||
Pointer(const gfx::Point& point, Button button)
|
||||
: m_point(point), m_button(button) { }
|
||||
// Should be called when the ToolLoop::getModifiers()
|
||||
// value was modified (e.g. when the user press/release a key).
|
||||
void notifyToolLoopModifiersChange();
|
||||
|
||||
const gfx::Point& point() const { return m_point; }
|
||||
Button getButton() const { return m_button; }
|
||||
// Should be called each time the user presses a mouse button.
|
||||
void pressButton(const Pointer& pointer);
|
||||
|
||||
private:
|
||||
gfx::Point m_point;
|
||||
Button m_button;
|
||||
};
|
||||
// Should be called each time the user releases a mouse button.
|
||||
//
|
||||
// Returns true if the tool-loop should continue, or false
|
||||
// if the editor should release the mouse capture.
|
||||
bool releaseButton(const Pointer& pointer);
|
||||
|
||||
// Contructs a manager for the ToolLoop delegate.
|
||||
ToolLoopManager(ToolLoop* toolLoop);
|
||||
virtual ~ToolLoopManager();
|
||||
// Should be called each time the user moves the mouse inside the editor.
|
||||
void movement(const Pointer& pointer);
|
||||
|
||||
bool isCanceled() const;
|
||||
private:
|
||||
void doLoopStep(bool last_step);
|
||||
void snapToGrid(gfx::Point& point);
|
||||
|
||||
// Should be called when the user start a tool-trace (pressing the
|
||||
// left or right button for first time in the editor).
|
||||
void prepareLoop(const Pointer& pointer);
|
||||
void calculateDirtyArea(const Strokes& strokes);
|
||||
|
||||
// Should be called when the ToolLoop::getModifiers()
|
||||
// value was modified (e.g. when the user press/release a key).
|
||||
void notifyToolLoopModifiersChange();
|
||||
ToolLoop* m_toolLoop;
|
||||
Stroke m_stroke;
|
||||
Pointer m_lastPointer;
|
||||
gfx::Point m_oldPoint;
|
||||
gfx::Region& m_dirtyArea;
|
||||
};
|
||||
|
||||
// Should be called each time the user presses a mouse button.
|
||||
void pressButton(const Pointer& pointer);
|
||||
|
||||
// Should be called each time the user releases a mouse button.
|
||||
//
|
||||
// Returns true if the tool-loop should continue, or false
|
||||
// if the editor should release the mouse capture.
|
||||
bool releaseButton(const Pointer& pointer);
|
||||
|
||||
// Should be called each time the user moves the mouse inside the editor.
|
||||
void movement(const Pointer& pointer);
|
||||
|
||||
private:
|
||||
void doLoopStep(bool last_step);
|
||||
void snapToGrid(gfx::Point& point);
|
||||
|
||||
void calculateDirtyArea(const Strokes& strokes);
|
||||
|
||||
ToolLoop* m_toolLoop;
|
||||
Stroke m_stroke;
|
||||
Pointer m_lastPointer;
|
||||
gfx::Point m_oldPoint;
|
||||
gfx::Region& m_dirtyArea;
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
} // namespace tools
|
||||
} // namespace app
|
||||
|
||||
#endif
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/shade.h"
|
||||
#include "app/tools/active_tool.h"
|
||||
#include "app/tools/controller.h"
|
||||
#include "app/tools/ink.h"
|
||||
#include "app/tools/ink_type.h"
|
||||
@ -322,7 +323,7 @@ public:
|
||||
pref.tool(tool).ink(inkType);
|
||||
}
|
||||
|
||||
m_owner->updateForCurrentTool();
|
||||
m_owner->updateForActiveTool();
|
||||
}
|
||||
|
||||
void setInkTypeIcon(InkType inkType) {
|
||||
@ -1344,9 +1345,9 @@ ContextBar::ContextBar()
|
||||
m_freehandAlgo->setupTooltips(tooltipManager);
|
||||
m_symmetry->setupTooltips(tooltipManager);
|
||||
|
||||
App::instance()->activeToolManager()->addObserver(this);
|
||||
|
||||
auto& pref = Preferences::instance();
|
||||
pref.toolBox.activeTool.AfterChange.connect(
|
||||
base::Bind<void>(&ContextBar::onCurrentToolChange, this));
|
||||
pref.symmetryMode.enabled.AfterChange.connect(
|
||||
base::Bind<void>(&ContextBar::onSymmetryModeChange, this));
|
||||
pref.colorBar.fgColor.AfterChange.connect(
|
||||
@ -1359,6 +1360,11 @@ ContextBar::ContextBar()
|
||||
setActiveBrush(createBrushFromPreferences());
|
||||
}
|
||||
|
||||
ContextBar::~ContextBar()
|
||||
{
|
||||
App::instance()->activeToolManager()->removeObserver(this);
|
||||
}
|
||||
|
||||
void ContextBar::onSizeHint(SizeHintEvent& ev)
|
||||
{
|
||||
ev.setSizeHint(gfx::Size(0, 18*guiscale())); // TODO calculate height
|
||||
@ -1386,7 +1392,7 @@ void ContextBar::onBrushSizeChange()
|
||||
if (m_activeBrush->type() != kImageBrushType)
|
||||
discardActiveBrush();
|
||||
|
||||
updateForCurrentTool();
|
||||
updateForActiveTool();
|
||||
}
|
||||
|
||||
void ContextBar::onBrushAngleChange()
|
||||
@ -1395,18 +1401,18 @@ void ContextBar::onBrushAngleChange()
|
||||
discardActiveBrush();
|
||||
}
|
||||
|
||||
void ContextBar::onCurrentToolChange()
|
||||
void ContextBar::onActiveToolChange(tools::Tool* tool)
|
||||
{
|
||||
if (m_activeBrush->type() != kImageBrushType)
|
||||
setActiveBrush(ContextBar::createBrushFromPreferences());
|
||||
else {
|
||||
updateForCurrentTool();
|
||||
updateForTool(tool);
|
||||
}
|
||||
}
|
||||
|
||||
void ContextBar::onSymmetryModeChange()
|
||||
{
|
||||
updateForCurrentTool();
|
||||
updateForActiveTool();
|
||||
}
|
||||
|
||||
void ContextBar::onFgOrBgColorChange(doc::Brush::ImageColor imageColor)
|
||||
@ -1433,7 +1439,7 @@ void ContextBar::onDropPixels(ContextBarObserver::DropAction action)
|
||||
notifyObservers(&ContextBarObserver::onDropPixels, action);
|
||||
}
|
||||
|
||||
void ContextBar::updateForCurrentTool()
|
||||
void ContextBar::updateForActiveTool()
|
||||
{
|
||||
updateForTool(App::instance()->activeTool());
|
||||
}
|
||||
@ -1719,7 +1725,7 @@ void ContextBar::setActiveBrush(const doc::BrushRef& brush)
|
||||
|
||||
BrushChange();
|
||||
|
||||
updateForCurrentTool();
|
||||
updateForActiveTool();
|
||||
}
|
||||
|
||||
doc::BrushRef ContextBar::activeBrush(tools::Tool* tool) const
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/shade.h"
|
||||
#include "app/tools/active_tool_observer.h"
|
||||
#include "app/tools/ink_type.h"
|
||||
#include "app/tools/tool_loop_modifiers.h"
|
||||
#include "app/ui/context_bar_observer.h"
|
||||
@ -39,12 +40,14 @@ namespace app {
|
||||
|
||||
class BrushSlot;
|
||||
|
||||
class ContextBar : public ui::Box,
|
||||
public base::Observable<ContextBarObserver> {
|
||||
class ContextBar : public ui::Box
|
||||
, public base::Observable<ContextBarObserver>
|
||||
, public tools::ActiveToolObserver {
|
||||
public:
|
||||
ContextBar();
|
||||
~ContextBar();
|
||||
|
||||
void updateForCurrentTool();
|
||||
void updateForActiveTool();
|
||||
void updateForTool(tools::Tool* tool);
|
||||
void updateForMovingPixels();
|
||||
void updateForSelectingBox(const std::string& text);
|
||||
@ -77,11 +80,13 @@ namespace app {
|
||||
private:
|
||||
void onBrushSizeChange();
|
||||
void onBrushAngleChange();
|
||||
void onCurrentToolChange();
|
||||
void onSymmetryModeChange();
|
||||
void onFgOrBgColorChange(doc::Brush::ImageColor imageColor);
|
||||
void onDropPixels(ContextBarObserver::DropAction action);
|
||||
|
||||
// ActiveToolObserver impl
|
||||
void onActiveToolChange(tools::Tool* tool) override;
|
||||
|
||||
class BrushTypeField;
|
||||
class BrushAngleField;
|
||||
class BrushSizeField;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "app/tools/tool_loop_manager.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/editor/editor_customization_delegate.h"
|
||||
#include "app/ui/editor/glue.h"
|
||||
#include "app/ui/keyboard_shortcuts.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "ui/message.h"
|
||||
@ -37,21 +38,6 @@ namespace app {
|
||||
|
||||
using namespace ui;
|
||||
|
||||
static tools::ToolLoopManager::Pointer::Button button_from_msg(MouseMessage* msg)
|
||||
{
|
||||
return
|
||||
(msg->right() ? tools::ToolLoopManager::Pointer::Right:
|
||||
(msg->middle() ? tools::ToolLoopManager::Pointer::Middle:
|
||||
tools::ToolLoopManager::Pointer::Left));
|
||||
}
|
||||
|
||||
static tools::ToolLoopManager::Pointer pointer_from_msg(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
return
|
||||
tools::ToolLoopManager::Pointer(editor->screenToEditor(msg->position()),
|
||||
button_from_msg(msg));
|
||||
}
|
||||
|
||||
DrawingState::DrawingState(tools::ToolLoop* toolLoop)
|
||||
: m_toolLoop(toolLoop)
|
||||
, m_toolLoopManager(new tools::ToolLoopManager(toolLoop))
|
||||
@ -79,7 +65,7 @@ void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
|
||||
|
||||
m_lastPoint = editor->lastDrawingPosition();
|
||||
|
||||
tools::ToolLoopManager::Pointer pointer;
|
||||
tools::Pointer pointer;
|
||||
bool movement = false;
|
||||
|
||||
if (m_toolLoop->getController()->isFreehand() &&
|
||||
@ -87,7 +73,7 @@ void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
|
||||
(editor->getCustomizationDelegate()
|
||||
->getPressedKeyAction(KeyContext::FreehandTool) & KeyAction::StraightLineFromLastPoint) == KeyAction::StraightLineFromLastPoint &&
|
||||
m_lastPoint.x >= 0) {
|
||||
pointer = tools::ToolLoopManager::Pointer(m_lastPoint, button_from_msg(msg));
|
||||
pointer = tools::Pointer(m_lastPoint, button_from_msg(msg));
|
||||
movement = true;
|
||||
}
|
||||
else {
|
||||
@ -170,8 +156,8 @@ bool DrawingState::onMouseMove(Editor* editor, MouseMessage* msg)
|
||||
|
||||
// Infinite scroll
|
||||
gfx::Point mousePos = editor->autoScroll(msg, AutoScroll::MouseDir);
|
||||
tools::ToolLoopManager::Pointer pointer(editor->screenToEditor(mousePos),
|
||||
button_from_msg(msg));
|
||||
tools::Pointer pointer(editor->screenToEditor(mousePos),
|
||||
button_from_msg(msg));
|
||||
|
||||
// Notify mouse movement to the tool
|
||||
ASSERT(m_toolLoopManager != NULL);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tools/active_tool.h"
|
||||
#include "app/tools/ink.h"
|
||||
#include "app/tools/tool.h"
|
||||
#include "app/tools/tool_box.h"
|
||||
@ -33,6 +34,7 @@
|
||||
#include "app/ui/editor/drawing_state.h"
|
||||
#include "app/ui/editor/editor_customization_delegate.h"
|
||||
#include "app/ui/editor/editor_decorator.h"
|
||||
#include "app/ui/editor/glue.h"
|
||||
#include "app/ui/editor/moving_pixels_state.h"
|
||||
#include "app/ui/editor/pixels_movement.h"
|
||||
#include "app/ui/editor/play_state.h"
|
||||
@ -157,14 +159,12 @@ Editor::Editor(Document* document, EditorFlags flags)
|
||||
, m_docPref(Preferences::instance().document(document))
|
||||
, m_brushPreview(this)
|
||||
, m_lastDrawingPosition(-1, -1)
|
||||
, m_quicktool(NULL)
|
||||
, m_toolLoopModifiers(tools::ToolLoopModifiers::kNone)
|
||||
, m_padding(0, 0)
|
||||
, m_antsTimer(100, this)
|
||||
, m_antsOffset(0)
|
||||
, m_customizationDelegate(NULL)
|
||||
, m_docView(NULL)
|
||||
, m_lastPointerType(ui::PointerType::Unknown)
|
||||
, m_flags(flags)
|
||||
, m_secondaryButton(false)
|
||||
, m_aniSpeed(1.0)
|
||||
@ -174,9 +174,7 @@ Editor::Editor(Document* document, EditorFlags flags)
|
||||
|
||||
this->setFocusStop(true);
|
||||
|
||||
m_currentToolChangeConn =
|
||||
Preferences::instance().toolBox.activeTool.AfterChange.connect(
|
||||
base::Bind<void>(&Editor::onCurrentToolChange, this));
|
||||
App::instance()->activeToolManager()->addObserver(this);
|
||||
|
||||
m_fgColorChangeConn =
|
||||
Preferences::instance().colorBar.fgColor.AfterChange.connect(
|
||||
@ -218,6 +216,7 @@ Editor::~Editor()
|
||||
|
||||
m_observers.notifyDestroyEditor(this);
|
||||
m_document->removeObserver(this);
|
||||
App::instance()->activeToolManager()->removeObserver(this);
|
||||
|
||||
setCustomizationDelegate(NULL);
|
||||
|
||||
@ -905,50 +904,9 @@ gfx::Point Editor::autoScroll(MouseMessage* msg, AutoScroll dir)
|
||||
return mousePos;
|
||||
}
|
||||
|
||||
bool Editor::isCurrentToolAffectedByRightClickMode()
|
||||
{
|
||||
tools::Tool* tool = App::instance()->activeTool();
|
||||
bool shadingMode = (Preferences::instance().tool(tool).ink() == tools::InkType::SHADING);
|
||||
return
|
||||
((tool->getInk(0)->isPaint() && !shadingMode) ||
|
||||
(tool->getInk(0)->isEffect())) &&
|
||||
(!tool->getInk(0)->isEraser());
|
||||
}
|
||||
|
||||
tools::Tool* Editor::getCurrentEditorTool()
|
||||
{
|
||||
if (m_quicktool)
|
||||
return m_quicktool;
|
||||
|
||||
// Eraser tip
|
||||
if (m_lastPointerType == ui::PointerType::Eraser) {
|
||||
tools::ToolBox* toolbox = App::instance()->toolBox();
|
||||
return toolbox->getToolById(tools::WellKnownTools::Eraser);
|
||||
}
|
||||
|
||||
tools::Tool* tool = App::instance()->activeTool();
|
||||
|
||||
if (m_secondaryButton &&
|
||||
isCurrentToolAffectedByRightClickMode()) {
|
||||
tools::ToolBox* toolbox = App::instance()->toolBox();
|
||||
|
||||
switch (Preferences::instance().editor.rightClickMode()) {
|
||||
case app::gen::RightClickMode::PAINT_BGCOLOR:
|
||||
// Do nothing, use the current tool
|
||||
break;
|
||||
case app::gen::RightClickMode::PICK_FGCOLOR:
|
||||
tool = toolbox->getToolById(tools::WellKnownTools::Eyedropper);
|
||||
break;
|
||||
case app::gen::RightClickMode::ERASE:
|
||||
tool = toolbox->getToolById(tools::WellKnownTools::Eraser);
|
||||
break;
|
||||
case app::gen::RightClickMode::SCROLL:
|
||||
tool = toolbox->getToolById(tools::WellKnownTools::Hand);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tool;
|
||||
return App::instance()->activeTool();
|
||||
}
|
||||
|
||||
tools::Ink* Editor::getCurrentEditorInk()
|
||||
@ -956,72 +914,8 @@ tools::Ink* Editor::getCurrentEditorInk()
|
||||
tools::Ink* ink = m_state->getStateInk();
|
||||
if (ink)
|
||||
return ink;
|
||||
|
||||
tools::Tool* tool = getCurrentEditorTool();
|
||||
ink = tool->getInk(m_secondaryButton ? 1: 0);
|
||||
|
||||
if (m_quicktool)
|
||||
return ink;
|
||||
|
||||
app::gen::RightClickMode rightClickMode = Preferences::instance().editor.rightClickMode();
|
||||
|
||||
if (m_secondaryButton &&
|
||||
rightClickMode != app::gen::RightClickMode::DEFAULT &&
|
||||
isCurrentToolAffectedByRightClickMode()) {
|
||||
tools::ToolBox* toolbox = App::instance()->toolBox();
|
||||
|
||||
switch (rightClickMode) {
|
||||
case app::gen::RightClickMode::DEFAULT:
|
||||
// Do nothing
|
||||
break;
|
||||
case app::gen::RightClickMode::PICK_FGCOLOR:
|
||||
ink = toolbox->getInkById(tools::WellKnownInks::PickFg);
|
||||
break;
|
||||
case app::gen::RightClickMode::ERASE:
|
||||
ink = toolbox->getInkById(tools::WellKnownInks::Eraser);
|
||||
break;
|
||||
case app::gen::RightClickMode::SCROLL:
|
||||
ink = toolbox->getInkById(tools::WellKnownInks::Scroll);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Only paint tools can have different inks
|
||||
else if (ink->isPaint() && !ink->isEffect()) {
|
||||
tools::InkType inkType = Preferences::instance().tool(tool).ink();
|
||||
const char* id = NULL;
|
||||
|
||||
switch (inkType) {
|
||||
|
||||
case tools::InkType::SIMPLE: {
|
||||
id = tools::WellKnownInks::Paint;
|
||||
|
||||
ColorBar* colorbar = ColorBar::instance();
|
||||
app::Color color = (m_secondaryButton ? colorbar->getBgColor():
|
||||
colorbar->getFgColor());
|
||||
if (color.getAlpha() == 0)
|
||||
id = tools::WellKnownInks::PaintCopy;
|
||||
break;
|
||||
}
|
||||
|
||||
case tools::InkType::ALPHA_COMPOSITING:
|
||||
id = tools::WellKnownInks::Paint;
|
||||
break;
|
||||
case tools::InkType::COPY_COLOR:
|
||||
id = tools::WellKnownInks::PaintCopy;
|
||||
break;
|
||||
case tools::InkType::LOCK_ALPHA:
|
||||
id = tools::WellKnownInks::PaintLockAlpha;
|
||||
break;
|
||||
case tools::InkType::SHADING:
|
||||
id = tools::WellKnownInks::Shading;
|
||||
break;
|
||||
}
|
||||
|
||||
if (id)
|
||||
ink = App::instance()->toolBox()->getInkById(id);
|
||||
}
|
||||
|
||||
return ink;
|
||||
else
|
||||
return App::instance()->activeToolManager()->activeInk();
|
||||
}
|
||||
|
||||
gfx::Point Editor::screenToEditor(const gfx::Point& pt)
|
||||
@ -1119,53 +1013,38 @@ void Editor::updateStatusBar()
|
||||
void Editor::updateQuicktool()
|
||||
{
|
||||
if (m_customizationDelegate && !hasCapture()) {
|
||||
tools::Tool* current_tool = App::instance()->activeTool();
|
||||
auto activeToolManager = App::instance()->activeToolManager();
|
||||
tools::Tool* selectedTool = activeToolManager->selectedTool();
|
||||
tools::Tool* oldQuicktool = activeToolManager->quickTool();
|
||||
|
||||
// Don't change quicktools if we are in a selection tool and using
|
||||
// the selection modifiers.
|
||||
if (current_tool->getInk(0)->isSelection() &&
|
||||
if (selectedTool->getInk(0)->isSelection() &&
|
||||
int(m_customizationDelegate->getPressedKeyAction(KeyContext::SelectionTool)) != 0)
|
||||
return;
|
||||
|
||||
tools::Tool* old_quicktool = m_quicktool;
|
||||
tools::Tool* new_quicktool = m_customizationDelegate->getQuickTool(current_tool);
|
||||
tools::Tool* newQuicktool =
|
||||
m_customizationDelegate->getQuickTool(selectedTool);
|
||||
|
||||
// Check if the current state accept the given quicktool.
|
||||
if (new_quicktool &&
|
||||
!m_state->acceptQuickTool(new_quicktool))
|
||||
if (newQuicktool && !m_state->acceptQuickTool(newQuicktool))
|
||||
return;
|
||||
|
||||
// If the quick tool has changed we update the brush cursor, the
|
||||
// context bar, and the status bar. Things that depends on the
|
||||
// current tool.
|
||||
//
|
||||
// TODO We could add a quick tool observer for this
|
||||
if (old_quicktool != new_quicktool) {
|
||||
// Hide the brush preview with the current tool brush size
|
||||
// before we change the quicktool. In this way we avoid using
|
||||
// the quicktool brush size to clean the current tool cursor.
|
||||
//
|
||||
// TODO Create a new Document concept of multiple extra cels: we
|
||||
// need an extra cel for the drawing cursor, other for the moving
|
||||
// pixels, etc. In this way we'll not have conflicts between
|
||||
// different uses of the same extra cel.
|
||||
{
|
||||
HideBrushPreview hide(m_brushPreview);
|
||||
m_quicktool = new_quicktool;
|
||||
}
|
||||
|
||||
m_state->onQuickToolChange(this);
|
||||
|
||||
updateStatusBar();
|
||||
|
||||
App::instance()->contextBar()->updateForTool(getCurrentEditorTool());
|
||||
}
|
||||
activeToolManager
|
||||
->newQuickToolSelectedFromEditor(newQuicktool);
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::updateContextBar()
|
||||
void Editor::updateToolByTipProximity(ui::PointerType pointerType)
|
||||
{
|
||||
App::instance()->contextBar()->updateForTool(getCurrentEditorTool());
|
||||
auto activeToolManager = App::instance()->activeToolManager();
|
||||
|
||||
if (pointerType == ui::PointerType::Eraser) {
|
||||
activeToolManager->eraserTipProximity();
|
||||
}
|
||||
else {
|
||||
activeToolManager->regularTipProximity();
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::updateToolLoopModifiersIndicators()
|
||||
@ -1288,17 +1167,19 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||
|
||||
m_oldPos = mouseMsg->position();
|
||||
m_lastPointerType = mouseMsg->pointerType();
|
||||
updateToolByTipProximity(mouseMsg->pointerType());
|
||||
|
||||
if (!m_secondaryButton && mouseMsg->right()) {
|
||||
m_secondaryButton = mouseMsg->right();
|
||||
|
||||
updateQuicktool();
|
||||
updateContextBar();
|
||||
updateToolLoopModifiersIndicators();
|
||||
setCursor(mouseMsg->position());
|
||||
}
|
||||
|
||||
App::instance()->activeToolManager()
|
||||
->pressButton(pointer_from_msg(this, mouseMsg));
|
||||
|
||||
EditorStatePtr holdState(m_state);
|
||||
return m_state->onMouseDown(this, mouseMsg);
|
||||
}
|
||||
@ -1307,14 +1188,9 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
case kMouseMoveMessage:
|
||||
if (m_sprite) {
|
||||
EditorStatePtr holdState(m_state);
|
||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||
|
||||
PointerType newPointerType = static_cast<MouseMessage*>(msg)->pointerType();
|
||||
if (m_lastPointerType != newPointerType) {
|
||||
m_lastPointerType = newPointerType;
|
||||
|
||||
updateQuicktool();
|
||||
updateContextBar();
|
||||
}
|
||||
updateToolByTipProximity(mouseMsg->pointerType());
|
||||
|
||||
return m_state->onMouseMove(this, static_cast<MouseMessage*>(msg));
|
||||
}
|
||||
@ -1326,13 +1202,13 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||
bool result = m_state->onMouseUp(this, mouseMsg);
|
||||
|
||||
m_lastPointerType = mouseMsg->pointerType();
|
||||
updateToolByTipProximity(mouseMsg->pointerType());
|
||||
|
||||
if (!hasCapture()) {
|
||||
App::instance()->activeToolManager()->releaseButtons();
|
||||
m_secondaryButton = false;
|
||||
|
||||
updateQuicktool();
|
||||
updateContextBar();
|
||||
updateToolLoopModifiersIndicators();
|
||||
setCursor(mouseMsg->position());
|
||||
}
|
||||
@ -1347,7 +1223,7 @@ bool Editor::onProcessMessage(Message* msg)
|
||||
MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
|
||||
EditorStatePtr holdState(m_state);
|
||||
|
||||
m_lastPointerType = mouseMsg->pointerType();
|
||||
updateToolByTipProximity(mouseMsg->pointerType());
|
||||
|
||||
bool used = m_state->onDoubleClick(this, mouseMsg);
|
||||
if (used)
|
||||
@ -1483,9 +1359,9 @@ void Editor::onInvalidateRegion(const gfx::Region& region)
|
||||
}
|
||||
|
||||
// When the current tool is changed
|
||||
void Editor::onCurrentToolChange()
|
||||
void Editor::onActiveToolChange(tools::Tool* tool)
|
||||
{
|
||||
m_state->onCurrentToolChange(this);
|
||||
m_state->onActiveToolChange(this, tool);
|
||||
}
|
||||
|
||||
void Editor::onFgColorChange()
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "app/color.h"
|
||||
#include "app/document.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tools/active_tool_observer.h"
|
||||
#include "app/tools/tool_loop_modifiers.h"
|
||||
#include "app/ui/color_source.h"
|
||||
#include "app/ui/editor/brush_preview.h"
|
||||
@ -61,9 +62,10 @@ namespace app {
|
||||
ScrollDir,
|
||||
};
|
||||
|
||||
class Editor : public ui::Widget,
|
||||
public doc::DocumentObserver
|
||||
, public IColorSource {
|
||||
class Editor : public ui::Widget
|
||||
, public doc::DocumentObserver
|
||||
, public IColorSource
|
||||
, public tools::ActiveToolObserver {
|
||||
public:
|
||||
enum EditorFlags {
|
||||
kNoneFlag = 0,
|
||||
@ -232,18 +234,19 @@ namespace app {
|
||||
void onResize(ui::ResizeEvent& ev) override;
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
void onInvalidateRegion(const gfx::Region& region) override;
|
||||
void onCurrentToolChange();
|
||||
void onFgColorChange();
|
||||
void onContextBarBrushChange();
|
||||
void onShowExtrasChange();
|
||||
void onExposeSpritePixels(doc::DocumentEvent& ev) override;
|
||||
|
||||
// ActiveToolObserver impl
|
||||
void onActiveToolChange(tools::Tool* tool) override;
|
||||
|
||||
private:
|
||||
void setStateInternal(const EditorStatePtr& newState);
|
||||
void updateQuicktool();
|
||||
void updateContextBar();
|
||||
void updateToolByTipProximity(ui::PointerType pointerType);
|
||||
void updateToolLoopModifiersIndicators();
|
||||
bool isCurrentToolAffectedByRightClickMode();
|
||||
|
||||
void drawMaskSafe();
|
||||
void drawMask(ui::Graphics* g);
|
||||
@ -285,10 +288,6 @@ namespace app {
|
||||
// (EditorCustomizationDelegate::isStraightLineFromLastPoint() modifier)
|
||||
gfx::Point m_lastDrawingPosition;
|
||||
|
||||
// Current selected quicktool (this genererally should be NULL if
|
||||
// the user is not pressing any keyboard key).
|
||||
tools::Tool* m_quicktool;
|
||||
|
||||
tools::ToolLoopModifiers m_toolLoopModifiers;
|
||||
bool m_autoSelectLayer;
|
||||
|
||||
@ -299,11 +298,6 @@ namespace app {
|
||||
ui::Timer m_antsTimer;
|
||||
int m_antsOffset;
|
||||
|
||||
// This slot is used to disconnect the Editor from CurrentToolChange
|
||||
// signal (because the editor can be destroyed and the application
|
||||
// still continue running and generating CurrentToolChange
|
||||
// signals).
|
||||
base::ScopedConnection m_currentToolChangeConn;
|
||||
base::ScopedConnection m_fgColorChangeConn;
|
||||
base::ScopedConnection m_contextBarBrushChangeConn;
|
||||
base::ScopedConnection m_showExtrasConn;
|
||||
|
@ -71,8 +71,7 @@ namespace app {
|
||||
// useful for states which depends on the selected current tool (as
|
||||
// MovingPixelsState which drops the pixels in case the user selects
|
||||
// other drawing tool).
|
||||
virtual void onCurrentToolChange(Editor* editor) { }
|
||||
virtual void onQuickToolChange(Editor* editor) { }
|
||||
virtual void onActiveToolChange(Editor* editor, tools::Tool* tool) { }
|
||||
|
||||
// Called when the user presses a mouse button over the editor.
|
||||
virtual bool onMouseDown(Editor* editor, ui::MouseMessage* msg) { return false; }
|
||||
|
35
src/app/ui/editor/glue.h
Normal file
35
src/app/ui/editor/glue.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
// published by the Free Software Foundation.
|
||||
|
||||
#ifndef APP_UI_EDITOR_GLUE_H_INCLUDED
|
||||
#define APP_UI_EDITOR_GLUE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/tools/pointer.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "ui/message.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
// Code to convert "ui" messages to "tools" mouse pointers
|
||||
|
||||
inline tools::Pointer::Button button_from_msg(ui::MouseMessage* msg) {
|
||||
return
|
||||
(msg->right() ? tools::Pointer::Right:
|
||||
(msg->middle() ? tools::Pointer::Middle:
|
||||
tools::Pointer::Left));
|
||||
}
|
||||
|
||||
inline tools::Pointer pointer_from_msg(Editor* editor, ui::MouseMessage* msg) {
|
||||
return
|
||||
tools::Pointer(editor->screenToEditor(msg->position()),
|
||||
button_from_msg(msg));
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -110,7 +110,7 @@ MovingPixelsState::~MovingPixelsState()
|
||||
{
|
||||
ContextBar* contextBar = App::instance()->contextBar();
|
||||
contextBar->removeObserver(this);
|
||||
contextBar->updateForCurrentTool();
|
||||
contextBar->updateForActiveTool();
|
||||
|
||||
m_pixelsMovement.reset(NULL);
|
||||
|
||||
@ -192,18 +192,16 @@ EditorState::LeaveAction MovingPixelsState::onLeaveState(Editor* editor, EditorS
|
||||
}
|
||||
}
|
||||
|
||||
void MovingPixelsState::onCurrentToolChange(Editor* editor)
|
||||
void MovingPixelsState::onActiveToolChange(Editor* editor, tools::Tool* tool)
|
||||
{
|
||||
ASSERT(m_pixelsMovement);
|
||||
ASSERT(editor == m_editor);
|
||||
|
||||
tools::Tool* current_tool = editor->getCurrentEditorTool();
|
||||
|
||||
// If the user changed the tool when he/she is moving pixels,
|
||||
// we have to drop the pixels only if the new tool is not selection...
|
||||
if (m_pixelsMovement &&
|
||||
(!current_tool->getInk(0)->isSelection() ||
|
||||
!current_tool->getInk(1)->isSelection())) {
|
||||
(!tool->getInk(0)->isSelection() ||
|
||||
!tool->getInk(1)->isSelection())) {
|
||||
// We have to drop pixels
|
||||
dropPixels();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -39,7 +39,7 @@ namespace app {
|
||||
// EditorState
|
||||
virtual void onEnterState(Editor* editor) override;
|
||||
virtual LeaveAction onLeaveState(Editor* editor, EditorState* newState) override;
|
||||
virtual void onCurrentToolChange(Editor* editor) override;
|
||||
virtual void onActiveToolChange(Editor* editor, tools::Tool* tool) override;
|
||||
virtual bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override;
|
||||
virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
|
||||
virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
|
||||
|
@ -41,7 +41,7 @@ SelectBoxState::SelectBoxState(SelectBoxDelegate* delegate, const gfx::Rect& rc,
|
||||
SelectBoxState::~SelectBoxState()
|
||||
{
|
||||
ContextBar* contextBar = App::instance()->contextBar();
|
||||
contextBar->updateForCurrentTool();
|
||||
contextBar->updateForActiveTool();
|
||||
}
|
||||
|
||||
void SelectBoxState::setFlags(Flags flags)
|
||||
|
@ -112,10 +112,8 @@ void StandbyState::onEnterState(Editor* editor)
|
||||
base::Bind<void>(&StandbyState::onPivotChange, this, editor));
|
||||
}
|
||||
|
||||
void StandbyState::onCurrentToolChange(Editor* editor)
|
||||
void StandbyState::onActiveToolChange(Editor* editor, tools::Tool* tool)
|
||||
{
|
||||
//tools::Tool* currentTool = editor->getCurrentEditorTool();
|
||||
|
||||
// If the user change from a selection tool to a non-selection tool,
|
||||
// or viceversa, we've to show or hide the transformation handles.
|
||||
// TODO Compare the ink (isSelection()) of the previous tool with
|
||||
@ -123,11 +121,6 @@ void StandbyState::onCurrentToolChange(Editor* editor)
|
||||
editor->invalidate();
|
||||
}
|
||||
|
||||
void StandbyState::onQuickToolChange(Editor* editor)
|
||||
{
|
||||
editor->invalidate();
|
||||
}
|
||||
|
||||
bool StandbyState::checkForScroll(Editor* editor, MouseMessage* msg)
|
||||
{
|
||||
tools::Ink* clickedInk = editor->getCurrentEditorInk();
|
||||
|
@ -27,8 +27,7 @@ namespace app {
|
||||
StandbyState();
|
||||
virtual ~StandbyState();
|
||||
virtual void onEnterState(Editor* editor) override;
|
||||
virtual void onCurrentToolChange(Editor* editor) override;
|
||||
virtual void onQuickToolChange(Editor* editor) override;
|
||||
virtual void onActiveToolChange(Editor* editor, tools::Tool* tool) override;
|
||||
virtual bool onMouseDown(Editor* editor, ui::MouseMessage* msg) override;
|
||||
virtual bool onMouseUp(Editor* editor, ui::MouseMessage* msg) override;
|
||||
virtual bool onMouseMove(Editor* editor, ui::MouseMessage* msg) override;
|
||||
|
@ -384,7 +384,7 @@ void MainWindow::configureWorkspaceLayout()
|
||||
Preferences::instance().general.visibleTimeline());
|
||||
|
||||
if (m_contextBar->isVisible()) {
|
||||
m_contextBar->updateForCurrentTool();
|
||||
m_contextBar->updateForActiveTool();
|
||||
}
|
||||
|
||||
layout();
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tools/active_tool.h"
|
||||
#include "app/tools/tool.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/color_button.h"
|
||||
@ -529,15 +530,14 @@ StatusBar::StatusBar()
|
||||
tooltipManager->addTooltipFor(m_currentFrame, "Current Frame", BOTTOM);
|
||||
tooltipManager->addTooltipFor(m_zoomEntry, "Zoom Level", BOTTOM);
|
||||
|
||||
Preferences::instance().toolBox.activeTool.AfterChange.connect(
|
||||
base::Bind<void>(&StatusBar::onCurrentToolChange, this));
|
||||
|
||||
UIContext::instance()->addObserver(this);
|
||||
UIContext::instance()->documents().addObserver(this);
|
||||
App::instance()->activeToolManager()->addObserver(this);
|
||||
}
|
||||
|
||||
StatusBar::~StatusBar()
|
||||
{
|
||||
App::instance()->activeToolManager()->removeObserver(this);
|
||||
UIContext::instance()->documents().removeObserver(this);
|
||||
UIContext::instance()->removeObserver(this);
|
||||
|
||||
@ -545,14 +545,11 @@ StatusBar::~StatusBar()
|
||||
delete m_snapToGridWindow;
|
||||
}
|
||||
|
||||
void StatusBar::onCurrentToolChange()
|
||||
void StatusBar::onSelectedToolChange(tools::Tool* tool)
|
||||
{
|
||||
if (isVisible()) {
|
||||
tools::Tool* tool = App::instance()->activeTool();
|
||||
if (tool) {
|
||||
showTool(500, tool);
|
||||
setTextf("%s Selected", tool->getText().c_str());
|
||||
}
|
||||
if (isVisible() && tool) {
|
||||
showTool(500, tool);
|
||||
setTextf("%s Selected", tool->getText().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "app/color.h"
|
||||
#include "app/tools/active_tool_observer.h"
|
||||
#include "base/observers.h"
|
||||
#include "base/time.h"
|
||||
#include "doc/context_observer.h"
|
||||
@ -46,7 +47,8 @@ namespace app {
|
||||
class StatusBar : public ui::HBox
|
||||
, public doc::ContextObserver
|
||||
, public doc::DocumentsObserver
|
||||
, public doc::DocumentObserver {
|
||||
, public doc::DocumentObserver
|
||||
, public tools::ActiveToolObserver {
|
||||
static StatusBar* m_instance;
|
||||
public:
|
||||
static StatusBar* instance() { return m_instance; }
|
||||
@ -77,8 +79,10 @@ namespace app {
|
||||
// DocumentObserver impl
|
||||
void onPixelFormatChanged(DocumentEvent& ev) override;
|
||||
|
||||
// ActiveToolObserver impl
|
||||
void onSelectedToolChange(tools::Tool* tool) override;
|
||||
|
||||
private:
|
||||
void onCurrentToolChange();
|
||||
void onCelOpacitySliderChange();
|
||||
void newFrame();
|
||||
void onChangeZoom(const render::Zoom& zoom);
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gfx.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/tools/active_tool.h"
|
||||
#include "app/tools/tool_box.h"
|
||||
#include "app/ui/keyboard_shortcuts.h"
|
||||
#include "app/ui/main_window.h"
|
||||
@ -101,10 +101,14 @@ ToolBar::ToolBar()
|
||||
if (m_selectedInGroup.find(tool->getGroup()) == m_selectedInGroup.end())
|
||||
m_selectedInGroup[tool->getGroup()] = tool;
|
||||
}
|
||||
|
||||
App::instance()->activeToolManager()->addObserver(this);
|
||||
}
|
||||
|
||||
ToolBar::~ToolBar()
|
||||
{
|
||||
App::instance()->activeToolManager()->removeObserver(this);
|
||||
|
||||
delete m_popupWindow;
|
||||
delete m_tipWindow;
|
||||
}
|
||||
@ -293,6 +297,7 @@ void ToolBar::onPaint(ui::PaintEvent& ev)
|
||||
gfx::Color normalFace = theme->colors.buttonNormalFace();
|
||||
gfx::Color hotFace = theme->colors.buttonHotFace();
|
||||
ToolBox* toolbox = App::instance()->toolBox();
|
||||
Tool* activeTool = App::instance()->activeTool();
|
||||
ToolGroupList::iterator it = toolbox->begin_group();
|
||||
int groups = toolbox->getGroupsCount();
|
||||
Rect toolrc;
|
||||
@ -305,7 +310,7 @@ void ToolBar::onPaint(ui::PaintEvent& ev)
|
||||
gfx::Color face;
|
||||
SkinPartPtr nw;
|
||||
|
||||
if (App::instance()->activeTool() == tool || m_hotIndex == c) {
|
||||
if (activeTool == tool || m_hotIndex == c) {
|
||||
nw = theme->parts.toolbuttonHot();
|
||||
face = hotFace;
|
||||
}
|
||||
@ -541,8 +546,8 @@ void ToolBar::selectTool(Tool* tool)
|
||||
|
||||
m_selectedInGroup[tool->getGroup()] = tool;
|
||||
|
||||
// Set active tool in preferences.
|
||||
Preferences::instance().toolBox.activeTool(tool->getId());
|
||||
// Inform to the active tool manager about this tool change.
|
||||
App::instance()->activeToolManager()->setSelectedTool(tool);
|
||||
|
||||
if (m_currentStrip)
|
||||
m_currentStrip->invalidate();
|
||||
@ -679,6 +684,7 @@ void ToolBar::ToolStrip::onPaint(PaintEvent& ev)
|
||||
Graphics* g = ev.graphics();
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
ToolBox* toolbox = App::instance()->toolBox();
|
||||
Tool* activeTool = App::instance()->activeTool();
|
||||
Rect toolrc;
|
||||
int index = 0;
|
||||
|
||||
@ -688,8 +694,7 @@ void ToolBar::ToolStrip::onPaint(PaintEvent& ev)
|
||||
gfx::Color face;
|
||||
SkinPartPtr nw;
|
||||
|
||||
if (App::instance()->activeTool() == tool ||
|
||||
m_hotTool == tool) {
|
||||
if (activeTool == tool || m_hotTool == tool) {
|
||||
nw = theme->parts.toolbuttonHot();
|
||||
face = theme->colors.buttonHotFace();
|
||||
}
|
||||
@ -723,4 +728,12 @@ Rect ToolBar::ToolStrip::getToolBounds(int index)
|
||||
iconsize.w, bounds.h);
|
||||
}
|
||||
|
||||
void ToolBar::onSelectedToolChange(tools::Tool* tool)
|
||||
{
|
||||
if (tool && m_selectedInGroup[tool->getGroup()] != tool)
|
||||
m_selectedInGroup[tool->getGroup()] = tool;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2 as
|
||||
@ -9,6 +9,7 @@
|
||||
#define APP_UI_TOOLBAR_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/tools/active_tool_observer.h"
|
||||
#include "base/connection.h"
|
||||
#include "gfx/point.h"
|
||||
#include "ui/timer.h"
|
||||
@ -29,7 +30,8 @@ namespace app {
|
||||
}
|
||||
|
||||
// Class to show selected tools for each tool (vertically)
|
||||
class ToolBar : public ui::Widget {
|
||||
class ToolBar : public ui::Widget
|
||||
, public tools::ActiveToolObserver {
|
||||
static ToolBar* m_instance;
|
||||
public:
|
||||
static ToolBar* instance() { return m_instance; }
|
||||
@ -59,6 +61,9 @@ namespace app {
|
||||
void openTipWindow(int group_index, tools::Tool* tool);
|
||||
void onClosePopup();
|
||||
|
||||
// ActiveToolObserver impl
|
||||
void onSelectedToolChange(tools::Tool* tool) override;
|
||||
|
||||
// What tool is selected for each tool-group
|
||||
std::map<const tools::ToolGroup*, tools::Tool*> m_selectedInGroup;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user