mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-12 16:14:10 +00:00
Unify Cut/Copy/Paste/Clear handling with InputChain class
This commit is contained in:
parent
e60236640a
commit
2bbaa45844
@ -329,6 +329,7 @@ add_library(app-lib
|
||||
ui/frame_tag_window.cpp
|
||||
ui/hex_color_entry.cpp
|
||||
ui/home_view.cpp
|
||||
ui/input_chain.cpp
|
||||
ui/keyboard_shortcuts.cpp
|
||||
ui/main_menu_bar.cpp
|
||||
ui/main_window.cpp
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "app/ui/document_view.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/editor/editor_view.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
#include "app/ui/keyboard_shortcuts.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
@ -94,6 +95,7 @@ public:
|
||||
CommandsModule m_commands_modules;
|
||||
UIContext m_ui_context;
|
||||
RecentFiles m_recent_files;
|
||||
InputChain m_inputChain;
|
||||
// This is a raw pointer because we want to delete this explicitly.
|
||||
app::crash::DataRecovery* m_recovery;
|
||||
scripting::Engine m_scriptingEngine;
|
||||
@ -683,6 +685,11 @@ void App::updateDisplayTitleBar()
|
||||
she::instance()->defaultDisplay()->setTitleBar(title);
|
||||
}
|
||||
|
||||
InputChain& App::inputChain()
|
||||
{
|
||||
return m_modules->m_inputChain;
|
||||
}
|
||||
|
||||
// Updates palette and redraw the screen.
|
||||
void app_refresh_screen()
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ namespace app {
|
||||
class Document;
|
||||
class DocumentExporter;
|
||||
class INotificationDelegate;
|
||||
class InputChain;
|
||||
class LegacyModules;
|
||||
class LoggerModule;
|
||||
class MainWindow;
|
||||
@ -70,6 +71,8 @@ namespace app {
|
||||
void showNotification(INotificationDelegate* del);
|
||||
void updateDisplayTitleBar();
|
||||
|
||||
InputChain& inputChain();
|
||||
|
||||
// App Signals
|
||||
Signal0<void> Exit;
|
||||
Signal0<void> PaletteChange;
|
||||
|
@ -11,10 +11,11 @@
|
||||
|
||||
#include "app/commands/command.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/commands/params.h"
|
||||
#include "app/context.h"
|
||||
#include "ui/manager.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -60,20 +61,14 @@ void CancelCommand::onExecute(Context* context)
|
||||
break;
|
||||
|
||||
case All:
|
||||
// TODO should the ContextBar be a InputChainElement to intercept onCancel()?
|
||||
// Discard brush
|
||||
{
|
||||
Command* discardBrush = CommandsModule::instance()->getCommandByName(CommandId::DiscardBrush);
|
||||
context->executeCommand(discardBrush);
|
||||
}
|
||||
|
||||
// Deselect mask
|
||||
if (context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasVisibleMask)) {
|
||||
Command* deselectMask = CommandsModule::instance()->getCommandByName(CommandId::DeselectMask);
|
||||
context->executeCommand(deselectMask);
|
||||
}
|
||||
|
||||
ui::Manager::getDefault()->invalidate();
|
||||
App::instance()->inputChain().cancel(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -10,18 +10,8 @@
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/cmd/clear_mask.h"
|
||||
#include "app/cmd/deselect_mask.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/transaction.h"
|
||||
#include "app/ui/color_bar.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/timeline.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/mask.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -31,8 +21,8 @@ public:
|
||||
Command* clone() const override { return new ClearCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
bool onEnabled(Context* ctx) override;
|
||||
void onExecute(Context* ctx) override;
|
||||
};
|
||||
|
||||
ClearCommand::ClearCommand()
|
||||
@ -42,58 +32,14 @@ ClearCommand::ClearCommand()
|
||||
{
|
||||
}
|
||||
|
||||
bool ClearCommand::onEnabled(Context* context)
|
||||
bool ClearCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable |
|
||||
ContextFlags::ActiveLayerIsImage);
|
||||
return App::instance()->inputChain().canClear(ctx);
|
||||
}
|
||||
|
||||
void ClearCommand::onExecute(Context* context)
|
||||
void ClearCommand::onExecute(Context* ctx)
|
||||
{
|
||||
// Clear of several frames is handled with ClearCel command.
|
||||
DocumentRange range = App::instance()->getMainWindow()->getTimeline()->range();
|
||||
if (range.enabled()) {
|
||||
Command* subCommand = NULL;
|
||||
|
||||
switch (range.type()) {
|
||||
case DocumentRange::kCels:
|
||||
subCommand = CommandsModule::instance()->getCommandByName(CommandId::ClearCel);
|
||||
break;
|
||||
case DocumentRange::kFrames:
|
||||
subCommand = CommandsModule::instance()->getCommandByName(CommandId::RemoveFrame);
|
||||
break;
|
||||
case DocumentRange::kLayers:
|
||||
subCommand = CommandsModule::instance()->getCommandByName(CommandId::RemoveLayer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (subCommand) {
|
||||
context->executeCommand(subCommand);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add support to clear the mask in the selected range of frames.
|
||||
|
||||
ContextWriter writer(context);
|
||||
Document* document = writer.document();
|
||||
bool visibleMask = document->isMaskVisible();
|
||||
|
||||
if (!writer.cel())
|
||||
return;
|
||||
|
||||
{
|
||||
Transaction transaction(writer.context(), "Clear");
|
||||
transaction.execute(new cmd::ClearMask(writer.cel()));
|
||||
if (visibleMask)
|
||||
transaction.execute(new cmd::DeselectMask(document));
|
||||
transaction.commit();
|
||||
}
|
||||
if (visibleMask)
|
||||
document->generateMaskBoundaries();
|
||||
update_screen_for_document(document);
|
||||
App::instance()->inputChain().clear(ctx);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createClearCommand()
|
||||
|
@ -11,16 +11,7 @@
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/timeline.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/site.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "ui/base.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -30,8 +21,8 @@ public:
|
||||
Command* clone() const override { return new CopyCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
bool onEnabled(Context* ctx) override;
|
||||
void onExecute(Context* ctx) override;
|
||||
};
|
||||
|
||||
CopyCommand::CopyCommand()
|
||||
@ -41,25 +32,14 @@ CopyCommand::CopyCommand()
|
||||
{
|
||||
}
|
||||
|
||||
bool CopyCommand::onEnabled(Context* context)
|
||||
bool CopyCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
return context->checkFlags(ContextFlags::HasActiveDocument);
|
||||
return App::instance()->inputChain().canCopy(ctx);
|
||||
}
|
||||
|
||||
void CopyCommand::onExecute(Context* context)
|
||||
void CopyCommand::onExecute(Context* ctx)
|
||||
{
|
||||
const ContextReader reader(context);
|
||||
|
||||
// Copy a range from the timeline.
|
||||
DocumentRange range = App::instance()->getMainWindow()->getTimeline()->range();
|
||||
if (range.enabled()) {
|
||||
clipboard::copy_range(reader, range);
|
||||
}
|
||||
else if (reader.site()->document() &&
|
||||
static_cast<const app::Document*>(reader.site()->document())->isMaskVisible() &&
|
||||
reader.site()->image()) {
|
||||
clipboard::copy(reader);
|
||||
}
|
||||
App::instance()->inputChain().copy(ctx);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createCopyCommand()
|
||||
|
@ -9,13 +9,9 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "ui/base.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -25,8 +21,8 @@ public:
|
||||
Command* clone() const override { return new CutCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
bool onEnabled(Context* ctx) override;
|
||||
void onExecute(Context* ctx) override;
|
||||
};
|
||||
|
||||
CutCommand::CutCommand()
|
||||
@ -36,19 +32,14 @@ CutCommand::CutCommand()
|
||||
{
|
||||
}
|
||||
|
||||
bool CutCommand::onEnabled(Context* context)
|
||||
bool CutCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable |
|
||||
ContextFlags::HasVisibleMask |
|
||||
ContextFlags::HasActiveImage);
|
||||
return App::instance()->inputChain().canCut(ctx);
|
||||
}
|
||||
|
||||
void CutCommand::onExecute(Context* context)
|
||||
void CutCommand::onExecute(Context* ctx)
|
||||
{
|
||||
ContextWriter writer(context);
|
||||
clipboard::cut(writer);
|
||||
App::instance()->inputChain().cut(ctx);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createCutCommand()
|
||||
|
@ -9,11 +9,9 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/context.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -23,8 +21,8 @@ public:
|
||||
Command* clone() const override { return new PasteCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
bool onEnabled(Context* ctx) override;
|
||||
void onExecute(Context* ctx) override;
|
||||
};
|
||||
|
||||
PasteCommand::PasteCommand()
|
||||
@ -34,21 +32,14 @@ PasteCommand::PasteCommand()
|
||||
{
|
||||
}
|
||||
|
||||
bool PasteCommand::onEnabled(Context* context)
|
||||
bool PasteCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
return
|
||||
(clipboard::get_current_format() == clipboard::ClipboardImage &&
|
||||
context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable |
|
||||
ContextFlags::ActiveLayerIsImage)) ||
|
||||
(clipboard::get_current_format() == clipboard::ClipboardDocumentRange &&
|
||||
context->checkFlags(ContextFlags::ActiveDocumentIsWritable));
|
||||
return App::instance()->inputChain().canPaste(ctx);
|
||||
}
|
||||
|
||||
void PasteCommand::onExecute(Context* context)
|
||||
void PasteCommand::onExecute(Context* ctx)
|
||||
{
|
||||
clipboard::paste();
|
||||
App::instance()->inputChain().paste(ctx);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createPasteCommand()
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "app/transaction.h"
|
||||
#include "app/ui/color_spectrum.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui_context.h"
|
||||
@ -41,6 +42,7 @@
|
||||
#include "she/surface.h"
|
||||
#include "ui/graphics.h"
|
||||
#include "ui/menu.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/paint_event.h"
|
||||
#include "ui/separator.h"
|
||||
#include "ui/splitter.h"
|
||||
@ -187,6 +189,7 @@ ColorBar::ColorBar(int align)
|
||||
|
||||
UIContext::instance()->addObserver(this);
|
||||
m_conn = UIContext::instance()->BeforeCommandExecution.connect(&ColorBar::onBeforeExecuteCommand, this);
|
||||
m_paletteView.FocusEnter.connect(&ColorBar::onFocusPaletteView, this);
|
||||
}
|
||||
|
||||
ColorBar::~ColorBar()
|
||||
@ -243,6 +246,11 @@ void ColorBar::onActiveSiteChange(const doc::Site& site)
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBar::onFocusPaletteView()
|
||||
{
|
||||
App::instance()->inputChain().prioritize(this);
|
||||
}
|
||||
|
||||
void ColorBar::onBeforeExecuteCommand(Command* command)
|
||||
{
|
||||
if (command->id() == CommandId::Undo ||
|
||||
@ -474,7 +482,7 @@ void ColorBar::onBgColorButtonChange(const app::Color& color)
|
||||
void ColorBar::onColorButtonChange(const app::Color& color)
|
||||
{
|
||||
if (color.getType() == app::Color::IndexType)
|
||||
m_paletteView.selectColor(color.getIndex());
|
||||
m_paletteView.selectColor(color.getIndex(), false);
|
||||
}
|
||||
|
||||
void ColorBar::onPickSpectrum(const app::Color& color, ui::MouseButtons buttons)
|
||||
@ -593,4 +601,58 @@ void ColorBar::destroyRemap()
|
||||
layout();
|
||||
}
|
||||
|
||||
void ColorBar::onNewInputPriority(InputChainElement* element)
|
||||
{
|
||||
m_paletteView.clearSelection();
|
||||
}
|
||||
|
||||
bool ColorBar::onCanCut(Context* ctx)
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool ColorBar::onCanCopy(Context* ctx)
|
||||
{
|
||||
return (m_paletteView.getSelectedEntriesCount() > 0);
|
||||
}
|
||||
|
||||
bool ColorBar::onCanPaste(Context* ctx)
|
||||
{
|
||||
return m_paletteView.areColorsInClipboard();
|
||||
}
|
||||
|
||||
bool ColorBar::onCanClear(Context* ctx)
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool ColorBar::onCut(Context* ctx)
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool ColorBar::onCopy(Context* ctx)
|
||||
{
|
||||
m_paletteView.copyToClipboard();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ColorBar::onPaste(Context* ctx)
|
||||
{
|
||||
m_paletteView.pasteFromClipboard();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ColorBar::onClear(Context* ctx)
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
void ColorBar::onCancel(Context* ctx)
|
||||
{
|
||||
m_paletteView.clearSelection();
|
||||
m_paletteView.discardClipboardSelection();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "app/color.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "app/ui/input_chain_element.h"
|
||||
#include "app/ui/palette_popup.h"
|
||||
#include "app/ui/palette_view.h"
|
||||
#include "base/connection.h"
|
||||
@ -32,7 +33,8 @@ namespace app {
|
||||
|
||||
class ColorBar : public ui::Box
|
||||
, public PaletteViewDelegate
|
||||
, public doc::ContextObserver {
|
||||
, public doc::ContextObserver
|
||||
, public app::InputChainElement {
|
||||
static ColorBar* m_instance;
|
||||
public:
|
||||
static ColorBar* instance() { return m_instance; }
|
||||
@ -56,11 +58,24 @@ namespace app {
|
||||
// ContextObserver impl
|
||||
void onActiveSiteChange(const doc::Site& site) override;
|
||||
|
||||
// InputChainElement impl
|
||||
void onNewInputPriority(InputChainElement* element) override;
|
||||
bool onCanCut(Context* ctx) override;
|
||||
bool onCanCopy(Context* ctx) override;
|
||||
bool onCanPaste(Context* ctx) override;
|
||||
bool onCanClear(Context* ctx) override;
|
||||
bool onCut(Context* ctx) override;
|
||||
bool onCopy(Context* ctx) override;
|
||||
bool onPaste(Context* ctx) override;
|
||||
bool onClear(Context* ctx) override;
|
||||
void onCancel(Context* ctx) override;
|
||||
|
||||
// Signals
|
||||
Signal1<void, const app::Color&> FgColorChange;
|
||||
Signal1<void, const app::Color&> BgColorChange;
|
||||
|
||||
protected:
|
||||
void onFocusPaletteView();
|
||||
void onBeforeExecuteCommand(Command* command);
|
||||
void onPaletteButtonClick();
|
||||
void onRemapButtonClick();
|
||||
|
@ -133,7 +133,7 @@ void ColorSelector::setColor(const app::Color& color, SetColorOptions options)
|
||||
|
||||
if (color.getType() == app::Color::IndexType) {
|
||||
m_colorPalette.clearSelection();
|
||||
m_colorPalette.selectColor(color.getIndex());
|
||||
m_colorPalette.selectColor(color.getIndex(), false);
|
||||
}
|
||||
|
||||
m_rgbSliders.setColor(m_color);
|
||||
@ -306,7 +306,7 @@ void ColorSelector::findBestfitIndex(const app::Color& color)
|
||||
int i = get_current_palette()->findBestfit(r, g, b);
|
||||
if (i >= 0 && i < 256) {
|
||||
m_colorPalette.clearSelection();
|
||||
m_colorPalette.selectColor(i);
|
||||
m_colorPalette.selectColor(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,15 @@
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/app_menus.h"
|
||||
#include "app/cmd/clear_mask.h"
|
||||
#include "app/cmd/deselect_mask.h"
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/console.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document_access.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/transaction.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/editor/editor_customization_delegate.h"
|
||||
#include "app/ui/editor/editor_view.h"
|
||||
@ -27,6 +31,7 @@
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/ui/workspace.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "base/path.h"
|
||||
#include "doc/document_event.h"
|
||||
#include "doc/layer.h"
|
||||
@ -434,4 +439,109 @@ void DocumentView::onLayerRestacked(doc::DocumentEvent& ev)
|
||||
m_editor->invalidate();
|
||||
}
|
||||
|
||||
void DocumentView::onNewInputPriority(InputChainElement* element)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
bool DocumentView::onCanCut(Context* ctx)
|
||||
{
|
||||
return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable |
|
||||
ContextFlags::HasVisibleMask |
|
||||
ContextFlags::HasActiveImage);
|
||||
}
|
||||
|
||||
bool DocumentView::onCanCopy(Context* ctx)
|
||||
{
|
||||
return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable |
|
||||
ContextFlags::HasVisibleMask |
|
||||
ContextFlags::HasActiveImage);
|
||||
}
|
||||
|
||||
bool DocumentView::onCanPaste(Context* ctx)
|
||||
{
|
||||
return
|
||||
(clipboard::get_current_format() == clipboard::ClipboardImage &&
|
||||
ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable |
|
||||
ContextFlags::ActiveLayerIsImage));
|
||||
}
|
||||
|
||||
bool DocumentView::onCanClear(Context* ctx)
|
||||
{
|
||||
return ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable |
|
||||
ContextFlags::ActiveLayerIsImage);
|
||||
}
|
||||
|
||||
bool DocumentView::onCut(Context* ctx)
|
||||
{
|
||||
ContextWriter writer(ctx);
|
||||
clipboard::cut(writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DocumentView::onCopy(Context* ctx)
|
||||
{
|
||||
const ContextReader reader(ctx);
|
||||
if (reader.site()->document() &&
|
||||
static_cast<const app::Document*>(reader.site()->document())->isMaskVisible() &&
|
||||
reader.site()->image()) {
|
||||
clipboard::copy(reader);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DocumentView::onPaste(Context* ctx)
|
||||
{
|
||||
if (clipboard::get_current_format() == clipboard::ClipboardImage) {
|
||||
clipboard::paste();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DocumentView::onClear(Context* ctx)
|
||||
{
|
||||
ContextWriter writer(ctx);
|
||||
Document* document = writer.document();
|
||||
bool visibleMask = document->isMaskVisible();
|
||||
|
||||
if (!writer.cel())
|
||||
return false;
|
||||
|
||||
{
|
||||
Transaction transaction(writer.context(), "Clear");
|
||||
transaction.execute(new cmd::ClearMask(writer.cel()));
|
||||
if (visibleMask)
|
||||
transaction.execute(new cmd::DeselectMask(document));
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
if (visibleMask)
|
||||
document->generateMaskBoundaries();
|
||||
|
||||
document->notifyGeneralUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DocumentView::onCancel(Context* ctx)
|
||||
{
|
||||
// Deselect mask
|
||||
if (ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasVisibleMask)) {
|
||||
Command* deselectMask = CommandsModule::instance()->getCommandByName(CommandId::DeselectMask);
|
||||
ctx->executeCommand(deselectMask);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define APP_UI_DOCUMENT_VIEW_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/ui/input_chain_element.h"
|
||||
#include "app/ui/tabs.h"
|
||||
#include "app/ui/workspace_view.h"
|
||||
#include "doc/document_observer.h"
|
||||
@ -29,7 +30,8 @@ namespace app {
|
||||
class DocumentView : public ui::Box
|
||||
, public TabView
|
||||
, public doc::DocumentObserver
|
||||
, public WorkspaceView {
|
||||
, public WorkspaceView
|
||||
, public app::InputChainElement {
|
||||
public:
|
||||
enum Type {
|
||||
Normal,
|
||||
@ -57,6 +59,7 @@ namespace app {
|
||||
void onClonedFrom(WorkspaceView* from) override;
|
||||
bool onCloseView(Workspace* workspace) override;
|
||||
void onTabPopup(Workspace* workspace) override;
|
||||
InputChainElement* onGetInputChainElement() override { return this; }
|
||||
|
||||
// DocumentObserver implementation
|
||||
void onGeneralUpdate(doc::DocumentEvent& ev) override;
|
||||
@ -69,6 +72,18 @@ namespace app {
|
||||
void onTotalFramesChanged(doc::DocumentEvent& ev) override;
|
||||
void onLayerRestacked(doc::DocumentEvent& ev) override;
|
||||
|
||||
// InputChainElement impl
|
||||
void onNewInputPriority(InputChainElement* element) override;
|
||||
bool onCanCut(Context* ctx) override;
|
||||
bool onCanCopy(Context* ctx) override;
|
||||
bool onCanPaste(Context* ctx) override;
|
||||
bool onCanClear(Context* ctx) override;
|
||||
bool onCut(Context* ctx) override;
|
||||
bool onCopy(Context* ctx) override;
|
||||
bool onPaste(Context* ctx) override;
|
||||
bool onClear(Context* ctx) override;
|
||||
void onCancel(Context* ctx) override;
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(ui::Message* msg) override;
|
||||
|
||||
|
109
src/app/ui/input_chain.cpp
Normal file
109
src/app/ui/input_chain.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 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/ui/input_chain.h"
|
||||
|
||||
#include "app/ui/input_chain_element.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace app {
|
||||
|
||||
void InputChain::prioritize(InputChainElement* element)
|
||||
{
|
||||
if (!m_elements.empty() && m_elements.front() == element)
|
||||
return;
|
||||
|
||||
auto it = std::find(m_elements.begin(), m_elements.end(), element);
|
||||
if (it != m_elements.end())
|
||||
m_elements.erase(it);
|
||||
|
||||
for (auto e : m_elements)
|
||||
e->onNewInputPriority(element);
|
||||
|
||||
m_elements.insert(m_elements.begin(), element);
|
||||
}
|
||||
|
||||
bool InputChain::canCut(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onCanCut(ctx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputChain::canCopy(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onCanCopy(ctx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputChain::canPaste(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onCanPaste(ctx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputChain::canClear(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onCanClear(ctx))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputChain::cut(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onCut(ctx))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InputChain::copy(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onCopy(ctx))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InputChain::paste(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onPaste(ctx))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InputChain::clear(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements) {
|
||||
if (e->onClear(ctx))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InputChain::cancel(Context* ctx)
|
||||
{
|
||||
for (auto e : m_elements)
|
||||
e->onCancel(ctx);
|
||||
}
|
||||
|
||||
} // namespace app
|
44
src/app/ui/input_chain.h
Normal file
44
src/app/ui/input_chain.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 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_INPUT_CHAIN_H_INCLUDED
|
||||
#define APP_INPUT_CHAIN_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "base/observable.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
class Context;
|
||||
class InputChainElement;
|
||||
|
||||
// The chain of objects (in order) that want to receive
|
||||
// input/commands from the user (e.g. ColorBar, Timeline, and
|
||||
// Workspace/DocumentView). When each of these elements receive the
|
||||
// user focus, they call InputChain::prioritize().
|
||||
class InputChain {
|
||||
public:
|
||||
void prioritize(InputChainElement* element);
|
||||
|
||||
bool canCut(Context* ctx);
|
||||
bool canCopy(Context* ctx);
|
||||
bool canPaste(Context* ctx);
|
||||
bool canClear(Context* ctx);
|
||||
|
||||
void cut(Context* ctx);
|
||||
void copy(Context* ctx);
|
||||
void paste(Context* ctx);
|
||||
void clear(Context* ctx);
|
||||
void cancel(Context* ctx);
|
||||
|
||||
private:
|
||||
std::vector<InputChainElement*> m_elements;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
37
src/app/ui/input_chain_element.h
Normal file
37
src/app/ui/input_chain_element.h
Normal file
@ -0,0 +1,37 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 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_INPUT_CHAIN_ELEMENT_H_INCLUDED
|
||||
#define APP_INPUT_CHAIN_ELEMENT_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
namespace app {
|
||||
|
||||
class Context;
|
||||
|
||||
class InputChainElement {
|
||||
public:
|
||||
virtual ~InputChainElement() { }
|
||||
|
||||
// Called when a new element has priorty in the chain.
|
||||
virtual void onNewInputPriority(InputChainElement* element) = 0;
|
||||
|
||||
virtual bool onCanCut(Context* ctx) = 0;
|
||||
virtual bool onCanCopy(Context* ctx) = 0;
|
||||
virtual bool onCanPaste(Context* ctx) = 0;
|
||||
virtual bool onCanClear(Context* ctx) = 0;
|
||||
|
||||
virtual bool onCut(Context* ctx) = 0;
|
||||
virtual bool onCopy(Context* ctx) = 0;
|
||||
virtual bool onPaste(Context* ctx) = 0;
|
||||
virtual bool onClear(Context* ctx) = 0;
|
||||
virtual void onCancel(Context* ctx) = 0;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -17,7 +17,6 @@
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/keyboard_shortcuts.h"
|
||||
#include "app/ui/palette_view.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/skin/style.h"
|
||||
@ -104,18 +103,25 @@ void PaletteView::setColumns(int columns)
|
||||
|
||||
void PaletteView::clearSelection()
|
||||
{
|
||||
bool invalidate = (m_selectedEntries.picks() > 0);
|
||||
|
||||
std::fill(m_selectedEntries.begin(),
|
||||
m_selectedEntries.end(), false);
|
||||
|
||||
if (invalidate)
|
||||
this->invalidate();
|
||||
}
|
||||
|
||||
void PaletteView::selectColor(int index)
|
||||
void PaletteView::selectColor(int index, bool startRange)
|
||||
{
|
||||
ASSERT(index >= 0 && index < Palette::MaxColors);
|
||||
|
||||
if (m_currentEntry != index || !m_selectedEntries[index]) {
|
||||
m_currentEntry = index;
|
||||
m_rangeAnchor = index;
|
||||
m_selectedEntries[index] = true;
|
||||
|
||||
if (startRange)
|
||||
m_selectedEntries[index] = true;
|
||||
|
||||
update_scroll(m_currentEntry);
|
||||
invalidate();
|
||||
@ -172,6 +178,11 @@ void PaletteView::getSelectedEntries(PalettePicks& entries) const
|
||||
entries = m_selectedEntries;
|
||||
}
|
||||
|
||||
int PaletteView::getSelectedEntriesCount() const
|
||||
{
|
||||
return m_selectedEntries.picks();
|
||||
}
|
||||
|
||||
app::Color PaletteView::getColorByPosition(const gfx::Point& pos)
|
||||
{
|
||||
gfx::Point relPos = pos - getBounds().getOrigin();
|
||||
@ -218,10 +229,31 @@ void PaletteView::pasteFromClipboard()
|
||||
m_delegate->onPaletteViewPasteColors(
|
||||
m_clipboardEditor, m_clipboardEntries, m_selectedEntries);
|
||||
|
||||
// We just hide the marching ants, the user can paste multiple
|
||||
// times.
|
||||
stopMarchingAnts();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteView::discardClipboardSelection()
|
||||
{
|
||||
bool redraw = false;
|
||||
|
||||
if (m_clipboardEditor) {
|
||||
setClipboardEditor(nullptr);
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
if (areColorsInClipboard()) {
|
||||
stopMarchingAnts();
|
||||
redraw = true;
|
||||
}
|
||||
|
||||
if (redraw)
|
||||
invalidate();
|
||||
}
|
||||
|
||||
bool PaletteView::areColorsInClipboard() const
|
||||
{
|
||||
return isMarchingAntsRunning();
|
||||
@ -231,36 +263,13 @@ bool PaletteView::onProcessMessage(Message* msg)
|
||||
{
|
||||
switch (msg->type()) {
|
||||
|
||||
case kKeyDownMessage: {
|
||||
Key* key = KeyboardShortcuts::instance()->command(CommandId::Copy);
|
||||
if (key && key->isPressed(msg)) {
|
||||
copyToClipboard();
|
||||
return true;
|
||||
}
|
||||
|
||||
key = KeyboardShortcuts::instance()->command(CommandId::Paste);
|
||||
if (key && key->isPressed(msg)) {
|
||||
pasteFromClipboard();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isMarchingAntsRunning()) {
|
||||
key = KeyboardShortcuts::instance()->command(CommandId::DeselectMask);
|
||||
Key* esc = KeyboardShortcuts::instance()->command(CommandId::Cancel);
|
||||
if ((key && key->isPressed(msg)) ||
|
||||
(esc && esc->isPressed(msg))) {
|
||||
stopMarchingAnts();
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
updateCopyFlag(msg);
|
||||
case kFocusEnterMessage:
|
||||
FocusEnter();
|
||||
break;
|
||||
}
|
||||
|
||||
case kMouseEnterMessage:
|
||||
case kKeyDownMessage:
|
||||
case kKeyUpMessage:
|
||||
case kMouseEnterMessage:
|
||||
updateCopyFlag(msg);
|
||||
break;
|
||||
|
||||
@ -297,7 +306,7 @@ bool PaletteView::onProcessMessage(Message* msg)
|
||||
if (msg->type() == kMouseMoveMessage)
|
||||
selectRange(m_rangeAnchor, idx);
|
||||
else
|
||||
selectColor(idx);
|
||||
selectColor(idx, true);
|
||||
|
||||
// Emit signal
|
||||
if (m_delegate)
|
||||
@ -478,10 +487,8 @@ void PaletteView::onDrawMarchingAnts()
|
||||
|
||||
void PaletteView::onDestroyEditor(Editor* editor)
|
||||
{
|
||||
if (m_clipboardEditor == editor) {
|
||||
setClipboardEditor(nullptr);
|
||||
stopMarchingAnts();
|
||||
}
|
||||
if (m_clipboardEditor == editor)
|
||||
discardClipboardSelection();
|
||||
}
|
||||
|
||||
void PaletteView::request_size(int* w, int* h)
|
||||
|
@ -52,12 +52,13 @@ namespace app {
|
||||
void setColumns(int columns);
|
||||
|
||||
void clearSelection();
|
||||
void selectColor(int index);
|
||||
void selectColor(int index, bool startRange);
|
||||
void selectRange(int index1, int index2);
|
||||
|
||||
int getSelectedEntry() const;
|
||||
bool getSelectedRange(int& index1, int& index2) const;
|
||||
void getSelectedEntries(doc::PalettePicks& entries) const;
|
||||
int getSelectedEntriesCount() const;
|
||||
|
||||
app::Color getColorByPosition(const gfx::Point& pos);
|
||||
|
||||
@ -66,8 +67,11 @@ namespace app {
|
||||
|
||||
void copyToClipboard();
|
||||
void pasteFromClipboard();
|
||||
void discardClipboardSelection();
|
||||
bool areColorsInClipboard() const;
|
||||
|
||||
Signal0<void> FocusEnter;
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(ui::Message* msg) override;
|
||||
void onPaint(ui::PaintEvent& ev) override;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "app/ui/configure_timeline_popup.h"
|
||||
#include "app/ui/document_view.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/skin/style.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
@ -138,14 +139,6 @@ void Timeline::updateUsingEditor(Editor* editor)
|
||||
{
|
||||
m_aniControls.updateUsingEditor(editor);
|
||||
|
||||
// As a sprite editor was selected, it looks like the user wants to
|
||||
// execute commands targetting the editor instead of the
|
||||
// timeline. Here we disable the selected range, so commands like
|
||||
// Clear, Copy, Cut, etc. don't target the Timeline and they are
|
||||
// sent to the active sprite editor.
|
||||
m_range.disableRange();
|
||||
invalidate();
|
||||
|
||||
detachDocument();
|
||||
|
||||
// We always update the editor. In this way the timeline keeps in
|
||||
@ -246,6 +239,10 @@ bool Timeline::onProcessMessage(Message* msg)
|
||||
{
|
||||
switch (msg->type()) {
|
||||
|
||||
case kFocusEnterMessage:
|
||||
App::instance()->inputChain().prioritize(this);
|
||||
break;
|
||||
|
||||
case kTimerMessage:
|
||||
if (static_cast<TimerMessage*>(msg)->timer() == &m_clipboard_timer) {
|
||||
Document* clipboard_document;
|
||||
@ -2333,4 +2330,101 @@ FrameTag* Timeline::Hit::getFrameTag() const
|
||||
return get<FrameTag>(frameTag);
|
||||
}
|
||||
|
||||
void Timeline::onNewInputPriority(InputChainElement* element)
|
||||
{
|
||||
// As a another input element has priority (e.g. Timeline or
|
||||
// Editor), it looks like the user wants to execute commands
|
||||
// targetting the editor instead of the timeline. Here we disable
|
||||
// the selected range, so commands like Clear, Copy, Cut, etc. don't
|
||||
// target the Timeline and they are sent to the active sprite
|
||||
// editor.
|
||||
m_range.disableRange();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
bool Timeline::onCanCut(Context* ctx)
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool Timeline::onCanCopy(Context* ctx)
|
||||
{
|
||||
return
|
||||
m_range.enabled() &&
|
||||
ctx->checkFlags(ContextFlags::HasActiveDocument);
|
||||
}
|
||||
|
||||
bool Timeline::onCanPaste(Context* ctx)
|
||||
{
|
||||
return
|
||||
(clipboard::get_current_format() == clipboard::ClipboardDocumentRange &&
|
||||
ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable));
|
||||
}
|
||||
|
||||
bool Timeline::onCanClear(Context* ctx)
|
||||
{
|
||||
return (m_document && m_sprite && m_range.enabled());
|
||||
}
|
||||
|
||||
bool Timeline::onCut(Context* ctx)
|
||||
{
|
||||
return false; // TODO
|
||||
}
|
||||
|
||||
bool Timeline::onCopy(Context* ctx)
|
||||
{
|
||||
if (m_range.enabled()) {
|
||||
const ContextReader reader(ctx);
|
||||
if (reader.document()) {
|
||||
clipboard::copy_range(reader, m_range);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Timeline::onPaste(Context* ctx)
|
||||
{
|
||||
if (clipboard::get_current_format() == clipboard::ClipboardDocumentRange) {
|
||||
clipboard::paste();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Timeline::onClear(Context* ctx)
|
||||
{
|
||||
if (!m_document || !m_sprite || !m_range.enabled())
|
||||
return false;
|
||||
|
||||
Command* cmd = nullptr;
|
||||
|
||||
switch (m_range.type()) {
|
||||
case DocumentRange::kCels:
|
||||
cmd = CommandsModule::instance()->getCommandByName(CommandId::ClearCel);
|
||||
break;
|
||||
case DocumentRange::kFrames:
|
||||
cmd = CommandsModule::instance()->getCommandByName(CommandId::RemoveFrame);
|
||||
break;
|
||||
case DocumentRange::kLayers:
|
||||
cmd = CommandsModule::instance()->getCommandByName(CommandId::RemoveLayer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd) {
|
||||
ctx->executeCommand(cmd);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Timeline::onCancel(Context* ctx)
|
||||
{
|
||||
m_range.disableRange();
|
||||
clearClipboardRange();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/ui/ani_controls.h"
|
||||
#include "app/ui/editor/editor_observer.h"
|
||||
#include "app/ui/input_chain_element.h"
|
||||
#include "base/connection.h"
|
||||
#include "doc/document_observer.h"
|
||||
#include "doc/documents_observer.h"
|
||||
@ -53,7 +54,8 @@ namespace app {
|
||||
class Timeline : public ui::Widget
|
||||
, public doc::DocumentsObserver
|
||||
, public doc::DocumentObserver
|
||||
, public app::EditorObserver {
|
||||
, public app::EditorObserver
|
||||
, public app::InputChainElement {
|
||||
public:
|
||||
typedef DocumentRange Range;
|
||||
|
||||
@ -119,6 +121,18 @@ namespace app {
|
||||
void onAfterLayerChanged(Editor* editor) override;
|
||||
void onDestroyEditor(Editor* editor) override;
|
||||
|
||||
// InputChainElement impl
|
||||
void onNewInputPriority(InputChainElement* element) override;
|
||||
bool onCanCut(Context* ctx) override;
|
||||
bool onCanCopy(Context* ctx) override;
|
||||
bool onCanPaste(Context* ctx) override;
|
||||
bool onCanClear(Context* ctx) override;
|
||||
bool onCut(Context* ctx) override;
|
||||
bool onCopy(Context* ctx) override;
|
||||
bool onPaste(Context* ctx) override;
|
||||
bool onClear(Context* ctx) override;
|
||||
void onCancel(Context* ctx) override;
|
||||
|
||||
private:
|
||||
struct Hit {
|
||||
int part;
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "app/ui/workspace.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui/workspace_tabs.h"
|
||||
#include "app/ui/workspace_view.h"
|
||||
@ -298,4 +300,100 @@ WorkspaceTabs* Workspace::getTabsAt(const gfx::Point& pos)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Workspace::onNewInputPriority(InputChainElement* newElement)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
activeElement->onNewInputPriority(newElement);
|
||||
}
|
||||
|
||||
bool Workspace::onCanCut(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onCanCut(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Workspace::onCanCopy(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onCanCopy(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Workspace::onCanPaste(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onCanPaste(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Workspace::onCanClear(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onCanClear(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Workspace::onCut(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onCut(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Workspace::onCopy(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onCopy(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Workspace::onPaste(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onPaste(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Workspace::onClear(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
return activeElement->onClear(ctx);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void Workspace::onCancel(Context* ctx)
|
||||
{
|
||||
WorkspaceView* view = activeView();
|
||||
InputChainElement* activeElement = (view ? view->onGetInputChainElement(): nullptr);
|
||||
if (activeElement)
|
||||
activeElement->onCancel(ctx);
|
||||
}
|
||||
|
||||
} // namespace app
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define APP_UI_WORKSPACE_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/ui/input_chain_element.h"
|
||||
#include "app/ui/tabs.h"
|
||||
#include "app/ui/workspace_panel.h"
|
||||
#include "base/signal.h"
|
||||
@ -17,7 +18,8 @@
|
||||
namespace app {
|
||||
class WorkspaceTabs;
|
||||
|
||||
class Workspace : public ui::Widget {
|
||||
class Workspace : public ui::Widget
|
||||
, public app::InputChainElement {
|
||||
public:
|
||||
typedef WorkspaceViews::iterator iterator;
|
||||
|
||||
@ -58,6 +60,18 @@ namespace app {
|
||||
// Returns true if the view was docked inside the workspace.
|
||||
DropViewAtResult dropViewAt(const gfx::Point& pos, WorkspaceView* view, bool clone);
|
||||
|
||||
// InputChainElement impl
|
||||
void onNewInputPriority(InputChainElement* element) override;
|
||||
bool onCanCut(Context* ctx) override;
|
||||
bool onCanCopy(Context* ctx) override;
|
||||
bool onCanPaste(Context* ctx) override;
|
||||
bool onCanClear(Context* ctx) override;
|
||||
bool onCut(Context* ctx) override;
|
||||
bool onCopy(Context* ctx) override;
|
||||
bool onPaste(Context* ctx) override;
|
||||
bool onClear(Context* ctx) override;
|
||||
void onCancel(Context* ctx) override;
|
||||
|
||||
Signal0<void> ActiveViewChanged;
|
||||
|
||||
protected:
|
||||
|
@ -14,6 +14,7 @@ namespace ui {
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class InputChainElement;
|
||||
class Workspace;
|
||||
|
||||
class WorkspaceView {
|
||||
@ -39,6 +40,8 @@ namespace app {
|
||||
virtual bool onCloseView(Workspace* workspace) = 0;
|
||||
|
||||
virtual void onTabPopup(Workspace* workspace) = 0;
|
||||
|
||||
virtual InputChainElement* onGetInputChainElement() { return nullptr; }
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "app/ui/color_bar.h"
|
||||
#include "app/ui/document_view.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/input_chain.h"
|
||||
#include "app/ui/main_window.h"
|
||||
#include "app/ui/preview_editor.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
@ -76,13 +77,17 @@ DocumentView* UIContext::activeView() const
|
||||
|
||||
void UIContext::setActiveView(DocumentView* docView)
|
||||
{
|
||||
MainWindow* mainWin = App::instance()->getMainWindow();
|
||||
|
||||
// Prioritize workspace for user input.
|
||||
App::instance()->inputChain().prioritize(mainWin->getWorkspace());
|
||||
|
||||
// Do nothing cases: 1) the view is already selected, or 2) the view
|
||||
// is the a preview.
|
||||
if (m_lastSelectedView == docView ||
|
||||
(docView && docView->isPreview()))
|
||||
return;
|
||||
|
||||
MainWindow* mainWin = App::instance()->getMainWindow();
|
||||
if (docView) {
|
||||
mainWin->getTabsBar()->selectTab(docView);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user