|
Carlos Lopez |
a09598 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
a09598 |
/*! \file action_system.cpp
|
|
Carlos Lopez |
a09598 |
** \brief Template File
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** $Id$
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** \legal
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is free software; you can redistribute it and/or
|
|
Carlos Lopez |
a09598 |
** modify it under the terms of the GNU General Public License as
|
|
Carlos Lopez |
a09598 |
** published by the Free Software Foundation; either version 2 of
|
|
Carlos Lopez |
a09598 |
** the License, or (at your option) any later version.
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is distributed in the hope that it will be useful,
|
|
Carlos Lopez |
a09598 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Carlos Lopez |
a09598 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Carlos Lopez |
a09598 |
** General Public License for more details.
|
|
Carlos Lopez |
a09598 |
** \endlegal
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
/* ========================================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === H E A D E R S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef USING_PCH
|
|
Carlos Lopez |
a09598 |
# include "pch.h"
|
|
Carlos Lopez |
a09598 |
#else
|
|
Carlos Lopez |
a09598 |
#ifdef HAVE_CONFIG_H
|
|
Carlos Lopez |
a09598 |
# include <config.h></config.h>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
bw |
94d8a6 |
#include <synfig general.h=""></synfig>
|
|
bw |
94d8a6 |
|
|
Carlos Lopez |
a09598 |
#include "action_system.h"
|
|
Carlos Lopez |
a09598 |
#include "instance.h"
|
|
Carlos Lopez |
a09598 |
#include "canvasinterface.h"
|
|
Carlos Lopez |
a09598 |
|
|
|
abdbf2 |
#include <synfigapp localization.h=""></synfigapp>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === U S I N G =========================================================== */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
using namespace synfig;
|
|
|
65f7fd |
using namespace synfigapp;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M A C R O S ========================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === P R O C E D U R E S ================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
namespace {
|
|
|
65f7fd |
class Lock {
|
|
|
65f7fd |
private:
|
|
|
65f7fd |
int &counter;
|
|
|
65f7fd |
public:
|
|
|
65f7fd |
Lock(int &counter): counter(counter) { ++counter; }
|
|
|
65f7fd |
~Lock() { --counter; }
|
|
|
65f7fd |
};
|
|
|
65f7fd |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Action::System::System():
|
|
Carlos Lopez |
a09598 |
action_count_(0)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
unset_ui_interface();
|
|
Carlos Lopez |
a09598 |
clear_redo_stack_on_new_action_=false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Action::System::~System()
|
|
|
65f7fd |
{ }
|
|
|
65f7fd |
|
|
|
65f7fd |
void
|
|
|
65f7fd |
Action::System::request_redraw(etl::handle<canvasinterface> x)</canvasinterface>
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
if (!x) return;
|
|
|
65f7fd |
if (!group_stack_.empty())
|
|
|
65f7fd |
{ group_stack_.front()->request_redraw(x); return; }
|
|
|
65f7fd |
x->signal_dirty_preview()();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
Action::System::perform_action(etl::handle<action::base> action)</action::base>
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
assert(action);
|
|
Nikita Kitaev |
dc5e35 |
if (getenv("SYNFIG_DEBUG_ACTIONS"))
|
|
Nikita Kitaev |
dc5e35 |
synfig::info("%s:%d perform_action: '%s'", __FILE__, __LINE__, action->get_name().c_str());
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<uiinterface> uim = get_ui_interface();</uiinterface>
|
|
|
65f7fd |
if (!action->is_ready()) {
|
|
Carlos Lopez |
a09598 |
uim->error(action->get_local_name()+": "+_("Action is not ready."));
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
most_recent_action_name_ = action->get_name();
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
static int inuse = 0;
|
|
|
65f7fd |
if (inuse) return false;
|
|
|
65f7fd |
Lock lock(inuse);
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
Action::CanvasSpecific *canvas_specific = dynamic_cast<action::canvasspecific*>(action.get());</action::canvasspecific*>
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (canvas_specific && canvas_specific->get_canvas())
|
|
|
65f7fd |
uim = static_cast<instance*>(this)->find_canvas_interface(canvas_specific->get_canvas())->get_ui_interface();</instance*>
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If we cannot undo this action, make sure
|
|
Carlos Lopez |
a09598 |
// that the user knows this.
|
|
|
65f7fd |
etl::handle<action::undoable> undoable_action = etl::handle<action::undoable>::cast_dynamic(action);</action::undoable></action::undoable>
|
|
|
65f7fd |
assert(!undoable_action || undoable_action->is_active());
|
|
|
65f7fd |
if (!undoable_action) {
|
|
|
65f7fd |
String message = etl::strprintf(_("Do you want to do action \"%s\"?"), action->get_local_name().c_str());
|
|
|
65f7fd |
String details = _("This action cannot be undone.");
|
|
|
65f7fd |
UIInterface::Response response = uim->confirmation(
|
|
Yu Chen |
4ca051 |
message,
|
|
Yu Chen |
4ca051 |
details,
|
|
Yu Chen |
4ca051 |
_("Cancel"),
|
|
Yu Chen |
4ca051 |
_("Continue"),
|
|
|
65f7fd |
UIInterface::RESPONSE_CANCEL );
|
|
|
65f7fd |
if (response == UIInterface::RESPONSE_CANCEL)
|
|
Carlos Lopez |
a09598 |
return false;
|
|
|
65f7fd |
// Because this action cannot be undone,
|
|
|
65f7fd |
// we need to clear the undo stack
|
|
|
65f7fd |
clear_undo_stack();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Perform the action
|
|
Carlos Lopez |
a09598 |
try { action->perform(); }
|
|
|
b1afd8 |
catch (const Action::Error& err) {
|
|
Carlos Lopez |
a09598 |
uim->task(action->get_local_name()+' '+_("Failed"));
|
|
|
65f7fd |
if (err.get_type() != Action::Error::TYPE_UNABLE) {
|
|
|
65f7fd |
if (err.get_desc().empty())
|
|
|
65f7fd |
uim->error(action->get_local_name() + ": " + etl::strprintf("%d", err.get_type()));
|
|
Carlos Lopez |
a09598 |
else
|
|
|
65f7fd |
uim->error(action->get_local_name() + ": " + err.get_desc());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
// If action failed for whatever reason, just return false and do
|
|
Carlos Lopez |
a09598 |
// not add the action onto the list
|
|
Carlos Lopez |
a09598 |
return false;
|
|
|
b1afd8 |
} catch (std::exception& err) {
|
|
|
4a958f |
uim->task(action->get_local_name() + ' ' + _("Failed"));
|
|
|
4a958f |
uim->error(action->get_local_name() + ": " + err.what());
|
|
Carlos Lopez |
a09598 |
// If action failed for whatever reason, just return false and do
|
|
Carlos Lopez |
a09598 |
// not add the action onto the list
|
|
Carlos Lopez |
a09598 |
return false;
|
|
|
65f7fd |
} catch(...) {
|
|
|
4a958f |
uim->task(action->get_local_name() + ' ' + _("Failed"));
|
|
Carlos Lopez |
a09598 |
// If action failed for whatever reason, just return false and do
|
|
Carlos Lopez |
a09598 |
// not add the action onto the list
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Clear the redo stack
|
|
|
65f7fd |
if (clear_redo_stack_on_new_action_)
|
|
Carlos Lopez |
a09598 |
clear_redo_stack();
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (!group_stack_.empty())
|
|
Carlos Lopez |
a09598 |
group_stack_.front()->inc_depth();
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
inc_action_count();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Push this action onto the action list if we can undo it
|
|
|
65f7fd |
if (undoable_action) {
|
|
Carlos Lopez |
a09598 |
// If necessary, signal the change in status of undo
|
|
Carlos Lopez |
a09598 |
if(undo_action_stack_.empty()) signal_undo_status_(true);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Add it to the list
|
|
Carlos Lopez |
a09598 |
undo_action_stack_.push_front(undoable_action);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Signal that a new action has been added
|
|
Carlos Lopez |
a09598 |
if(group_stack_.empty())
|
|
Carlos Lopez |
a09598 |
signal_new_action()(undoable_action);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
uim->task(action->get_local_name()+' '+_("Successful"));
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If the action has "dirtied" the preview, signal it.
|
|
|
65f7fd |
if (canvas_specific && canvas_specific->is_dirty())
|
|
|
65f7fd |
request_redraw(canvas_specific->get_canvas_interface());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
synfigapp::Action::System::undo_(etl::handle<uiinterface> uim)</uiinterface>
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
etl::handle<action::undoable> action = undo_action_stack().front();</action::undoable>
|
|
|
65f7fd |
most_recent_action_name_ = action->get_name();
|
|
|
65f7fd |
|
|
|
65f7fd |
try { if (action->is_active()) action->undo(); }
|
|
|
65f7fd |
catch (Action::Error &err) {
|
|
|
65f7fd |
if(err.get_type() != Action::Error::TYPE_UNABLE) {
|
|
Carlos Lopez |
a09598 |
if(err.get_desc().empty())
|
|
|
65f7fd |
uim->error(action->get_local_name() + _(" (Undo): ") + etl::strprintf("%d",err.get_type()));
|
|
Carlos Lopez |
a09598 |
else
|
|
|
65f7fd |
uim->error(action->get_local_name() + _(" (Undo): ") + err.get_desc());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
return false;
|
|
|
65f7fd |
} catch (std::runtime_error &x) {
|
|
Carlos Lopez |
a09598 |
uim->error(x.what());
|
|
Carlos Lopez |
a09598 |
return false;
|
|
|
65f7fd |
} catch (...) {
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
dec_action_count();
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (redo_action_stack_.empty()) signal_redo_status()(true);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
redo_action_stack_.push_front(undo_action_stack_.front());
|
|
Carlos Lopez |
a09598 |
undo_action_stack_.pop_front();
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (undo_action_stack_.empty()) signal_undo_status()(false);
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (!group_stack_.empty())
|
|
Carlos Lopez |
a09598 |
group_stack_.front()->dec_depth();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
signal_undo_();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
synfigapp::Action::System::undo()
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
static int inuse = 0;
|
|
|
65f7fd |
if (inuse) return false;
|
|
|
65f7fd |
Lock lock(inuse);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If there is nothing on the action list, there is nothing to undo
|
|
|
65f7fd |
if (undo_action_stack().empty())
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<action::undoable> action = undo_action_stack().front();</action::undoable>
|
|
|
65f7fd |
Action::CanvasSpecific *canvas_specific = dynamic_cast<action::canvasspecific*>(action.get());</action::canvasspecific*>
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<uiinterface> uim = get_ui_interface();</uiinterface>
|
|
|
65f7fd |
if (canvas_specific && canvas_specific->get_canvas())
|
|
|
65f7fd |
uim = static_cast<instance*>(this)->find_canvas_interface(canvas_specific->get_canvas())->get_ui_interface();</instance*>
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (!undo_(uim)) {
|
|
Carlos Lopez |
a09598 |
uim->error(undo_action_stack_.front()->get_local_name()+": "+_("Failed to undo."));
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If the action has "dirtied" the preview, signal it.
|
|
|
65f7fd |
if(action->is_active() && canvas_specific && canvas_specific->is_dirty())
|
|
|
65f7fd |
request_redraw(canvas_specific->get_canvas_interface());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
Action::System::redo_(etl::handle<uiinterface> uim)</uiinterface>
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
etl::handle<action::undoable> action = redo_action_stack().front();</action::undoable>
|
|
|
65f7fd |
most_recent_action_name_ = action->get_name();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
try { if(action->is_active()) action->perform(); }
|
|
|
b1afd8 |
catch (const Action::Error& err) {
|
|
|
65f7fd |
if (err.get_type() != Action::Error::TYPE_UNABLE) {
|
|
Carlos Lopez |
a09598 |
if(err.get_desc().empty())
|
|
|
65f7fd |
uim->error(action->get_local_name() + _(" (Redo): ") + etl::strprintf("%d", err.get_type()));
|
|
Carlos Lopez |
a09598 |
else
|
|
|
65f7fd |
uim->error(action->get_local_name() + _(" (Redo): ") + err.get_desc());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
return false;
|
|
|
b1afd8 |
} catch (const std::runtime_error &x) {
|
|
Carlos Lopez |
a09598 |
uim->error(x.what());
|
|
Carlos Lopez |
a09598 |
return false;
|
|
|
65f7fd |
} catch(...) {
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
inc_action_count();
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (undo_action_stack_.empty()) signal_undo_status()(true);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
undo_action_stack_.push_front(redo_action_stack_.front());
|
|
Carlos Lopez |
a09598 |
redo_action_stack_.pop_front();
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (redo_action_stack_.empty()) signal_redo_status()(false);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
if(!group_stack_.empty())
|
|
Carlos Lopez |
a09598 |
group_stack_.front()->inc_depth();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
signal_redo_();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
Action::System::redo()
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
static int inuse = 0;
|
|
|
65f7fd |
if (inuse) return false;
|
|
|
65f7fd |
Lock lock(inuse);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If there is nothing on the action list, there is nothing to undo
|
|
|
65f7fd |
if (redo_action_stack_.empty())
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<action::undoable> action = redo_action_stack().front();</action::undoable>
|
|
|
65f7fd |
Action::CanvasSpecific *canvas_specific = dynamic_cast<action::canvasspecific*>(action.get());</action::canvasspecific*>
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<uiinterface> uim = get_ui_interface();</uiinterface>
|
|
|
65f7fd |
if (canvas_specific && canvas_specific->get_canvas())
|
|
|
65f7fd |
uim = static_cast<instance*>(this)->find_canvas_interface(canvas_specific->get_canvas())->get_ui_interface();</instance*>
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (!redo_(uim)) {
|
|
Carlos Lopez |
a09598 |
uim->error(redo_action_stack_.front()->get_local_name()+": "+_("Failed to redo."));
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If the action has "dirtied" the preview, signal it.
|
|
|
65f7fd |
if (action->is_active() && canvas_specific && canvas_specific->is_dirty())
|
|
|
65f7fd |
request_redraw(canvas_specific->get_canvas_interface());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
|
65f7fd |
Action::System::inc_action_count() const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
action_count_++;
|
|
|
65f7fd |
if (action_count_ == 1)
|
|
Carlos Lopez |
a09598 |
signal_unsaved_status_changed_(true);
|
|
|
65f7fd |
if (!action_count_)
|
|
Carlos Lopez |
a09598 |
signal_unsaved_status_changed_(false);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
|
65f7fd |
Action::System::dec_action_count() const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
action_count_--;
|
|
Carlos Lopez |
a09598 |
if(action_count_==-1)
|
|
Carlos Lopez |
a09598 |
signal_unsaved_status_changed_(true);
|
|
Carlos Lopez |
a09598 |
if(!action_count_)
|
|
Carlos Lopez |
a09598 |
signal_unsaved_status_changed_(false);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
|
65f7fd |
Action::System::reset_action_count() const
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
if (!action_count_)
|
|
Carlos Lopez |
a09598 |
return;
|
|
|
65f7fd |
action_count_ = 0;
|
|
Carlos Lopez |
a09598 |
signal_unsaved_status_changed_(false);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
Action::System::clear_undo_stack()
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
if (undo_action_stack_.empty()) return;
|
|
Carlos Lopez |
a09598 |
undo_action_stack_.clear();
|
|
Carlos Lopez |
a09598 |
signal_undo_status_(false);
|
|
Carlos Lopez |
a09598 |
signal_undo_stack_cleared_();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
Action::System::clear_redo_stack()
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
if (redo_action_stack_.empty()) return;
|
|
Carlos Lopez |
a09598 |
redo_action_stack_.clear();
|
|
Carlos Lopez |
a09598 |
signal_redo_status_(false);
|
|
Carlos Lopez |
a09598 |
signal_redo_stack_cleared_();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
bool
|
|
Carlos Lopez |
a09598 |
Action::System::set_action_status(etl::handle<action::undoable> action, bool x)</action::undoable>
|
|
Carlos Lopez |
a09598 |
{
|
|
|
65f7fd |
if (action->is_active() == x)
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<action::undoable> cur_pos = undo_action_stack_.front();</action::undoable>
|
|
|
65f7fd |
Action::CanvasSpecific *canvas_specific = dynamic_cast<action::canvasspecific*>(action.get());</action::canvasspecific*>
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<uiinterface> uim = new ConfidentUIInterface();</uiinterface>
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
Stack::iterator iter = std::find(undo_action_stack_.begin(), undo_action_stack_.end(), action);
|
|
|
65f7fd |
if (iter != undo_action_stack_.end()) {
|
|
|
65f7fd |
while(undo_action_stack_.front() != action)
|
|
|
65f7fd |
if (!undo_(uim)) return false;
|
|
|
65f7fd |
if (!undo_(uim)) return false;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
action->set_active(x);
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
bool success = redo_(get_ui_interface());
|
|
|
65f7fd |
if (success)
|
|
Carlos Lopez |
a09598 |
signal_action_status_changed_(action);
|
|
Carlos Lopez |
a09598 |
else
|
|
Carlos Lopez |
a09598 |
action->set_active(!x);
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
while(undo_action_stack_.front() != cur_pos)
|
|
|
65f7fd |
if (!redo_(uim)) {
|
|
Carlos Lopez |
a09598 |
redo_action_stack_.front()->set_active(false);
|
|
Carlos Lopez |
a09598 |
signal_action_status_changed_(redo_action_stack_.front());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (success && canvas_specific && canvas_specific->is_dirty())
|
|
|
65f7fd |
request_redraw(canvas_specific->get_canvas_interface());
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
iter = std::find(redo_action_stack_.begin(), redo_action_stack_.end(), action);
|
|
|
65f7fd |
if (iter!=redo_action_stack_.end()) {
|
|
Carlos Lopez |
a09598 |
action->set_active(x);
|
|
Carlos Lopez |
a09598 |
signal_action_status_changed_(action);
|
|
|
65f7fd |
if (canvas_specific && canvas_specific->is_dirty())
|
|
|
65f7fd |
request_redraw(canvas_specific->get_canvas_interface());
|
|
Carlos Lopez |
a09598 |
return true;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
return false;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Action::PassiveGrouper::PassiveGrouper(etl::loose_handle<system> instance_,synfig::String name_):</system>
|
|
Carlos Lopez |
a09598 |
instance_(instance_),
|
|
Carlos Lopez |
a09598 |
name_(name_),
|
|
|
0bd937 |
depth_(0),
|
|
|
0bd937 |
finished_(false)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// Add this group onto the group stack
|
|
Carlos Lopez |
a09598 |
instance_->group_stack_.push_front(this);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
Action::PassiveGrouper::request_redraw(etl::handle<canvasinterface> x)</canvasinterface>
|
|
|
65f7fd |
{ if (x) redraw_set_.insert(x); }
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
Action::PassiveGrouper::~PassiveGrouper()
|
|
|
0bd937 |
{ if (!finished_) finish(); }
|
|
|
0bd937 |
|
|
|
0bd937 |
etl::handle<action::group></action::group>
|
|
|
0bd937 |
Action::PassiveGrouper::finish()
|
|
Carlos Lopez |
a09598 |
{
|
|
|
0bd937 |
assert(!finished_);
|
|
|
0bd937 |
if (finished_) return etl::handle<action::group>();</action::group>
|
|
|
0bd937 |
finished_ = true;
|
|
|
0bd937 |
|
|
Carlos Lopez |
a09598 |
// Remove this group from the group stack
|
|
|
65f7fd |
assert(instance_->group_stack_.front() == this);
|
|
Carlos Lopez |
a09598 |
instance_->group_stack_.pop_front();
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
etl::handle<action::group> group;</action::group>
|
|
|
65f7fd |
if (depth_ == 1) {
|
|
|
65f7fd |
etl::handle<action::undoable> action = instance_->undo_action_stack_.front();</action::undoable>
|
|
|
65f7fd |
group = etl::handle<action::group>::cast_dynamic(action);</action::group>
|
|
|
65f7fd |
if (group) {
|
|
Carlos Lopez |
a09598 |
// If the only action inside of us is a group,
|
|
Carlos Lopez |
a09598 |
// then we should rename the group to our name.
|
|
Carlos Lopez |
a09598 |
group->set_name(name_);
|
|
|
65f7fd |
} else
|
|
|
65f7fd |
if (Action::CanvasSpecific* canvas_specific = dynamic_cast<action::canvasspecific*>(action.get()))</action::canvasspecific*>
|
|
|
65f7fd |
if (canvas_specific->is_dirty() && canvas_specific->get_canvas_interface())
|
|
|
65f7fd |
if (instance_->group_stack_.empty())
|
|
Carlos Lopez |
a09598 |
request_redraw(canvas_specific->get_canvas_interface());
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (instance_->group_stack_.empty()) {
|
|
Carlos Lopez |
a09598 |
instance_->inc_action_count();
|
|
Carlos Lopez |
a09598 |
instance_->signal_new_action()(instance_->undo_action_stack_.front());
|
|
|
65f7fd |
} else
|
|
Carlos Lopez |
a09598 |
instance_->group_stack_.front()->inc_depth();
|
|
|
65f7fd |
} else
|
|
|
65f7fd |
if (depth_ > 1) {
|
|
|
65f7fd |
group = new Action::Group(name_);
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
for(int i=0; i < depth_; i++) {
|
|
|
65f7fd |
etl::handle<action::undoable> action = instance_->undo_action_stack_.front();</action::undoable>
|
|
|
65f7fd |
|
|
|
65f7fd |
if (Action::CanvasSpecific* canvas_specific = dynamic_cast<action::canvasspecific*>(action.get()))</action::canvasspecific*>
|
|
|
65f7fd |
if (canvas_specific->is_dirty()) {
|
|
|
65f7fd |
group->set_dirty(true);
|
|
|
65f7fd |
group->set_canvas(canvas_specific->get_canvas());
|
|
|
65f7fd |
group->set_canvas_interface(canvas_specific->get_canvas_interface());
|
|
|
65f7fd |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Copy the action from the undo stack to the group
|
|
Carlos Lopez |
a09598 |
group->add_action_front(action);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Remove the action from the undo stack
|
|
Carlos Lopez |
a09598 |
instance_->undo_action_stack_.pop_front();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Push the group onto the stack
|
|
Carlos Lopez |
a09598 |
instance_->undo_action_stack_.push_front(group);
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if(group->is_dirty())
|
|
Carlos Lopez |
a09598 |
request_redraw(group->get_canvas_interface());
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if(instance_->group_stack_.empty()) {
|
|
Carlos Lopez |
a09598 |
instance_->inc_action_count();
|
|
Carlos Lopez |
a09598 |
instance_->signal_new_action()(instance_->undo_action_stack_.front());
|
|
|
65f7fd |
} else
|
|
Carlos Lopez |
a09598 |
instance_->group_stack_.front()->inc_depth();
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
// redraw request
|
|
|
65f7fd |
for(RedrawSet::const_iterator i = redraw_set_.begin(); i != redraw_set_.end(); ++i)
|
|
|
65f7fd |
instance_->request_redraw(*i);
|
|
|
65f7fd |
redraw_set_.clear();
|
|
|
0bd937 |
|
|
|
0bd937 |
return group;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
void
|
|
Carlos Lopez |
a09598 |
Action::PassiveGrouper::cancel()
|
|
Carlos Lopez |
a09598 |
{
|
|
|
0bd937 |
assert(!finished_);
|
|
|
0bd937 |
if (finished_) return;
|
|
|
0bd937 |
|
|
Carlos Lopez |
a09598 |
// Cancel any groupers that may be on top of us first
|
|
Carlos Lopez |
a09598 |
//while(instance_->group_stack_.front()!=this)
|
|
Carlos Lopez |
a09598 |
// instance_->group_stack_.front()->cancel();
|
|
Carlos Lopez |
a09598 |
synfig::warning("Cancel depth: %d",depth_);
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
bool success = true;
|
|
|
65f7fd |
while(success && depth_)
|
|
|
65f7fd |
if (!instance_->undo())
|
|
|
65f7fd |
success = false;
|
|
Carlos Lopez |
a09598 |
|
|
|
65f7fd |
if (success)
|
|
|
65f7fd |
redraw_set_.clear();
|
|
Carlos Lopez |
a09598 |
else
|
|
|
65f7fd |
instance_->get_ui_interface()->error(_("State restore failure"));
|
|
Carlos Lopez |
a09598 |
}
|