Example #1
0
bool
Action::System::perform_action(etl::handle<Action::Base> action)
{
	if (getenv("SYNFIG_DEBUG_ACTIONS"))
		synfig::info("%s:%d perform_action: '%s'", __FILE__, __LINE__, action->get_name().c_str());

	handle<UIInterface> uim(get_ui_interface());

	assert(action);

	if(!action->is_ready())
	{
		uim->error(action->get_local_name()+": "+_("Action is not ready."));
		return false;
	}

	most_recent_action_name_=action->get_name();

	static bool inuse=false;

	if(inuse) return false;

	inuse=true;
	try {

	assert(action);

	Action::CanvasSpecific* canvas_specific(dynamic_cast<Action::CanvasSpecific*>(action.get()));

	if(canvas_specific && canvas_specific->get_canvas())
	{
		handle<CanvasInterface> canvas_interface=static_cast<Instance*>(this)->find_canvas_interface(canvas_specific->get_canvas());
		assert(canvas_interface);
		uim=canvas_interface->get_ui_interface();
	}

	handle<Action::Undoable> undoable_action=handle<Action::Undoable>::cast_dynamic(action);

	// If we cannot undo this action, make sure
	// that the user knows this.
	if(!undoable_action)
	{
		if(uim->yes_no(
			action->get_local_name(),
			_("This action cannot be undone! Are you sure you want to continue?"),
			UIInterface::RESPONSE_NO
			) == UIInterface::RESPONSE_NO
		)
			return false;
		else
		{
			// Because this action cannot be undone,
			// we need to clear the undo stack
			clear_undo_stack();
		}
	}
	else
		assert(undoable_action->is_active());

	// Perform the action
	try { action->perform(); }
	catch(Action::Error err)
	{
		uim->task(action->get_local_name()+' '+_("Failed"));
		inuse=false;

		if(err.get_type()!=Action::Error::TYPE_UNABLE)
		{
			if(err.get_desc().empty())
				uim->error(action->get_local_name()+": "+strprintf("%d",err.get_type()));
			else
				uim->error(action->get_local_name()+": "+err.get_desc());
		}

		// If action failed for whatever reason, just return false and do
		// not add the action onto the list
		return false;
	}
	catch(std::exception err)
	{
		uim->task(action->get_local_name()+' '+_("Failed"));
		inuse=false;

		uim->error(action->get_local_name()+": "+err.what());

		// If action failed for whatever reason, just return false and do
		// not add the action onto the list
		return false;
	}
	catch(...)
	{
		uim->task(action->get_local_name()+' '+_("Failed"));
		inuse=false;

		// If action failed for whatever reason, just return false and do
		// not add the action onto the list
		return false;
	}

	// Clear the redo stack
	if(clear_redo_stack_on_new_action_)
		clear_redo_stack();

	if(!group_stack_.empty())
		group_stack_.front()->inc_depth();
	else
		inc_action_count();

	// Push this action onto the action list if we can undo it
	if(undoable_action)
	{
		// If necessary, signal the change in status of undo
		if(undo_action_stack_.empty()) signal_undo_status_(true);

		// Add it to the list
		undo_action_stack_.push_front(undoable_action);

		// Signal that a new action has been added
		if(group_stack_.empty())
			signal_new_action()(undoable_action);
	}

	inuse=false;

	uim->task(action->get_local_name()+' '+_("Successful"));

	// If the action has "dirtied" the preview, signal it.
	if(0)if(canvas_specific && canvas_specific->is_dirty())
	{
		Canvas::Handle canvas=canvas_specific->get_canvas();
		if(!group_stack_.empty())
			group_stack_.front()->request_redraw(canvas_specific->get_canvas_interface());
		else
		{
			handle<CanvasInterface> canvas_interface=static_cast<Instance*>(this)->find_canvas_interface(canvas);
			assert(canvas_interface);
			//canvas_interface->signal_dirty_preview()();
		}
	}

	}catch(...) { inuse=false; throw; }

	return true;
}