initial version
[synfig.git] / synfig-studio / trunk / src / gtkmm / historytreestore.cpp
1 /* === S I N F G =========================================================== */
2 /*!     \file historytreestore.cpp
3 **      \brief Template File
4 **
5 **      $Id: historytreestore.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #ifdef USING_PCH
25 #       include "pch.h"
26 #else
27 #ifdef HAVE_CONFIG_H
28 #       include <config.h>
29 #endif
30
31 #include "historytreestore.h"
32 #include <sinfg/valuenode.h>
33 #include "iconcontroler.h"
34 #include <sinfg/valuenode_timedswap.h>
35 #include <gtkmm/button.h>
36 #include <sinfgapp/action.h>
37 #include "instance.h"
38
39 #endif
40
41 /* === U S I N G =========================================================== */
42
43 using namespace std;
44 using namespace etl;
45 using namespace sinfg;
46 using namespace studio;
47
48 /* === M A C R O S ========================================================= */
49
50 /* === G L O B A L S ======================================================= */
51
52 /* === P R O C E D U R E S ================================================= */
53
54 /* === M E T H O D S ======================================================= */
55
56 static HistoryTreeStore::Model& ModelHack()
57 {
58         static HistoryTreeStore::Model* model(0);
59         if(!model)model=new HistoryTreeStore::Model;
60         return *model;
61 }
62
63 HistoryTreeStore::HistoryTreeStore(etl::loose_handle<studio::Instance> instance_):
64         Gtk::TreeStore  (ModelHack()),
65         instance_               (instance_)
66 {
67         instance_->signal_undo().connect(sigc::mem_fun(*this,&studio::HistoryTreeStore::on_undo));
68         instance_->signal_redo().connect(sigc::mem_fun(*this,&studio::HistoryTreeStore::on_redo));
69         instance_->signal_undo_stack_cleared().connect(sigc::mem_fun(*this,&studio::HistoryTreeStore::on_undo_stack_cleared));
70         instance_->signal_redo_stack_cleared().connect(sigc::mem_fun(*this,&studio::HistoryTreeStore::on_redo_stack_cleared));
71         instance_->signal_new_action().connect(sigc::mem_fun(*this,&studio::HistoryTreeStore::on_new_action));
72         instance_->signal_action_status_changed().connect(sigc::mem_fun(*this,&studio::HistoryTreeStore::on_action_status_changed));
73 }
74
75 HistoryTreeStore::~HistoryTreeStore()
76 {
77         sinfg::info("HistoryTreeStore::~HistoryTreeStore(): Deleted");
78 }
79
80 Glib::RefPtr<HistoryTreeStore>
81 HistoryTreeStore::create(etl::loose_handle<studio::Instance> instance_)
82 {
83         return Glib::RefPtr<HistoryTreeStore>(new HistoryTreeStore(instance_));
84 }
85
86 void
87 HistoryTreeStore::rebuild()
88 {
89         sinfgapp::Action::Stack::const_iterator iter;
90         
91         clear();
92         
93         for(iter=instance()->undo_action_stack().begin();iter!=instance()->undo_action_stack().end();++iter)
94         {
95                 insert_action(*(prepend()),*iter,true,true,false);      
96         }
97         curr_row=*children().end();
98         for(iter=instance()->redo_action_stack().begin();iter!=instance()->redo_action_stack().end();++iter)
99         {
100                 insert_action(*(append()),*iter,true,false,true);       
101         }               
102 }
103
104 void
105 HistoryTreeStore::insert_action(Gtk::TreeRow row,etl::handle<sinfgapp::Action::Undoable> action, bool is_active, bool is_undo, bool is_redo)
106 {
107         assert(action);
108
109         row[model.action] = action;
110         row[model.name] = static_cast<Glib::ustring>(action->get_local_name());
111         row[model.is_active] = action->is_active();
112         row[model.is_undo] = is_undo;
113         row[model.is_redo] = is_redo;
114         
115         sinfgapp::Action::CanvasSpecific *specific_action;
116         specific_action=dynamic_cast<sinfgapp::Action::CanvasSpecific*>(action.get());
117         if(specific_action)
118         {
119                 row[model.canvas] = specific_action->get_canvas();
120                 row[model.canvas_id] = specific_action->get_canvas()->get_id();         
121         }
122
123         etl::handle<sinfgapp::Action::Group> group;
124         group=etl::handle<sinfgapp::Action::Group>::cast_dynamic(action);
125         if(group)
126         {
127                 sinfgapp::Action::ActionList::const_iterator iter;
128                 for(iter=group->action_list().begin();iter!=group->action_list().end();++iter)
129                 {
130                         Gtk::TreeRow child_row = *(append(row.children()));
131                         insert_action(child_row,*iter,true,is_undo,is_redo);
132                 }
133         }
134         
135         //row[model.icon] = Gtk::Button().render_icon(Gtk::StockID("sinfg-canvas"),Gtk::ICON_SIZE_SMALL_TOOLBAR);       
136 }
137
138
139 void
140 HistoryTreeStore::on_undo()
141 {
142         refresh();
143 }
144
145 void
146 HistoryTreeStore::on_redo()
147 {
148         refresh();
149 }
150
151 void
152 HistoryTreeStore::on_undo_stack_cleared()
153 {
154         Gtk::TreeModel::Children::iterator iter,next;
155         Gtk::TreeModel::Children children_(children());
156         
157         for(next=children_.begin(),iter=next++; iter != children_.end(); iter=(next!=children_.end())?next++:next)
158         {
159                 Gtk::TreeModel::Row row = *iter;
160                 if(row[model.is_undo])
161                         erase(iter);
162         }
163 }
164
165 void
166 HistoryTreeStore::on_redo_stack_cleared()
167 {
168         Gtk::TreeModel::Children::iterator iter,next;
169         Gtk::TreeModel::Children children_(children());
170         
171         for(next=children_.begin(),iter=next++; iter != children_.end(); iter=(next!=children_.end())?next++:next)
172         {
173                 Gtk::TreeModel::Row row = *iter;
174                 if(row[model.is_redo])
175                         erase(iter);
176         }
177 }
178
179 void
180 HistoryTreeStore::on_new_action(etl::handle<sinfgapp::Action::Undoable> action)
181 {
182 //      Gtk::TreeRow row = *(append());
183         Gtk::TreeRow row;
184         Gtk::TreeModel::Children::iterator iter;
185         for(iter=children().begin(); iter != children().end(); ++iter)
186         {
187                 Gtk::TreeModel::Row row = *iter;
188                 if(row[model.is_redo])
189                 {
190                         break;
191                 }
192         }
193
194         row=*insert(iter);
195
196         insert_action(row,action);
197 }
198
199 void
200 HistoryTreeStore::on_action_status_changed(etl::handle<sinfgapp::Action::Undoable> action)
201 {
202         Gtk::TreeModel::Children::iterator iter;
203         Gtk::TreeModel::Children children_(children());
204         
205         for(iter=children_.begin(); iter != children_.end(); ++iter)
206         {
207                 Gtk::TreeModel::Row row = *iter;
208                 if(action == (etl::handle<sinfgapp::Action::Undoable>)row[model.action])
209                 {
210                         row[model.is_active]=action->is_active();
211                         return;
212                 }
213         }       
214 }