X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-studio%2Fsrc%2Fgtkmm%2Fdock_history.cpp;fp=synfig-studio%2Fsrc%2Fgtkmm%2Fdock_history.cpp;h=c8fc3da8bd49ef673ff6cdc802a7232620047e80;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=0000000000000000000000000000000000000000;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/synfig-studio/src/gtkmm/dock_history.cpp b/synfig-studio/src/gtkmm/dock_history.cpp new file mode 100644 index 0000000..c8fc3da --- /dev/null +++ b/synfig-studio/src/gtkmm/dock_history.cpp @@ -0,0 +1,468 @@ +/* === S Y N F I G ========================================================= */ +/*! \file dock_history.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "dock_history.h" +#include "app.h" + + + +#include +#include +#include "instance.h" +#include +#include +#include +#include +#include "historytreestore.h" + +#include "general.h" + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; +using namespace studio; + +/* === M A C R O S ========================================================= */ +#define COLUMNID_JUMP (787584) +#define ColumnID int + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +Dock_History::Dock_History(): + Dock_CanvasSpecific("history",_("History"),Gtk::StockID("gtk-undo")), + action_group(Gtk::ActionGroup::create()) +{ + App::signal_instance_deleted().connect(sigc::mem_fun(*this,&studio::Dock_History::delete_instance)); + App::signal_instance_selected().connect(sigc::mem_fun(*this,&studio::Dock_History::set_selected_instance_signal)); + + action_group->add(Gtk::Action::create( + "clear-undo", + Gtk::StockID("synfig-clear_undo"), + _("Clear Undo Stack"), + _("Clear the undo stack") + ), + sigc::mem_fun( + *this, + &Dock_History::clear_undo + ) + ); + action_group->add(Gtk::Action::create( + "clear-redo", + Gtk::StockID("synfig-clear_redo"), + _("Clear Redo Stack"), + _("Clear the redo stack") + ), + sigc::mem_fun( + *this, + &Dock_History::clear_redo + ) + ); + action_group->add(Gtk::Action::create( + "clear-undo-and-redo", + Gtk::Stock::CLEAR, + _("Clear Undo and Redo Stacks"), + _("Clear the undo and redo stacks") + ), + sigc::mem_fun( + *this, + &Dock_History::clear_undo_and_redo + ) + ); + action_group->add(Gtk::Action::create( + "undo", + Gtk::StockID("gtk-undo"), + _("Undo"), + _("Undo the previous action") + ), + sigc::ptr_fun(studio::App::undo) + ); + action_group->add(Gtk::Action::create( + "redo", + Gtk::StockID("gtk-redo"), + _("Redo"), + _("Redo the previously undone action") + ), + sigc::ptr_fun(studio::App::redo) + ); + + action_group->add( Gtk::Action::create("toolbar-history", _("History")) ); + App::ui_manager()->insert_action_group(action_group); + + Glib::ustring ui_info = + "" + " " + " " + " " + " " + " " + " " + " " + "" + ; + + App::ui_manager()->add_ui_from_string(ui_info); + + action_group->set_sensitive(false); + + set_toolbar(*dynamic_cast(App::ui_manager()->get_widget("/toolbar-history"))); + add(*create_action_tree()); + + /* + add_button( + Gtk::StockID("synfig-clear_undo"), + _("Clear the UNDO Stack") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &Dock_History::clear_undo + ) + ); + add_button( + Gtk::StockID("synfig-clear_redo"), + _("Clear the REDO Stack") + )->signal_clicked().connect( + sigc::mem_fun( + *this, + &Dock_History::clear_redo + ) + ); + */ +} + +Dock_History::~Dock_History() +{ +} + +void +Dock_History::init_instance_vfunc(etl::loose_handle instance) +{ + instance->signal_undo_redo_status_changed().connect( + sigc::mem_fun(*this,&Dock_History::update_undo_redo) + ); +} + +Gtk::Widget* +Dock_History::create_action_tree() +{ + studio::HistoryTreeStore::Model history_tree_model; + action_tree=manage(new class Gtk::TreeView()); + { + Gtk::TreeView::Column* column = Gtk::manage( new Gtk::TreeView::Column("") ); + + Gtk::CellRendererToggle* toggle_cr = Gtk::manage( new Gtk::CellRendererToggle() ); + toggle_cr->signal_toggled().connect(sigc::mem_fun(*this, &studio::Dock_History::on_action_toggle) ); + + column->pack_start(*toggle_cr); //false = don't expand. + column->add_attribute(toggle_cr->property_active(),history_tree_model.is_active); + column->set_resizable(); + column->set_clickable(); + + action_tree->append_column(*column); + } + /*{ + Gtk::TreeView::Column* column = Gtk::manage( new Gtk::TreeView::Column(_("Canvas")) ); + Gtk::CellRendererText *text_cr=Gtk::manage(new Gtk::CellRendererText()); + text_cr->property_foreground()=Glib::ustring("#7f7f7f"); + + column->pack_start(*text_cr); + column->add_attribute(text_cr->property_text(),history_tree_model.canvas_id); + column->add_attribute(text_cr->property_foreground_set(),history_tree_model.is_redo); + + action_tree->append_column(*column); + }*/ + { + Gtk::TreeView::Column* column = Gtk::manage( new Gtk::TreeView::Column(_("Jump")) ); + + Gtk::CellRendererText* cell_renderer_jump=Gtk::manage(new Gtk::CellRendererText()); + column->pack_start(*cell_renderer_jump,true); + + cell_renderer_jump->property_text()=_("(JMP)"); + cell_renderer_jump->property_foreground()="#003a7f"; + + column->set_resizable(); + column->set_clickable(); + + column->set_sort_column(COLUMNID_JUMP); + + action_tree->append_column(*column); + //column->clicked(); + } + { + Gtk::TreeView::Column* column = Gtk::manage( new Gtk::TreeView::Column(_("Action")) ); + + Gtk::CellRendererText *text_cr=Gtk::manage(new Gtk::CellRendererText()); + text_cr->property_foreground()=Glib::ustring("#7f7f7f"); + + + + //column->pack_start(history_tree_model.icon, false); //false = don't expand. + column->pack_start(*text_cr); + column->add_attribute(text_cr->property_text(),history_tree_model.name); + column->add_attribute(text_cr->property_foreground_set(),history_tree_model.is_redo); + + action_tree->append_column(*column); + } + + action_tree->set_enable_search(true); + action_tree->set_search_column(history_tree_model.name); + action_tree->set_search_equal_func(sigc::ptr_fun(&studio::HistoryTreeStore::search_func)); + + action_tree->set_rules_hint(); +// action_tree->signal_row_activated().connect(sigc::mem_fun(*this,&Dock_History::on_row_activate)); + action_tree->signal_event().connect(sigc::mem_fun(*this,&Dock_History::on_action_event)); +// action_tree->add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK); +// action_tree->add_events(Gdk::BUTTON1_MOTION_MASK); + action_tree->show(); + + Gtk::ScrolledWindow *scrolledwindow = manage(new class Gtk::ScrolledWindow()); + scrolledwindow->set_flags(Gtk::CAN_FOCUS); + scrolledwindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + scrolledwindow->add(*action_tree); + scrolledwindow->set_shadow_type(Gtk::SHADOW_ETCHED_IN); + scrolledwindow->show_all(); + +/* { + Gtk::Widget& widget(*action_tree); + Pango::FontDescription font(widget.get_modifier_style()->get_font()); + font.set_size(Pango::SCALE*5); + widget.get_modifier_style()->set_font(font); + widget.modify_font(font); + } +*/ + return scrolledwindow; +} + +void +Dock_History::clear_undo() +{ + if(selected_instance && App::dialog_yes_no(_("Clear History"), + _("You will not be able to undo any changes that you have made!\nAre you sure you want to clear the undo stack?"))) + selected_instance->clear_undo_stack(); +} + +void +Dock_History::clear_redo() +{ + if(selected_instance && App::dialog_yes_no(_("Clear History"), + _("You will not be able to redo any changes that you have made!\nAre you sure you want to clear the redo stack?"))) + selected_instance->clear_redo_stack(); +} + +void +Dock_History::clear_undo_and_redo() +{ + if(selected_instance && App::dialog_yes_no(_("Clear History"), + _("You will not be able to undo or redo any changes that you have made!\nAre you sure you want to clear the undo and redo stacks?"))) + { + selected_instance->clear_undo_stack(); + selected_instance->clear_redo_stack(); + } +} + +void +Dock_History::update_undo_redo() +{ + etl::handle instance=App::get_selected_instance(); + if(instance) + { + action_group->get_action("undo")->set_sensitive(instance->get_undo_status()); + action_group->get_action("clear-undo")->set_sensitive(instance->get_undo_status()); + action_group->get_action("redo")->set_sensitive(instance->get_redo_status()); + action_group->get_action("clear-redo")->set_sensitive(instance->get_redo_status()); + action_group->get_action("clear-undo-and-redo")->set_sensitive(instance->get_undo_status() || instance->get_redo_status()); + } +} + +void +Dock_History::on_undo_tree_changed() +{ + Gtk::TreeModel::Children children(selected_instance->history_tree_store()->children()); + + if (!children.size()) + return; + + studio::HistoryTreeStore::Model model; + + Gtk::TreeModel::Children::iterator iter, prev = children.end(); + for (iter = children.begin(); iter != children.end(); prev = iter++) + if ((*iter)[model.is_redo]) + { + if (prev == children.end()) + action_tree->get_selection()->unselect_all(); + else + { + action_tree->scroll_to_row(Gtk::TreePath(prev), 0.5); + action_tree->get_selection()->select(prev); + } + return; + } + + action_tree->scroll_to_row(Gtk::TreePath(prev), 0.5); + action_tree->get_selection()->select(prev); +} + +void +Dock_History::set_selected_instance_(etl::handle instance) +{ + if(studio::App::shutdown_in_progress) + return; + + if (on_undo_tree_changed_connection) + on_undo_tree_changed_connection.disconnect(); + + selected_instance=instance; + if(instance) + { + on_undo_tree_changed_connection = selected_instance->history_tree_store()->signal_undo_tree_changed().connect( + sigc::mem_fun(*this,&Dock_History::on_undo_tree_changed)); + + action_tree->set_model(instance->history_tree_store()); + action_tree->show(); + update_undo_redo(); + action_group->set_sensitive(true); + } + else + { + action_tree->set_model(Glib::RefPtr< Gtk::TreeModel >()); + action_tree->hide(); + action_group->set_sensitive(false); + } +} + +void +Dock_History::set_selected_instance_signal(etl::handle x) +{ + set_selected_instance(x); +} + +void +Dock_History::set_selected_instance(etl::loose_handle x) +{ + if(studio::App::shutdown_in_progress) + return; + + // if it's already selected, don't select it again + if (x==selected_instance) + return; + + std::list >::iterator iter; + + set_selected_instance_(x); +} + +void +Dock_History::delete_instance(etl::handle instance) +{ + if(studio::App::shutdown_in_progress) + return; + + if(selected_instance==instance) + { + set_selected_instance(0); + } +} + +bool +Dock_History::on_action_event(GdkEvent *event) +{ + studio::HistoryTreeStore::Model model; + switch(event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + { + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn *column; + int cell_x, cell_y; + if(!action_tree->get_path_at_pos( + int(event->button.x),int(event->button.y), // x, y + path, // TreeModel::Path& + column, //TreeViewColumn*& + cell_x,cell_y //int&cell_x,int&cell_y + ) + ) break; + const Gtk::TreeRow row = *(action_tree->get_model()->get_iter(path)); + + //signal_user_click()(event->button.button,row,(ColumnID)column->get_sort_column_id()); + if((ColumnID)column->get_sort_column_id()==COLUMNID_JUMP) + { + etl::handle action(row[model.action]); + try{ + if((bool)row[model.is_undo]) + { + while(get_selected_instance()->undo_action_stack().size() && get_selected_instance()->undo_action_stack().front()!=action) + if(get_selected_instance()->undo()==false) + throw int(); + } + else if((bool)row[model.is_redo]) + { + while(get_selected_instance()->redo_action_stack().size() && get_selected_instance()->undo_action_stack().front()!=action) + if(get_selected_instance()->redo()==false) + throw int(); + } + } + catch(int) + { + return true; + } + } + } + + case GDK_BUTTON_RELEASE: + break; + default: + break; + } + return false; +} + +void +Dock_History::on_action_toggle(const Glib::ustring& path_string) +{ + studio::HistoryTreeStore::Model history_tree_model; + + Gtk::TreePath path(path_string); + + const Gtk::TreeRow row = *(selected_instance->history_tree_store()->get_iter(path)); + + handle action=row[history_tree_model.action]; + + selected_instance->synfigapp::Instance::set_action_status(action,!action->is_active()); +}