1 /* === S Y N F I G ========================================================= */
2 /*! \file canvastreestore.cpp
3 ** \brief Canvas tree store
4 **
5 ** $Id$
6 **
7 ** \legal
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2008 Chris Moore
10 ** Copyright (c) 2011 Carlos López
11 ** Copyright (c) 2016 caryoscelus
12 **
13 ** This package is free software; you can redistribute it and/or
14 ** modify it under the terms of the GNU General Public License as
15 ** published by the Free Software Foundation; either version 2 of
16 ** the License, or (at your option) any later version.
17 **
18 ** This package is distributed in the hope that it will be useful,
19 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 ** General Public License for more details.
22 ** \endlegal
23 */
24 /* ========================================================================= */
25
26 /* === H E A D E R S ======================================================= */
27
28 #ifdef USING_PCH
29 # include "pch.h"
30 #else
31 #ifdef HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #include <synfig/general.h>
36
37 #include "trees/canvastreestore.h"
38 #include <synfig/valuenode.h>
39 #include "iconcontroller.h"
40 #include <synfig/valuenodes/valuenode_timedswap.h>
41 #include <synfig/valuenodes/valuenode_bone.h>
42 #include <synfig/boneweightpair.h>
43 #include <synfig/valuenodes/valuenode_animated.h>
44 #include <gtkmm/button.h>
45 #include <synfigapp/instance.h>
46 #include "cellrenderer/cellrenderer_value.h"
47 #include "cellrenderer/cellrenderer_timetrack.h"
48 #include <ETL/clock>
49 #include <synfig/interpolation.h>
50
51 #include <gui/localization.h>
52
53 #endif
54
55 /* === U S I N G =========================================================== */
56
57 using namespace std;
58 using namespace etl;
59 using namespace synfig;
60 using namespace studio;
61
62 /* === M A C R O S ========================================================= */
63
64 /* === G L O B A L S ======================================================= */
65
66 /* === P R O C E D U R E S ================================================= */
67
68 /* === M E T H O D S ======================================================= */
69
ModelHack()70 static CanvasTreeStore::Model& ModelHack()
71 {
72 static CanvasTreeStore::Model* model(0);
73 if(!model)model=new CanvasTreeStore::Model;
74 return *model;
75 }
76
CanvasTreeStore(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_)77 CanvasTreeStore::CanvasTreeStore(etl::loose_handle<synfigapp::CanvasInterface> canvas_interface_):
78 Gtk::TreeStore(ModelHack()),
79 canvas_interface_ (canvas_interface_)
80 {
81 }
82
~CanvasTreeStore()83 CanvasTreeStore::~CanvasTreeStore()
84 {
85 }
86
87 ValueNode::Handle
expandable_bone_parent(ValueNode::Handle node)88 CanvasTreeStore::expandable_bone_parent(ValueNode::Handle node)
89 {
90 if ((!getenv("SYNFIG_DISABLE_EXPANDABLE_BONE_PARENTS")) &&
91 node->get_type() == type_bone_valuenode &&
92 (node->get_name() == "constant" || node->get_name() == "animated"))
93 if (ValueNode::Handle bone_node = (*node)(canvas_interface()->get_time()).get(ValueNode_Bone::Handle()))
94 return bone_node;
95 return node;
96 }
97
98 void
get_value_vfunc(const Gtk::TreeModel::iterator & iter,int column,Glib::ValueBase & value) const99 CanvasTreeStore::get_value_vfunc(const Gtk::TreeModel::iterator& iter, int column, Glib::ValueBase& value)const
100 {
101 if(column==model.value.index())
102 {
103 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
104
105 Glib::Value<synfig::ValueBase> x;
106 g_value_init(x.gobj(),x.value_type());
107
108 if(!value_desc)
109 {
110 x.set(ValueBase());
111 }
112 else
113 if(value_desc.is_const())
114 x.set(value_desc.get_value());
115 else
116 if(value_desc.is_value_node())
117 {
118 Type &type(value_desc.get_value_type());
119 if (type == type_bone_object)
120 {
121 Time time(canvas_interface()->get_time());
122 Bone bone((*(value_desc.get_value_node()))(time).get(Bone()));
123 String display(String(bone.get_name()));
124 ValueNode_Bone::ConstHandle parent(bone.get_parent());
125 if (!parent->is_root())
126 display += " --> " + String((*parent->get_link("name"))(time).get(String()));
127 x.set(display);
128 }
129 else
130 if (type == type_bone_weight_pair)
131 {
132 Time time(canvas_interface()->get_time());
133 BoneWeightPair bone_weight_pair((*(value_desc.get_value_node()))(time).get(BoneWeightPair()));
134 x.set(bone_weight_pair.get_string());
135 }
136 else
137 if (type == type_segment
138 || type == type_list
139 || type == type_bline_point)
140 {
141 x.set(value_desc.get_value_type().description.local_name);
142 }
143 else
144 {
145 x.set((*value_desc.get_value_node())(canvas_interface()->get_time()));
146 }
147 }
148 else
149 {
150 synfig::error(__FILE__":%d: Unable to figure out value",__LINE__);
151 return;
152 }
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.is_value_node.index())
159 {
160 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
161
162 Glib::Value<bool> x;
163 g_value_init(x.gobj(),x.value_type());
164
165 x.set(value_desc && value_desc.is_value_node());
166
167 g_value_init(value.gobj(),x.value_type());
168 g_value_copy(x.gobj(),value.gobj());
169 }
170 else
171 if(column==model.is_shared.index())
172 {
173 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
174
175 Glib::Value<bool> x;
176 g_value_init(x.gobj(),x.value_type());
177
178 x.set(value_desc.is_value_node() && value_desc.get_value_node()->rcount()>1);
179
180 g_value_init(value.gobj(),x.value_type());
181 g_value_copy(x.gobj(),value.gobj());
182 }
183 else
184 if(column==model.is_exported.index())
185 {
186 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
187
188 Glib::Value<bool> x;
189 g_value_init(x.gobj(),x.value_type());
190
191 x.set(value_desc.is_value_node() && value_desc.get_value_node()->is_exported());
192
193 g_value_init(value.gobj(),x.value_type());
194 g_value_copy(x.gobj(),value.gobj());
195 }
196 else
197 if(column==model.is_canvas.index())
198 {
199 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
200
201 Glib::Value<bool> x;
202 g_value_init(x.gobj(),x.value_type());
203
204 x.set(!value_desc && (Canvas::Handle)(*iter)[model.canvas]);
205
206 g_value_init(value.gobj(),x.value_type());
207 g_value_copy(x.gobj(),value.gobj());
208 }
209 else
210 if(column==model.id.index())
211 {
212 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
213
214 Glib::Value<Glib::ustring> x;
215 g_value_init(x.gobj(),x.value_type());
216
217 if(value_desc && value_desc.is_value_node())
218 x.set(value_desc.get_value_node()->get_id());
219 else if(!value_desc && Canvas::Handle((*iter)[model.canvas]))
220 x.set(Canvas::Handle((*iter)[model.canvas])->get_id());
221 else
222 return Gtk::TreeStore::get_value_vfunc(iter,column,value);
223
224 g_value_init(value.gobj(),x.value_type());
225 g_value_copy(x.gobj(),value.gobj());
226 }
227 else
228 if(column==model.is_editable.index())
229 {
230 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
231
232 Glib::Value<bool> x;
233 g_value_init(x.gobj(),x.value_type());
234
235 x.set(
236 // Temporary fix crash when trying to edit bline point
237 // https://github.com/synfig/synfig/issues/264
238 // TODO: move this check into a more proper place
239 value_desc.get_value_type() != type_bline_point
240 && value_desc.get_value_type() != type_width_point
241 && value_desc.get_value_type() != type_dash_item
242 && (
243 !value_desc.is_value_node()
244 || synfigapp::is_editable(value_desc.get_value_node())
245 )
246 );
247
248 g_value_init(value.gobj(),x.value_type());
249 g_value_copy(x.gobj(),value.gobj());
250 }
251 else
252 if(column==model.type.index())
253 {
254 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
255 String stype, lname;
256
257 Glib::Value<Glib::ustring> x;
258 g_value_init(x.gobj(),x.value_type());
259
260 // Set the type
261 if(!value_desc)
262 {
263 if((*iter)[model.is_canvas])
264 x.set(_("Canvas"));
265 }
266 else
267 {
268 stype=value_desc.get_value_type().description.local_name;
269 if(!value_desc.is_const())
270 stype+=" (" + value_desc.get_value_node()->get_local_name() + ")";
271 }
272 x.set(stype.c_str());
273 g_value_init(value.gobj(),x.value_type());
274 g_value_copy(x.gobj(),value.gobj());
275 }
276 else
277 if(column==model.label.index())
278 {
279 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
280
281 Glib::Value<Glib::ustring> x;
282 g_value_init(x.gobj(),x.value_type());
283
284 // Set the type
285 if(!value_desc)
286 {
287 Canvas::Handle canvas((*iter)[model.canvas]);
288 if(canvas)
289 {
290 if(!canvas->get_id().empty())
291 x.set(canvas->get_id());
292 else if(!canvas->get_name().empty())
293 x.set(canvas->get_name());
294 else
295 x.set(_("[Unnamed]"));
296 // todo: what are the previous 6 lines for if we're going to overwrite it here?
297 x.set(_("Canvas"));
298 }
299 return Gtk::TreeStore::get_value_vfunc(iter,column,value);
300 }
301 else
302 {
303 ValueNode::Handle value_node=value_desc.get_value_node();
304
305 // Setup the row's label
306 if(value_node->get_id().empty())
307 x.set(Glib::ustring((*iter)[model.name]));
308 else if(Glib::ustring((*iter)[model.name]).empty())
309 x.set(value_node->get_id());
310 else
311 x.set(Glib::ustring((*iter)[model.name])+" ("+value_node->get_id()+')');
312 }
313
314 g_value_init(value.gobj(),x.value_type());
315 g_value_copy(x.gobj(),value.gobj());
316 }
317 else
318 if(column==model.icon.index())
319 {
320 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
321 if(!value_desc)
322 return Gtk::TreeStore::get_value_vfunc(iter,column,value);
323
324 Glib::Value<Glib::RefPtr<Gdk::Pixbuf> > x;
325 g_value_init(x.gobj(),x.value_type());
326
327 x.set(get_tree_pixbuf(value_desc.get_value_type()));
328
329 g_value_init(value.gobj(),x.value_type());
330 g_value_copy(x.gobj(),value.gobj());
331 }
332 else
333 if(column==model.interpolation_icon.index())
334 {
335 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
336 if(!value_desc)
337 return Gtk::TreeStore::get_value_vfunc(iter,column,value);
338
339 Glib::Value<Glib::RefPtr<Gdk::Pixbuf> > x;
340 g_value_init(x.gobj(),x.value_type());
341
342 x.set(get_interpolation_pixbuf(value_desc.get_interpolation()));
343
344 g_value_init(value.gobj(),x.value_type());
345 g_value_copy(x.gobj(),value.gobj());
346
347 }
348 else
349 if(column==model.is_static.index())
350 {
351 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
352
353 Glib::Value<bool> x;
354 g_value_init(x.gobj(),x.value_type());
355
356 x.set(value_desc.get_static());
357
358 g_value_init(value.gobj(),x.value_type());
359 g_value_copy(x.gobj(),value.gobj());
360 }
361 else
362 if(column==model.interpolation_icon_visible.index())
363 {
364 synfigapp::ValueDesc value_desc((*iter)[model.value_desc]);
365
366 Glib::Value<bool> x;
367 g_value_init(x.gobj(),x.value_type());
368
369 bool is_visible((!value_desc.get_static())
370 && (value_desc.get_interpolation()!=INTERPOLATION_UNDEFINED)
371 && (value_desc.get_interpolation()!=INTERPOLATION_MANUAL)
372 && (value_desc.get_interpolation()!=INTERPOLATION_NIL));
373 x.set(is_visible);
374 g_value_init(value.gobj(),x.value_type());
375 g_value_copy(x.gobj(),value.gobj());
376 }
377 else
378 Gtk::TreeStore::get_value_vfunc(iter,column,value);
379 }
380
381 bool
find_first_value_desc(const synfigapp::ValueDesc & value_desc,Gtk::TreeIter & iter)382 CanvasTreeStore::find_first_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter)
383 {
384 iter=children().begin();
385 while(iter && value_desc!=(*iter)[model.value_desc])
386 {
387 if(!iter->children().empty())
388 {
389 Gtk::TreeIter iter2(iter->children().begin());
390 //! \todo confirm that the && should be done before the ||
391 if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2))
392 {
393 iter=iter2;
394 return true;
395 }
396 }
397 Gtk::TreeIter iter2(++iter);
398 if(!iter2)
399 iter=iter->parent();
400 else
401 iter=iter2;
402 }
403 return (bool)iter && value_desc==(*iter)[model.value_desc];
404 }
405
406 bool
find_next_value_desc(const synfigapp::ValueDesc & value_desc,Gtk::TreeIter & iter)407 CanvasTreeStore::find_next_value_desc(const synfigapp::ValueDesc& value_desc, Gtk::TreeIter& iter)
408 {
409 if(!iter) return find_first_value_desc(value_desc,iter);
410
411 if(iter) do {
412 if(!iter->children().empty())
413 {
414 Gtk::TreeIter iter2(iter->children().begin());
415 //! \todo confirm that the && should be done before the ||
416 if((iter2 && value_desc==(*iter2)[model.value_desc]) || find_next_value_desc(value_desc, iter2))
417 {
418 iter=iter2;
419 return true;
420 }
421 }
422 Gtk::TreeIter iter2(++iter);
423 if(!iter2)
424 {
425 iter=iter->parent();
426 if(iter)++iter;
427 }
428 else
429 iter=iter2;
430 } while(iter && value_desc!=(*iter)[model.value_desc]);
431 return (bool)iter && value_desc==(*iter)[model.value_desc];
432 }
433
434 bool
find_first_value_node(const synfig::ValueNode::Handle & value_node,Gtk::TreeIter & iter)435 CanvasTreeStore::find_first_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
436 {
437 // maybe replace the ValueNode_Const or ValueNode_Animated with the contained ValueNode_Bone
438 // todo: do we need to do this in find_next_value_node, and find_*_value_desc too?
439 synfig::ValueNode::Handle node(expandable_bone_parent(value_node));
440
441 iter=children().begin();
442 while(iter && node!=(ValueNode::Handle)(*iter)[model.value_node])
443 {
444 if(!iter->children().empty())
445 {
446 Gtk::TreeIter iter2(iter->children().begin());
447 //! \todo confirm that the && should be done before the ||
448 if((iter2 && node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(node, iter2))
449 {
450 iter=iter2;
451 return true;
452 }
453 }
454 Gtk::TreeIter iter2(++iter);
455 if(!iter2)
456 iter=iter->parent();
457 else
458 iter=iter2;
459 }
460 return (bool)iter && node==(ValueNode::Handle)(*iter)[model.value_node];
461 }
462
463 bool
find_next_value_node(const synfig::ValueNode::Handle & value_node,Gtk::TreeIter & iter)464 CanvasTreeStore::find_next_value_node(const synfig::ValueNode::Handle& value_node, Gtk::TreeIter& iter)
465 {
466 if(!iter) return find_first_value_node(value_node,iter);
467
468 if(iter) do {
469 if(!iter->children().empty())
470 {
471 Gtk::TreeIter iter2(iter->children().begin());
472 //! \todo confirm that the && should be done before the ||
473 if((iter2 && value_node==(ValueNode::Handle)(*iter2)[model.value_node]) || find_next_value_node(value_node, iter2))
474 {
475 iter=iter2;
476 return true;
477 }
478 }
479 Gtk::TreeIter iter2(++iter);
480 if(!iter2)
481 {
482 iter=iter->parent();
483 if(iter)++iter;
484 }
485 else
486 iter=iter2;
487 } while(iter && value_node!=(ValueNode::Handle)(*iter)[model.value_node]);
488 return (bool)iter && value_node==(ValueNode::Handle)(*iter)[model.value_node];
489 }
490
491 void
set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc,bool do_children)492 CanvasTreeStore::set_row(Gtk::TreeRow row,synfigapp::ValueDesc value_desc, bool do_children)
493 {
494 Gtk::TreeModel::Children children = row.children();
495 while(!children.empty() && erase(children.begin()))
496 ;
497
498 row[model.value_desc]=value_desc;
499 try
500 {
501 //row[model.icon] = get_tree_pixbuf(value_desc.get_value_type());
502
503 if(value_desc.is_value_node())
504 {
505 ValueNode::Handle value_node=value_desc.get_value_node();
506
507 // todo: if the parent is animated and expanded, and we drag the time slider so that it changes,
508 // it's not updated. it still shows the previous bone valuenode.
509
510 // maybe replace the ValueNode_Const or ValueNode_Animated with the contained ValueNode_Bone
511 value_node = expandable_bone_parent(value_node);
512
513 assert(value_node);
514
515 row[model.value_node] = value_node;
516 //row[model.is_canvas] = false;
517 //row[model.is_value_node] = true;
518 //row[model.is_editable] = synfigapp::is_editable(value_node);
519 //row[model.id]=value_node->get_id();
520
521 // Set the canvas
522 if(value_desc.parent_is_canvas())
523 row[model.canvas]=value_desc.get_canvas();
524 else
525 row[model.canvas]=canvas_interface()->get_canvas();
526
527 LinkableValueNode::Handle linkable;
528 // printf("%s:%d value_node = %s\n", __FILE__, __LINE__, value_node->get_description().c_str());
529 linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
530
531 // printf("linkable: %d; do_children: %d\n", bool(linkable), bool(do_children));
532 if(linkable && do_children)
533 {
534 row[model.link_count] = linkable->link_count();
535 LinkableValueNode::Vocab vocab(linkable->get_children_vocab());
536 LinkableValueNode::Vocab::iterator iter(vocab.begin());
537 for(int i=0;i<linkable->link_count();i++, iter++)
538 {
539 if(iter->get_hidden())
540 continue;
541 Gtk::TreeRow child_row=*(append(row.children()));
542 child_row[model.link_id] = i;
543 child_row[model.canvas] = static_cast<Canvas::Handle>(row[model.canvas]);
544 child_row[model.name] = linkable->link_local_name(i);
545 child_row[model.tooltip] = iter->get_description();
546 child_row[model.child_param_desc] = *iter;
547 set_row(child_row,synfigapp::ValueDesc(linkable,i));
548 }
549 }
550 return;
551 }
552 else
553 {
554 //row[model.is_value_node] = false;
555 //row[model.is_editable] = true;
556 //row[model.label] = Glib::ustring(row[model.name]);
557 return;
558 }
559 }
560 catch(synfig::Exception::IDNotFound x)
561 {
562 synfig::error(__FILE__":%d: IDNotFound thrown",__LINE__);
563 erase(row);
564 return;
565 }
566
567 // We should never get to this point
568 assert(0);
569 }
570
571 void
refresh_row(Gtk::TreeModel::Row & row,bool do_children)572 CanvasTreeStore::refresh_row(Gtk::TreeModel::Row &row, bool do_children)
573 {
574 synfigapp::ValueDesc value_desc=row[model.value_desc];
575
576 if(value_desc)
577 {
578 if((bool)row[model.is_value_node] != value_desc.is_value_node() ||
579 (!bool(row[model.is_value_node]) && row[model.link_count]!=0))
580 {
581 set_row(row,value_desc,do_children);
582 return;
583 }
584
585 if(row[model.is_value_node])
586 {
587 ValueNode::Handle value_node(value_desc.get_value_node());
588
589 if(ValueNode::Handle(row[model.value_node])!=value_node)
590 {
591 rebuild_row(row,do_children);
592 return;
593 }
594
595 //row[model.id]=value_node->get_id();
596
597 // Setup the row's label
598 /*
599 if(value_node->get_id().empty())
600 row[model.label] = Glib::ustring(row[model.name]);
601 else if(Glib::ustring(row[model.name]).empty())
602 row[model.label] = value_node->get_id();
603 else
604 row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
605 */
606
607 LinkableValueNode::Handle linkable;
608 linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
609 if(do_children && linkable && ((int)row[model.link_count] != linkable->link_count()))
610 {
611 // Gtk::TreeModel::Children children = row.children();
612 // while(!children.empty() && erase(children.begin()));
613
614 set_row(row,value_desc);
615 return;
616 }
617 }
618 else
619 {
620 //row[model.label] = Glib::ustring(row[model.name]);
621 //row[model.is_value_node] = false;
622 //row[model.is_editable] = true;
623 }
624 }
625 if(!do_children)
626 return;
627
628 Gtk::TreeModel::Children children = row.children();
629 Gtk::TreeModel::Children::iterator iter;
630
631 if(!children.empty())
632 for(iter = children.begin(); iter != children.end(); ++iter)
633 {
634 Gtk::TreeRow row=*iter;
635 refresh_row(row);
636 }
637 }
638
639 void
rebuild_row(Gtk::TreeModel::Row & row,bool do_children)640 CanvasTreeStore::rebuild_row(Gtk::TreeModel::Row &row, bool do_children)
641 {
642 synfigapp::ValueDesc value_desc=(synfigapp::ValueDesc)row[model.value_desc];
643
644 if(value_desc && value_desc.get_value_node())
645 {
646 ValueNode::Handle value_node;
647 value_node=value_desc.get_value_node();
648
649 assert(value_node);if(!value_node)return;
650
651 if(value_node && value_node!=(ValueNode::Handle)row[model.value_node])
652 {
653 // Gtk::TreeModel::Children children = row.children();
654 // while(!children.empty() && erase(children.begin()));
655
656 set_row(row,value_desc,do_children);
657 return;
658 }
659
660 LinkableValueNode::Handle linkable;
661 linkable=LinkableValueNode::Handle::cast_dynamic(value_node);
662
663 if( do_children && linkable && (int)row[model.link_count] != linkable->link_count())
664 {
665 // Gtk::TreeModel::Children children = row.children();
666 // while(!children.empty() && erase(children.begin()));
667
668 set_row(row,value_desc);
669 return;
670 }
671
672 //if(!value_node)
673 // value_node=row[model.value_node];
674
675 row[model.id]=value_node->get_id();
676
677 // Setup the row's label
678 if(value_node->get_id().empty())
679 row[model.label] = Glib::ustring(row[model.name]);
680 else if(Glib::ustring(row[model.name]).empty())
681 row[model.label] = value_node->get_id();
682 else
683 row[model.label] = Glib::ustring(row[model.name])+" ("+value_node->get_id()+')';
684 }
685 else
686 {
687 row[model.label] = Glib::ustring(row[model.name]);
688 row[model.is_value_node] = false;
689 row[model.is_editable] = true;
690 Gtk::TreeModel::Children children = row.children();
691 while(!children.empty() && erase(children.begin()))
692 ;
693 }
694 if(!do_children)
695 return;
696
697 Gtk::TreeModel::Children children = row.children();
698 Gtk::TreeModel::Children::iterator iter;
699 if(!children.empty())
700 for(iter = children.begin(); iter != children.end(); ++iter)
701 {
702 Gtk::TreeRow row=*iter;
703 rebuild_row(row);
704 }
705 }
706
707 CellRenderer_ValueBase*
add_cell_renderer_value(Gtk::TreeView::Column * column)708 CanvasTreeStore::add_cell_renderer_value(Gtk::TreeView::Column* column)
709 {
710 const CanvasTreeStore::Model model;
711
712 CellRenderer_ValueBase* ret;
713
714 ret=Gtk::manage( new CellRenderer_ValueBase() );
715
716 column->pack_start(*ret,true);
717 column->add_attribute(ret->property_value(), model.value);
718 column->add_attribute(ret->property_editable(), model.is_editable);
719 column->add_attribute(ret->property_canvas(), model.canvas);
720
721 return ret;
722 }
723
724 CellRenderer_TimeTrack*
add_cell_renderer_value_node(Gtk::TreeView::Column * column)725 CanvasTreeStore::add_cell_renderer_value_node(Gtk::TreeView::Column* column)
726 {
727 const CanvasTreeStore::Model model;
728
729 CellRenderer_TimeTrack* ret;
730
731 ret = Gtk::manage( new CellRenderer_TimeTrack() );
732
733 column->pack_start(*ret,true);
734 //column->add_attribute(ret->property_visible(), model.is_value_node);
735 column->add_attribute(ret->property_value_desc(), model.value_desc);
736 column->add_attribute(ret->property_canvas(), model.canvas);
737
738
739 return ret;
740 }
741