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