Fix most of the warnings from doxygen for synfig-studio sources.
[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_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                         if(iter2 && value_desc==(*iter2)[model.value_desc] || find_next_value_desc(value_desc, iter2))
290                         {
291                                 iter=iter2;
292                                 return true;
293                         }
294                 }
295                 Gtk::TreeIter iter2(++iter);
296                 if(!iter2)
297                         iter==iter->parent();
298                 else
299                         iter=iter2;
300         }
301         return (bool)iter && value_desc==(*iter)[model.value_desc];
302 }
303
304 bool
305 CanvasTreeStore::find_next_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter)
306 {
307         if(!iter) return find_first_value_desc(value_desc,iter);
308
309         if(iter) do {
310                 if(!iter->children().empty())
311                 {
312                         Gtk::TreeIter iter2(iter->children().begin());
313                         if(iter2 && value_desc==(*iter2)[model.value_desc] || find_next_value_desc(value_desc, iter2))
314                         {
315                                 iter=iter2;
316                                 return true;
317                         }
318                 }
319                 Gtk::TreeIter iter2(++iter);
320                 if(!iter2)
321                 {
322                         iter==iter->parent();
323                         if(iter)++iter;
324                 }
325                 else
326                         iter=iter2;
327         } while(iter && value_desc!=(*iter)[model.value_desc]);
328         return (bool)iter && value_desc==(*iter)[model.value_desc];
329 }
330
331 bool
332 CanvasTreeStore::find_first_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
333 {
334         iter=children().begin();
335         while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node])
336         {
337                 if(!iter->children().empty())
338                 {
339                         Gtk::TreeIter iter2(iter->children().begin());
340                         if(iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node] || find_next_value_node(value_node, iter2))
341                         {
342                                 iter=iter2;
343                                 return true;
344                         }
345                 }
346                 Gtk::TreeIter iter2(++iter);
347                 if(!iter2)
348                         iter==iter->parent();
349                 else
350                         iter=iter2;
351         }
352         return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node];
353 }
354
355 bool
356 CanvasTreeStore::find_next_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
357 {
358         if(!iter) return find_first_value_node(value_node,iter);
359
360         if(iter) do {
361                 if(!iter->children().empty())
362                 {
363                         Gtk::TreeIter iter2(iter->children().begin());
364                         if(iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node] || find_next_value_node(value_node, iter2))
365                         {
366                                 iter=iter2;
367                                 return true;
368                         }
369                 }
370                 Gtk::TreeIter iter2(++iter);
371                 if(!iter2)
372                 {
373                         iter==iter->parent();
374                         if(iter)++iter;
375                 }
376                 else
377                         iter=iter2;
378         } while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node]);
379         return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node];
380 }
381
382 void
383 CanvasTreeStore::set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc, bool do_children)
384 {
385         Gtk::TreeModel::Children children = row.children();
386         while(!children.empty() && erase(children.begin()));
387
388         row[model.value_desc]=value_desc;
389         try
390         {
391                 //row[model.icon] = get_tree_pixbuf(value_desc.get_value_type());
392
393                 if(value_desc.is_value_node())
394                 {
395                         ValueNode::Handle value_node=value_desc.get_value_node();
396
397                         assert(value_node);
398
399                         row[model.value_node] = value_node;
400                         //row[model.is_canvas] = false;
401                         //row[model.is_value_node] = true;
402                         //row[model.is_editable] = synfigapp::is_editable(value_node);
403                         //row[model.id]=value_node->get_id();
404
405                         // Set the canvas
406                         if(value_desc.parent_is_canvas())
407                                 row[model.canvas]=value_desc.get_canvas();
408                         else
409                                 row[model.canvas]=canvas_interface()->get_canvas();
410
411                         LinkableValueNode::Handle linkable;
412                         linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
413
414                         if(linkable && do_children)
415                         {
416                                 row[model.link_count] = linkable->link_count();
417                                 for(int i=0;i<linkable->link_count();i++)
418                                 {
419                                         Gtk::TreeRow child_row=*(append(row.children()));
420                                         child_row[model.link_id] = i;
421                                         child_row[model.canvas] = static_cast<Canvas::Handle>(row[model.canvas]);
422                                         child_row[model.name] = linkable->link_local_name(i);
423                                         set_row(child_row,synfigapp::ValueDesc(linkable,i));
424                                 }
425                         }
426                         return;
427                 }
428                 else
429                 {
430                         //row[model.is_value_node] = false;
431                         //row[model.is_editable] = true;
432                         //row[model.label] = Glib::ustring(row[model.name]);
433                         return;
434                 }
435         }
436         catch(synfig::Exception::IDNotFound x)
437         {
438                 synfig::error(__FILE__":%d: IDNotFound thrown",__LINE__);
439                 erase(row);
440                 return;
441         }
442
443         // We should never get to this point
444         assert(0);
445 }
446
447 void
448 CanvasTreeStore::refresh_row(Gtk::TreeModel::Row &row, bool do_children)
449 {
450         synfigapp::ValueDesc value_desc=row[model.value_desc];
451
452         if(value_desc)
453         {
454                 if((bool)row[model.is_value_node] != value_desc.is_value_node() ||
455                         (!bool(row[model.is_value_node]) && row[model.link_count]!=0))
456                 {
457                         set_row(row,value_desc,do_children);
458                         return;
459                 }
460
461                 if(row[model.is_value_node])
462                 {
463                         ValueNode::Handle value_node(value_desc.get_value_node());
464
465                         if(ValueNode::Handle(row[model.value_node])!=value_node)
466                         {
467                                 rebuild_row(row,do_children);
468                                 return;
469                         }
470
471                         //row[model.id]=value_node->get_id();
472
473                         // Setup the row's label
474                         /*
475                         if(value_node->get_id().empty())
476                                 row[model.label] = Glib::ustring(row[model.name]);
477                         else if(Glib::ustring(row[model.name]).empty())
478                                 row[model.label] = value_node->get_id();
479                         else
480                                 row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
481                         */
482
483                         LinkableValueNode::Handle linkable;
484                         linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
485                         if(do_children && linkable && ((int)row[model.link_count] != linkable->link_count()))
486                         {
487         //                      Gtk::TreeModel::Children children = row.children();
488         //                      while(!children.empty() && erase(children.begin()));
489
490                                 set_row(row,value_desc);
491                                 return;
492                         }
493                 }
494                 else
495                 {
496                         //row[model.label] = Glib::ustring(row[model.name]);
497                         //row[model.is_value_node] = false;
498                         //row[model.is_editable] = true;
499                 }
500         }
501         if(!do_children)
502                 return;
503
504         Gtk::TreeModel::Children children = row.children();
505         Gtk::TreeModel::Children::iterator iter;
506
507         if(!children.empty())
508         for(iter = children.begin(); iter != children.end(); ++iter)
509         {
510                 Gtk::TreeRow row=*iter;
511                 refresh_row(row);
512         }
513 }
514
515 void
516 CanvasTreeStore::rebuild_row(Gtk::TreeModel::Row &row, bool do_children)
517 {
518         synfigapp::ValueDesc value_desc=(synfigapp::ValueDesc)row[model.value_desc];
519
520         if(value_desc && value_desc.get_value_node())
521         {
522                 ValueNode::Handle value_node;
523                 value_node=value_desc.get_value_node();
524
525                 assert(value_node);if(!value_node)return;
526
527                 if(value_node && value_node!=(ValueNode::Handle)row[model.value_node])
528                 {
529 //                      Gtk::TreeModel::Children children = row.children();
530 //                      while(!children.empty() && erase(children.begin()));
531
532                         set_row(row,value_desc,do_children);
533                         return;
534                 }
535
536                 LinkableValueNode::Handle linkable;
537                 linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
538
539                 if( do_children && linkable && (int)row[model.link_count] != linkable->link_count())
540                 {
541 //                      Gtk::TreeModel::Children children = row.children();
542 //                      while(!children.empty() && erase(children.begin()));
543
544                         set_row(row,value_desc);
545                         return;
546                 }
547
548                 //if(!value_node)
549                 //      value_node=row[model.value_node];
550
551                 row[model.id]=value_node->get_id();
552
553                 // Setup the row's label
554                 if(value_node->get_id().empty())
555                         row[model.label] = Glib::ustring(row[model.name]);
556                 else if(Glib::ustring(row[model.name]).empty())
557                         row[model.label] = value_node->get_id();
558                 else
559                         row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
560         }
561         else
562         {
563                 row[model.label] = Glib::ustring(row[model.name]);
564                 row[model.is_value_node] = false;
565                 row[model.is_editable] = true;
566                 Gtk::TreeModel::Children children = row.children();
567                 while(!children.empty() && erase(children.begin()));
568         }
569         if(!do_children)
570                 return;
571
572         Gtk::TreeModel::Children children = row.children();
573         Gtk::TreeModel::Children::iterator iter;
574         if(!children.empty())
575         for(iter = children.begin(); iter != children.end(); ++iter)
576         {
577                 Gtk::TreeRow row=*iter;
578                 rebuild_row(row);
579         }
580 }
581
582 CellRenderer_ValueBase*
583 CanvasTreeStore::add_cell_renderer_value(Gtk::TreeView::Column* column)
584 {
585         const CanvasTreeStore::Model model;
586
587         CellRenderer_ValueBase* ret;
588
589         ret=Gtk::manage( new CellRenderer_ValueBase() );
590
591         column->pack_start(*ret,true);
592         column->add_attribute(ret->property_value(), model.value);
593         column->add_attribute(ret->property_editable(), model.is_editable);
594         column->add_attribute(ret->property_canvas(), model.canvas);
595
596         return ret;
597 }
598
599 CellRenderer_TimeTrack*
600 CanvasTreeStore::add_cell_renderer_value_node(Gtk::TreeView::Column* column)
601 {
602         const CanvasTreeStore::Model model;
603
604         CellRenderer_TimeTrack* ret;
605
606         ret = Gtk::manage( new CellRenderer_TimeTrack() );
607
608         column->pack_start(*ret,true);
609         //column->add_attribute(ret->property_visible(), model.is_value_node);
610         column->add_attribute(ret->property_value_desc(), model.value_desc);
611         column->add_attribute(ret->property_canvas(), model.canvas);
612
613
614         return ret;
615 }