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