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