57fd42a8d59fdfe83e4ea3f1a9ccec3c6c06cbe5
[synfig.git] / synfig-studio / src / gui / trees / 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 "trees/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/cellrenderer_value.h"
41 #include "cellrenderer/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                 String stype, lname;
197
198                 Glib::Value<Glib::ustring> x;
199                 g_value_init(x.gobj(),x.value_type());
200
201                 // Set the type
202                 if(!value_desc)
203                 {
204                         if((*iter)[model.is_canvas])
205                                 x.set(_("Canvas"));
206                 }
207                 else
208                 {
209                         stype=ValueBase::type_local_name(value_desc.get_value_type());
210                         if(value_desc.get_value_node())
211                         {
212                                 lname=value_desc.get_value_node()->get_name();
213                                 if (lname=="animated" || lname=="static")
214                                         stype+=" (" + value_desc.get_value_node()->get_local_name() + ")";
215                         }
216                         else if(value_desc.parent_is_layer_param())
217                         {
218                                 if(value_desc.get_value().get_static())
219                                         stype+=_(" (Static)");
220                         }
221                 }
222                 x.set(stype.c_str());
223                 g_value_init(value.gobj(),x.value_type());
224                 g_value_copy(x.gobj(),value.gobj());
225         }
226         else
227         if(column==model.label.index())
228         {
229                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
230
231                 Glib::Value<Glib::ustring> x;
232                 g_value_init(x.gobj(),x.value_type());
233
234                 // Set the type
235                 if(!value_desc)
236                 {
237                         Canvas::Handle canvas((*iter)[model.canvas]);
238                         if(canvas)
239                         {
240                                 if(!canvas->get_id().empty())
241                                         x.set(canvas->get_id());
242                                 else
243                                 if(!canvas->get_name().empty())
244                                         x.set(canvas->get_name());
245                                 else
246                                         x.set(_("[Unnamed]"));
247                                 x.set(_("Canvas"));
248                         }
249                         return Gtk::TreeStore::get_value_vfunc(iter,column,value);
250                 }
251                 else
252                 {
253                         ValueNode::Handle value_node=value_desc.get_value_node();
254
255                         // Setup the row's label
256                         if(value_node->get_id().empty())
257                                 x.set(Glib::ustring((*iter)[model.name]));
258                         else if(Glib::ustring((*iter)[model.name]).empty())
259                                 x.set(value_node->get_id());
260                         else
261                                 x.set(Glib::ustring((*iter)[model.name])+" ("+value_node->get_id()+')');
262                 }
263
264                 g_value_init(value.gobj(),x.value_type());
265                 g_value_copy(x.gobj(),value.gobj());
266         }
267         else
268         if(column==model.icon.index())
269         {
270                 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
271                 if(!value_desc)
272                         return Gtk::TreeStore::get_value_vfunc(iter,column,value);
273
274                 Glib::Value<Glib::RefPtr<Gdk::Pixbuf> > x;
275                 g_value_init(x.gobj(),x.value_type());
276
277                 x.set(get_tree_pixbuf(value_desc.get_value_type()));
278
279                 g_value_init(value.gobj(),x.value_type());
280                 g_value_copy(x.gobj(),value.gobj());
281         }
282         else
283                 Gtk::TreeStore::get_value_vfunc(iter,column,value);
284 }
285
286 bool
287 CanvasTreeStore::find_first_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter)
288 {
289         iter=children().begin();
290         while(iter && value_desc!=(*iter)[model.value_desc])
291         {
292                 if(!iter->children().empty())
293                 {
294                         Gtk::TreeIter iter2(iter->children().begin());
295                         //! \todo confirm that the && should be done before the ||
296                         if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2))
297                         {
298                                 iter=iter2;
299                                 return true;
300                         }
301                 }
302                 Gtk::TreeIter iter2(++iter);
303                 if(!iter2)
304                         iter==iter->parent();
305                 else
306                         iter=iter2;
307         }
308         return (bool)iter && value_desc==(*iter)[model.value_desc];
309 }
310
311 bool
312 CanvasTreeStore::find_next_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter)
313 {
314         if(!iter) return find_first_value_desc(value_desc,iter);
315
316         if(iter) do {
317                 if(!iter->children().empty())
318                 {
319                         Gtk::TreeIter iter2(iter->children().begin());
320                         //! \todo confirm that the && should be done before the ||
321                         if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2))
322                         {
323                                 iter=iter2;
324                                 return true;
325                         }
326                 }
327                 Gtk::TreeIter iter2(++iter);
328                 if(!iter2)
329                 {
330                         iter==iter->parent();
331                         if(iter)++iter;
332                 }
333                 else
334                         iter=iter2;
335         } while(iter && value_desc!=(*iter)[model.value_desc]);
336         return (bool)iter && value_desc==(*iter)[model.value_desc];
337 }
338
339 bool
340 CanvasTreeStore::find_first_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
341 {
342         iter=children().begin();
343         while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node])
344         {
345                 if(!iter->children().empty())
346                 {
347                         Gtk::TreeIter iter2(iter->children().begin());
348                         //! \todo confirm that the && should be done before the ||
349                         if((iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(value_node, iter2))
350                         {
351                                 iter=iter2;
352                                 return true;
353                         }
354                 }
355                 Gtk::TreeIter iter2(++iter);
356                 if(!iter2)
357                         iter==iter->parent();
358                 else
359                         iter=iter2;
360         }
361         return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node];
362 }
363
364 bool
365 CanvasTreeStore::find_next_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
366 {
367         if(!iter) return find_first_value_node(value_node,iter);
368
369         if(iter) do {
370                 if(!iter->children().empty())
371                 {
372                         Gtk::TreeIter iter2(iter->children().begin());
373                         //! \todo confirm that the && should be done before the ||
374                         if((iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(value_node, iter2))
375                         {
376                                 iter=iter2;
377                                 return true;
378                         }
379                 }
380                 Gtk::TreeIter iter2(++iter);
381                 if(!iter2)
382                 {
383                         iter==iter->parent();
384                         if(iter)++iter;
385                 }
386                 else
387                         iter=iter2;
388         } while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node]);
389         return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node];
390 }
391
392 void
393 CanvasTreeStore::set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc, bool do_children)
394 {
395         Gtk::TreeModel::Children children = row.children();
396         while(!children.empty() && erase(children.begin()))
397                 ;
398
399         row[model.value_desc]=value_desc;
400         try
401         {
402                 //row[model.icon] = get_tree_pixbuf(value_desc.get_value_type());
403
404                 if(value_desc.is_value_node())
405                 {
406                         ValueNode::Handle value_node=value_desc.get_value_node();
407
408                         assert(value_node);
409
410                         row[model.value_node] = value_node;
411                         //row[model.is_canvas] = false;
412                         //row[model.is_value_node] = true;
413                         //row[model.is_editable] = synfigapp::is_editable(value_node);
414                         //row[model.id]=value_node->get_id();
415
416                         // Set the canvas
417                         if(value_desc.parent_is_canvas())
418                                 row[model.canvas]=value_desc.get_canvas();
419                         else
420                                 row[model.canvas]=canvas_interface()->get_canvas();
421
422                         LinkableValueNode::Handle linkable;
423                         linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
424
425                         if(linkable && do_children)
426                         {
427                                 row[model.link_count] = linkable->link_count();
428                                 for(int i=0;i<linkable->link_count();i++)
429                                 {
430                                         Gtk::TreeRow child_row=*(append(row.children()));
431                                         child_row[model.link_id] = i;
432                                         child_row[model.canvas] = static_cast<Canvas::Handle>(row[model.canvas]);
433                                         child_row[model.name] = linkable->link_local_name(i);
434                                         set_row(child_row,synfigapp::ValueDesc(linkable,i));
435                                 }
436                         }
437                         return;
438                 }
439                 else
440                 {
441                         //row[model.is_value_node] = false;
442                         //row[model.is_editable] = true;
443                         //row[model.label] = Glib::ustring(row[model.name]);
444                         return;
445                 }
446         }
447         catch(synfig::Exception::IDNotFound x)
448         {
449                 synfig::error(__FILE__":%d: IDNotFound thrown",__LINE__);
450                 erase(row);
451                 return;
452         }
453
454         // We should never get to this point
455         assert(0);
456 }
457
458 void
459 CanvasTreeStore::refresh_row(Gtk::TreeModel::Row &row, bool do_children)
460 {
461         synfigapp::ValueDesc value_desc=row[model.value_desc];
462
463         if(value_desc)
464         {
465                 if((bool)row[model.is_value_node] != value_desc.is_value_node() ||
466                         (!bool(row[model.is_value_node]) && row[model.link_count]!=0))
467                 {
468                         set_row(row,value_desc,do_children);
469                         return;
470                 }
471
472                 if(row[model.is_value_node])
473                 {
474                         ValueNode::Handle value_node(value_desc.get_value_node());
475
476                         if(ValueNode::Handle(row[model.value_node])!=value_node)
477                         {
478                                 rebuild_row(row,do_children);
479                                 return;
480                         }
481
482                         //row[model.id]=value_node->get_id();
483
484                         // Setup the row's label
485                         /*
486                         if(value_node->get_id().empty())
487                                 row[model.label] = Glib::ustring(row[model.name]);
488                         else if(Glib::ustring(row[model.name]).empty())
489                                 row[model.label] = value_node->get_id();
490                         else
491                                 row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
492                         */
493
494                         LinkableValueNode::Handle linkable;
495                         linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
496                         if(do_children && linkable && ((int)row[model.link_count] != linkable->link_count()))
497                         {
498         //                      Gtk::TreeModel::Children children = row.children();
499         //                      while(!children.empty() && erase(children.begin()));
500
501                                 set_row(row,value_desc);
502                                 return;
503                         }
504                 }
505                 else
506                 {
507                         //row[model.label] = Glib::ustring(row[model.name]);
508                         //row[model.is_value_node] = false;
509                         //row[model.is_editable] = true;
510                 }
511         }
512         if(!do_children)
513                 return;
514
515         Gtk::TreeModel::Children children = row.children();
516         Gtk::TreeModel::Children::iterator iter;
517
518         if(!children.empty())
519         for(iter = children.begin(); iter != children.end(); ++iter)
520         {
521                 Gtk::TreeRow row=*iter;
522                 refresh_row(row);
523         }
524 }
525
526 void
527 CanvasTreeStore::rebuild_row(Gtk::TreeModel::Row &row, bool do_children)
528 {
529         synfigapp::ValueDesc value_desc=(synfigapp::ValueDesc)row[model.value_desc];
530
531         if(value_desc && value_desc.get_value_node())
532         {
533                 ValueNode::Handle value_node;
534                 value_node=value_desc.get_value_node();
535
536                 assert(value_node);if(!value_node)return;
537
538                 if(value_node && value_node!=(ValueNode::Handle)row[model.value_node])
539                 {
540 //                      Gtk::TreeModel::Children children = row.children();
541 //                      while(!children.empty() && erase(children.begin()));
542
543                         set_row(row,value_desc,do_children);
544                         return;
545                 }
546
547                 LinkableValueNode::Handle linkable;
548                 linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
549
550                 if( do_children && linkable && (int)row[model.link_count] != linkable->link_count())
551                 {
552 //                      Gtk::TreeModel::Children children = row.children();
553 //                      while(!children.empty() && erase(children.begin()));
554
555                         set_row(row,value_desc);
556                         return;
557                 }
558
559                 //if(!value_node)
560                 //      value_node=row[model.value_node];
561
562                 row[model.id]=value_node->get_id();
563
564                 // Setup the row's label
565                 if(value_node->get_id().empty())
566                         row[model.label] = Glib::ustring(row[model.name]);
567                 else if(Glib::ustring(row[model.name]).empty())
568                         row[model.label] = value_node->get_id();
569                 else
570                         row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
571         }
572         else
573         {
574                 row[model.label] = Glib::ustring(row[model.name]);
575                 row[model.is_value_node] = false;
576                 row[model.is_editable] = true;
577                 Gtk::TreeModel::Children children = row.children();
578                 while(!children.empty() && erase(children.begin()))
579                         ;
580         }
581         if(!do_children)
582                 return;
583
584         Gtk::TreeModel::Children children = row.children();
585         Gtk::TreeModel::Children::iterator iter;
586         if(!children.empty())
587         for(iter = children.begin(); iter != children.end(); ++iter)
588         {
589                 Gtk::TreeRow row=*iter;
590                 rebuild_row(row);
591         }
592 }
593
594 CellRenderer_ValueBase*
595 CanvasTreeStore::add_cell_renderer_value(Gtk::TreeView::Column* column)
596 {
597         const CanvasTreeStore::Model model;
598
599         CellRenderer_ValueBase* ret;
600
601         ret=Gtk::manage( new CellRenderer_ValueBase() );
602
603         column->pack_start(*ret,true);
604         column->add_attribute(ret->property_value(), model.value);
605         column->add_attribute(ret->property_editable(), model.is_editable);
606         column->add_attribute(ret->property_canvas(), model.canvas);
607
608         return ret;
609 }
610
611 CellRenderer_TimeTrack*
612 CanvasTreeStore::add_cell_renderer_value_node(Gtk::TreeView::Column* column)
613 {
614         const CanvasTreeStore::Model model;
615
616         CellRenderer_TimeTrack* ret;
617
618         ret = Gtk::manage( new CellRenderer_TimeTrack() );
619
620         column->pack_start(*ret,true);
621         //column->add_attribute(ret->property_visible(), model.is_value_node);
622         column->add_attribute(ret->property_value_desc(), model.value_desc);
623         column->add_attribute(ret->property_canvas(), model.canvas);
624
625
626         return ret;
627 }