Allow scrolling left and right in time widgets
[synfig.git] / synfig-studio / trunk / src / gtkmm / canvastreestore.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file canvastreestore.cpp
3 **      \brief Template File
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2008 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "canvastreestore.h"
34 #include <synfig/valuenode.h>
35 #include "iconcontroller.h"
36 #include <synfig/valuenode_timedswap.h>
37 #include <synfig/valuenode_animated.h>
38 #include <gtkmm/button.h>
39 #include <synfigapp/instance.h>
40 #include "cellrenderer_value.h"
41 #include "cellrenderer_timetrack.h"
42 #include <ETL/clock>
43
44 #include "general.h"
45
46 #endif
47
48 /* === U S I N G =========================================================== */
49
50 using namespace std;
51 using namespace etl;
52 using namespace synfig;
53 using namespace studio;
54
55 /* === M A C R O S ========================================================= */
56
57 /* === G L O B A L S ======================================================= */
58
59 /* === P R O C E D U R E S ================================================= */
60
61 /* === M E T H O D S ======================================================= */
62
63 static CanvasTreeStore::Model& ModelHack()
64 {
65         static CanvasTreeStore::Model* model(0);
66         if(!model)model=new CanvasTreeStore::Model;
67         return *model;
68 }
69
70 CanvasTreeStore::CanvasTreeStore(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_):
71         Gtk::TreeStore(ModelHack()),
72         canvas_interface_               (canvas_interface_)
73 {
74 }
75
76 CanvasTreeStore::~CanvasTreeStore()
77 {
78 }
79
80 void
81 CanvasTreeStore::get_value_vfunc(const Gtk::TreeModel::iterator& iter, int column, Glib::ValueBase& value)const
82 {
83         if(column==model.value.index())
84         {
85                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
86
87                 Glib::Value<synfig::ValueBase> x;
88                 g_value_init(x.gobj(),x.value_type());
89
90                 if(!value_desc)
91                 {
92                         x.set(ValueBase());
93                 }
94                 else
95                 if(value_desc.is_const())
96                         x.set(value_desc.get_value());
97                 else
98                 if(value_desc.is_value_node())
99                         x.set((*value_desc.get_value_node())(canvas_interface()->get_time()));
100                 else
101                 {
102                         synfig::error(__FILE__":%d: Unable to figure out value",__LINE__);
103                         return;
104                 }
105
106                 g_value_init(value.gobj(),x.value_type());
107                 g_value_copy(x.gobj(),value.gobj());
108         }
109         else
110         if(column==model.is_value_node.index())
111         {
112                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
113
114                 Glib::Value<bool> x;
115                 g_value_init(x.gobj(),x.value_type());
116
117                 x.set(value_desc && value_desc.is_value_node());
118
119                 g_value_init(value.gobj(),x.value_type());
120                 g_value_copy(x.gobj(),value.gobj());
121         }
122         else
123         if(column==model.is_shared.index())
124         {
125                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
126
127                 Glib::Value<bool> x;
128                 g_value_init(x.gobj(),x.value_type());
129
130                 x.set(value_desc.is_value_node() && value_desc.get_value_node()->rcount()>1);
131
132                 g_value_init(value.gobj(),x.value_type());
133                 g_value_copy(x.gobj(),value.gobj());
134         }
135         else
136         if(column==model.is_exported.index())
137         {
138                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
139
140                 Glib::Value<bool> x;
141                 g_value_init(x.gobj(),x.value_type());
142
143                 x.set(value_desc.is_value_node() && value_desc.get_value_node()->is_exported());
144
145                 g_value_init(value.gobj(),x.value_type());
146                 g_value_copy(x.gobj(),value.gobj());
147         }
148         else
149         if(column==model.is_canvas.index())
150         {
151                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
152
153                 Glib::Value<bool> x;
154                 g_value_init(x.gobj(),x.value_type());
155
156                 x.set(!value_desc && (Canvas::Handle)(*iter)[model.canvas]);
157
158                 g_value_init(value.gobj(),x.value_type());
159                 g_value_copy(x.gobj(),value.gobj());
160         }
161         else
162         if(column==model.id.index())
163         {
164                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
165
166                 Glib::Value<Glib::ustring> x;
167                 g_value_init(x.gobj(),x.value_type());
168
169                 if(value_desc && value_desc.is_value_node())
170                         x.set(value_desc.get_value_node()->get_id());
171                 else if(!value_desc && Canvas::Handle((*iter)[model.canvas]))
172                         x.set(Canvas::Handle((*iter)[model.canvas])->get_id());
173                 else
174                         return Gtk::TreeStore::get_value_vfunc(iter,column,value);
175
176                 g_value_init(value.gobj(),x.value_type());
177                 g_value_copy(x.gobj(),value.gobj());
178         }
179         else
180         if(column==model.is_editable.index())
181         {
182                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
183
184                 Glib::Value<bool> x;
185                 g_value_init(x.gobj(),x.value_type());
186
187                 x.set(!value_desc.is_value_node() || synfigapp::is_editable(value_desc.get_value_node()));
188
189                 g_value_init(value.gobj(),x.value_type());
190                 g_value_copy(x.gobj(),value.gobj());
191         }
192         else
193         if(column==model.type.index())
194         {
195                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
196
197                 Glib::Value<Glib::ustring> x;
198                 g_value_init(x.gobj(),x.value_type());
199
200                 // Set the type
201                 if(!value_desc)
202                 {
203                         if((*iter)[model.is_canvas])
204                                 x.set(_("Canvas"));
205                 }
206                 else
207                 {
208                         if(!value_desc.is_value_node() || value_desc.get_value_node()->get_name()=="constant")
209                         {
210                                 x.set(ValueBase::type_local_name(value_desc.get_value_type()));
211                         }
212                         else
213                         {
214                                 x.set(value_desc.get_value_node()->get_local_name());
215                         }
216                 }
217
218                 g_value_init(value.gobj(),x.value_type());
219                 g_value_copy(x.gobj(),value.gobj());
220         }
221         else
222         if(column==model.label.index())
223         {
224                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
225
226                 Glib::Value<Glib::ustring> x;
227                 g_value_init(x.gobj(),x.value_type());
228
229                 // Set the type
230                 if(!value_desc)
231                 {
232                         Canvas::Handle canvas((*iter)[model.canvas]);
233                         if(canvas)
234                         {
235                                 if(!canvas->get_id().empty())
236                                         x.set(canvas->get_id());
237                                 else
238                                 if(!canvas->get_name().empty())
239                                         x.set(canvas->get_name());
240                                 else
241                                         x.set(_("[Unnamed]"));
242                                 x.set(_("Canvas"));
243                         }
244                         return Gtk::TreeStore::get_value_vfunc(iter,column,value);
245                 }
246                 else
247                 {
248                         ValueNode::Handle value_node=value_desc.get_value_node();
249
250                         // Setup the row's label
251                         if(value_node->get_id().empty())
252                                 x.set(Glib::ustring((*iter)[model.name]));
253                         else if(Glib::ustring((*iter)[model.name]).empty())
254                                 x.set(value_node->get_id());
255                         else
256                                 x.set(Glib::ustring((*iter)[model.name])+" ("+value_node->get_id()+')');
257                 }
258
259                 g_value_init(value.gobj(),x.value_type());
260                 g_value_copy(x.gobj(),value.gobj());
261         }
262         else
263         if(column==model.icon.index())
264         {
265                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
266                 if(!value_desc)
267                         return Gtk::TreeStore::get_value_vfunc(iter,column,value);
268
269                 Glib::Value<Glib::RefPtr<Gdk::Pixbuf> > x;
270                 g_value_init(x.gobj(),x.value_type());
271
272                 x.set(get_tree_pixbuf(value_desc.get_value_type()));
273
274                 g_value_init(value.gobj(),x.value_type());
275                 g_value_copy(x.gobj(),value.gobj());
276         }
277         else
278                 Gtk::TreeStore::get_value_vfunc(iter,column,value);
279 }
280
281 bool
282 CanvasTreeStore::find_first_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter)
283 {
284         iter=children().begin();
285         while(iter && value_desc!=(*iter)[model.value_desc])
286         {
287                 if(!iter->children().empty())
288                 {
289                         Gtk::TreeIter iter2(iter->children().begin());
290                         //! \todo confirm that the && should be done before the ||
291                         if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2))
292                         {
293                                 iter=iter2;
294                                 return true;
295                         }
296                 }
297                 Gtk::TreeIter iter2(++iter);
298                 if(!iter2)
299                         iter==iter->parent();
300                 else
301                         iter=iter2;
302         }
303         return (bool)iter && value_desc==(*iter)[model.value_desc];
304 }
305
306 bool
307 CanvasTreeStore::find_next_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter)
308 {
309         if(!iter) return find_first_value_desc(value_desc,iter);
310
311         if(iter) do {
312                 if(!iter->children().empty())
313                 {
314                         Gtk::TreeIter iter2(iter->children().begin());
315                         //! \todo confirm that the && should be done before the ||
316                         if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2))
317                         {
318                                 iter=iter2;
319                                 return true;
320                         }
321                 }
322                 Gtk::TreeIter iter2(++iter);
323                 if(!iter2)
324                 {
325                         iter==iter->parent();
326                         if(iter)++iter;
327                 }
328                 else
329                         iter=iter2;
330         } while(iter && value_desc!=(*iter)[model.value_desc]);
331         return (bool)iter && value_desc==(*iter)[model.value_desc];
332 }
333
334 bool
335 CanvasTreeStore::find_first_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
336 {
337         iter=children().begin();
338         while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node])
339         {
340                 if(!iter->children().empty())
341                 {
342                         Gtk::TreeIter iter2(iter->children().begin());
343                         //! \todo confirm that the && should be done before the ||
344                         if((iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(value_node, iter2))
345                         {
346                                 iter=iter2;
347                                 return true;
348                         }
349                 }
350                 Gtk::TreeIter iter2(++iter);
351                 if(!iter2)
352                         iter==iter->parent();
353                 else
354                         iter=iter2;
355         }
356         return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node];
357 }
358
359 bool
360 CanvasTreeStore::find_next_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
361 {
362         if(!iter) return find_first_value_node(value_node,iter);
363
364         if(iter) do {
365                 if(!iter->children().empty())
366                 {
367                         Gtk::TreeIter iter2(iter->children().begin());
368                         //! \todo confirm that the && should be done before the ||
369                         if((iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(value_node, iter2))
370                         {
371                                 iter=iter2;
372                                 return true;
373                         }
374                 }
375                 Gtk::TreeIter iter2(++iter);
376                 if(!iter2)
377                 {
378                         iter==iter->parent();
379                         if(iter)++iter;
380                 }
381                 else
382                         iter=iter2;
383         } while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node]);
384         return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node];
385 }
386
387 void
388 CanvasTreeStore::set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc, bool do_children)
389 {
390         Gtk::TreeModel::Children children = row.children();
391         while(!children.empty() && erase(children.begin()))
392                 ;
393
394         row[model.value_desc]=value_desc;
395         try
396         {
397                 //row[model.icon] = get_tree_pixbuf(value_desc.get_value_type());
398
399                 if(value_desc.is_value_node())
400                 {
401                         ValueNode::Handle value_node=value_desc.get_value_node();
402
403                         assert(value_node);
404
405                         row[model.value_node] = value_node;
406                         //row[model.is_canvas] = false;
407                         //row[model.is_value_node] = true;
408                         //row[model.is_editable] = synfigapp::is_editable(value_node);
409                         //row[model.id]=value_node->get_id();
410
411                         // Set the canvas
412                         if(value_desc.parent_is_canvas())
413                                 row[model.canvas]=value_desc.get_canvas();
414                         else
415                                 row[model.canvas]=canvas_interface()->get_canvas();
416
417                         LinkableValueNode::Handle linkable;
418                         linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
419
420                         if(linkable && do_children)
421                         {
422                                 row[model.link_count] = linkable->link_count();
423                                 for(int i=0;i<linkable->link_count();i++)
424                                 {
425                                         Gtk::TreeRow child_row=*(append(row.children()));
426                                         child_row[model.link_id] = i;
427                                         child_row[model.canvas] = static_cast<Canvas::Handle>(row[model.canvas]);
428                                         child_row[model.name] = linkable->link_local_name(i);
429                                         set_row(child_row,synfigapp::ValueDesc(linkable,i));
430                                 }
431                         }
432                         return;
433                 }
434                 else
435                 {
436                         //row[model.is_value_node] = false;
437                         //row[model.is_editable] = true;
438                         //row[model.label] = Glib::ustring(row[model.name]);
439                         return;
440                 }
441         }
442         catch(synfig::Exception::IDNotFound x)
443         {
444                 synfig::error(__FILE__":%d: IDNotFound thrown",__LINE__);
445                 erase(row);
446                 return;
447         }
448
449         // We should never get to this point
450         assert(0);
451 }
452
453 void
454 CanvasTreeStore::refresh_row(Gtk::TreeModel::Row &row, bool do_children)
455 {
456         synfigapp::ValueDesc value_desc=row[model.value_desc];
457
458         if(value_desc)
459         {
460                 if((bool)row[model.is_value_node] != value_desc.is_value_node() ||
461                         (!bool(row[model.is_value_node]) && row[model.link_count]!=0))
462                 {
463                         set_row(row,value_desc,do_children);
464                         return;
465                 }
466
467                 if(row[model.is_value_node])
468                 {
469                         ValueNode::Handle value_node(value_desc.get_value_node());
470
471                         if(ValueNode::Handle(row[model.value_node])!=value_node)
472                         {
473                                 rebuild_row(row,do_children);
474                                 return;
475                         }
476
477                         //row[model.id]=value_node->get_id();
478
479                         // Setup the row's label
480                         /*
481                         if(value_node->get_id().empty())
482                                 row[model.label] = Glib::ustring(row[model.name]);
483                         else if(Glib::ustring(row[model.name]).empty())
484                                 row[model.label] = value_node->get_id();
485                         else
486                                 row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
487                         */
488
489                         LinkableValueNode::Handle linkable;
490                         linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
491                         if(do_children && linkable && ((int)row[model.link_count] != linkable->link_count()))
492                         {
493         //                      Gtk::TreeModel::Children children = row.children();
494         //                      while(!children.empty() && erase(children.begin()));
495
496                                 set_row(row,value_desc);
497                                 return;
498                         }
499                 }
500                 else
501                 {
502                         //row[model.label] = Glib::ustring(row[model.name]);
503                         //row[model.is_value_node] = false;
504                         //row[model.is_editable] = true;
505                 }
506         }
507         if(!do_children)
508                 return;
509
510         Gtk::TreeModel::Children children = row.children();
511         Gtk::TreeModel::Children::iterator iter;
512
513         if(!children.empty())
514         for(iter = children.begin(); iter != children.end(); ++iter)
515         {
516                 Gtk::TreeRow row=*iter;
517                 refresh_row(row);
518         }
519 }
520
521 void
522 CanvasTreeStore::rebuild_row(Gtk::TreeModel::Row &row, bool do_children)
523 {
524         synfigapp::ValueDesc value_desc=(synfigapp::ValueDesc)row[model.value_desc];
525
526         if(value_desc && value_desc.get_value_node())
527         {
528                 ValueNode::Handle value_node;
529                 value_node=value_desc.get_value_node();
530
531                 assert(value_node);if(!value_node)return;
532
533                 if(value_node && value_node!=(ValueNode::Handle)row[model.value_node])
534                 {
535 //                      Gtk::TreeModel::Children children = row.children();
536 //                      while(!children.empty() && erase(children.begin()));
537
538                         set_row(row,value_desc,do_children);
539                         return;
540                 }
541
542                 LinkableValueNode::Handle linkable;
543                 linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
544
545                 if( do_children && linkable && (int)row[model.link_count] != linkable->link_count())
546                 {
547 //                      Gtk::TreeModel::Children children = row.children();
548 //                      while(!children.empty() && erase(children.begin()));
549
550                         set_row(row,value_desc);
551                         return;
552                 }
553
554                 //if(!value_node)
555                 //      value_node=row[model.value_node];
556
557                 row[model.id]=value_node->get_id();
558
559                 // Setup the row's label
560                 if(value_node->get_id().empty())
561                         row[model.label] = Glib::ustring(row[model.name]);
562                 else if(Glib::ustring(row[model.name]).empty())
563                         row[model.label] = value_node->get_id();
564                 else
565                         row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
566         }
567         else
568         {
569                 row[model.label] = Glib::ustring(row[model.name]);
570                 row[model.is_value_node] = false;
571                 row[model.is_editable] = true;
572                 Gtk::TreeModel::Children children = row.children();
573                 while(!children.empty() && erase(children.begin()))
574                         ;
575         }
576         if(!do_children)
577                 return;
578
579         Gtk::TreeModel::Children children = row.children();
580         Gtk::TreeModel::Children::iterator iter;
581         if(!children.empty())
582         for(iter = children.begin(); iter != children.end(); ++iter)
583         {
584                 Gtk::TreeRow row=*iter;
585                 rebuild_row(row);
586         }
587 }
588
589 CellRenderer_ValueBase*
590 CanvasTreeStore::add_cell_renderer_value(Gtk::TreeView::Column* column)
591 {
592         const CanvasTreeStore::Model model;
593
594         CellRenderer_ValueBase* ret;
595
596         ret=Gtk::manage( new CellRenderer_ValueBase() );
597
598         column->pack_start(*ret,true);
599         column->add_attribute(ret->property_value(), model.value);
600         column->add_attribute(ret->property_editable(), model.is_editable);
601         column->add_attribute(ret->property_canvas(), model.canvas);
602
603         return ret;
604 }
605
606 CellRenderer_TimeTrack*
607 CanvasTreeStore::add_cell_renderer_value_node(Gtk::TreeView::Column* column)
608 {
609         const CanvasTreeStore::Model model;
610
611         CellRenderer_TimeTrack* ret;
612
613         ret = Gtk::manage( new CellRenderer_TimeTrack() );
614
615         column->pack_start(*ret,true);
616         //column->add_attribute(ret->property_visible(), model.is_value_node);
617         column->add_attribute(ret->property_value_desc(), model.value_desc);
618         column->add_attribute(ret->property_canvas(), model.canvas);
619
620
621         return ret;
622 }