initial version
[synfig.git] / synfig-studio / trunk / src / gtkmm / dock_timetrack.cpp
1 /* === S I N F G =========================================================== */
2 /*!     \file dock_timetrack.cpp
3 **      \brief Template File
4 **
5 **      $Id: dock_timetrack.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #ifdef USING_PCH
25 #       include "pch.h"
26 #else
27 #ifdef HAVE_CONFIG_H
28 #       include <config.h>
29 #endif
30
31 #include "dock_timetrack.h"
32 #include "app.h"
33
34 #include <gtkmm/scrolledwindow.h>
35 #include <cassert>
36 #include "instance.h"
37 #include <sigc++/signal.h>
38 #include <sigc++/hide.h>
39 #include <sigc++/slot.h>
40 #include "canvasview.h"
41 #include "layerparamtreestore.h"
42 #include "workarea.h"
43 #include "widget_timeslider.h"
44 #include "layerparamtreestore.h"
45 #endif
46
47 /* === U S I N G =========================================================== */
48
49 using namespace std;
50 using namespace etl;
51 using namespace sinfg;
52 using namespace studio;
53
54 /* === M A C R O S ========================================================= */
55
56 /* === C L A S S E S ======================================================= */
57
58 class TimeTrackView : public Gtk::TreeView
59 {
60         CellRenderer_TimeTrack *cellrenderer_time_track;
61
62         Glib::RefPtr<LayerParamTreeStore> param_tree_store_;
63         
64         Gtk::TreeView *mimic_tree_view; 
65 public:
66
67         sigc::signal<void,sinfgapp::ValueDesc,sinfg::Waypoint,int> signal_waypoint_clicked;
68
69         LayerParamTreeStore::Model model;
70
71         void set_canvas_view(handle<CanvasView> canvas_view)
72         {
73                 cellrenderer_time_track->set_adjustment(canvas_view->time_adjustment());
74         }
75
76         TimeTrackView()
77         {
78                 int label_index(append_column_editable(_("Name"),model.label));
79                 Gtk::TreeView::Column* label_column = get_column(label_index-1);
80         
81                 {       // --- T I M E   T R A C K --------------------------------------------
82                         Gtk::TreeView::Column* column = Gtk::manage( new Gtk::TreeView::Column(_("Time Track")) );
83                         
84                         // Set up the value-node cell-renderer
85                         cellrenderer_time_track=LayerParamTreeStore::add_cell_renderer_value_node(column);
86                         cellrenderer_time_track->property_mode()=Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
87                         cellrenderer_time_track->signal_waypoint_clicked().connect(sigc::mem_fun(*this, &TimeTrackView::on_waypoint_clicked) );
88                         cellrenderer_time_track->signal_waypoint_changed().connect(sigc::mem_fun(*this, &TimeTrackView::on_waypoint_changed) );
89                         column->add_attribute(cellrenderer_time_track->property_value_desc(), model.value_desc);
90                         column->add_attribute(cellrenderer_time_track->property_canvas(), model.canvas);
91                         //column->add_attribute(cellrenderer_time_track->property_visible(), model.is_value_node);
92         
93                         //column->pack_start(*cellrenderer_time_track);
94                                         
95                         // Finish setting up the column
96                         column->set_reorderable();
97                         column->set_resizable();
98                         column->set_min_width(200);
99
100         
101                         append_column(*column);
102                 }
103                 set_rules_hint();
104         
105                 set_expander_column(*label_column);
106                 label_column->set_visible(false);
107                 set_headers_visible(false);
108                 set_size_request(-1,64);
109         }
110
111         bool
112         on_event(GdkEvent *event)
113         {
114                 switch(event->type)
115                 {
116                 case GDK_SCROLL:
117                         if(mimic_tree_view)
118                         {
119                                 if(event->scroll.direction==GDK_SCROLL_DOWN)
120                                 {
121                                         mimic_tree_view->get_vadjustment()->set_value(
122                                                 std::min(
123                                                         mimic_tree_view->get_vadjustment()->get_value()+
124                                                         mimic_tree_view->get_vadjustment()->get_step_increment(),
125                                                         mimic_tree_view->get_vadjustment()->get_upper()-
126                                                         mimic_tree_view->get_vadjustment()->get_page_size()
127                                                 )
128                                         );
129                                         mimic_tree_view->get_vadjustment()->value_changed();
130                                 }
131                                 else if(event->scroll.direction==GDK_SCROLL_UP)
132                                 {
133                                         mimic_tree_view->get_vadjustment()->set_value(
134                                                 std::max(
135                                                         mimic_tree_view->get_vadjustment()->get_value()-
136                                                         mimic_tree_view->get_vadjustment()->get_step_increment(),
137                                                         mimic_tree_view->get_vadjustment()->get_lower()                                 
138                                                 )
139                                         );
140                                         mimic_tree_view->get_vadjustment()->value_changed();
141                                 }
142                         }
143                         break;
144                 case GDK_BUTTON_PRESS:
145                         {
146                                 Gtk::TreeModel::Path path;
147                                 Gtk::TreeViewColumn *column;
148                                 int cell_x, cell_y;
149                                 if(!get_path_at_pos(
150                                         int(event->button.x),int(event->button.y),      // x, y
151                                         path, // TreeModel::Path&
152                                         column, //TreeViewColumn*&
153                                         cell_x,cell_y //int&cell_x,int&cell_y
154                                         )
155                                 ) break;
156                                 const Gtk::TreeRow row = *(get_model()->get_iter(path));
157                                 
158                                 if(column && column->get_first_cell_renderer()==cellrenderer_time_track)
159                                 {
160                                         Gdk::Rectangle rect;
161                                         get_cell_area(path,*column,rect);
162                                         cellrenderer_time_track->property_value_desc()=row[model.value_desc];
163                                         cellrenderer_time_track->property_canvas()=row[model.canvas];
164                                         cellrenderer_time_track->activate(event,*this,path.to_string(),rect,rect,Gtk::CellRendererState());
165                                         queue_draw_area(rect.get_x(),rect.get_y(),rect.get_width(),rect.get_height());
166                                         return true;
167                                         //return signal_param_user_click()(event->button.button,row,COLUMNID_TIME_TRACK);
168                                 }
169 /*                              else 
170                                 {
171                                         if(event->button.button==3)
172                                         {
173                                                 LayerList layer_list(get_selected_layers());
174                                                 if(layer_list.size()<=1)
175                                                 {
176                                                         sinfgapp::ValueDesc value_desc(row[model.value_desc]);
177                                                         Gtk::Menu* menu(manage(new Gtk::Menu()));                                       
178                                                         App::get_instance(param_tree_store_->canvas_interface()->get_canvas())->make_param_menu(menu,param_tree_store_->canvas_interface()->get_canvas(),value_desc,0.5f);
179                                                         menu->popup(event->button.button,gtk_get_current_event_time());
180                                                         return true;
181                                                 }
182                                                 Gtk::Menu* menu(manage(new Gtk::Menu()));                                       
183                                                 std::list<sinfgapp::ValueDesc> value_desc_list;
184                                                 ParamDesc param_desc(row[model.param_desc]);
185                                                 for(;!layer_list.empty();layer_list.pop_back())
186                                                         value_desc_list.push_back(sinfgapp::ValueDesc(layer_list.back(),param_desc.get_name()));
187                                                 App::get_instance(param_tree_store_->canvas_interface()->get_canvas())->make_param_menu(menu,param_tree_store_->canvas_interface()->get_canvas(),value_desc_list);
188                                                 menu->popup(event->button.button,gtk_get_current_event_time());
189                                                 return true;
190                                         }
191                                         else
192                                         {
193                                                 if(column->get_first_cell_renderer()==cellrenderer_value)
194                                                         return signal_param_user_click()(event->button.button,row,COLUMNID_VALUE);
195                                                 else
196                                                         return signal_param_user_click()(event->button.button,row,COLUMNID_NAME);
197                                         }
198                                 }
199                                 */
200                         }
201                         break;
202                         
203                 case GDK_MOTION_NOTIFY:
204                         {
205                                 Gtk::TreeModel::Path path;
206                                 Gtk::TreeViewColumn *column;
207                                 int cell_x, cell_y;
208                                 if(!get_path_at_pos(
209                                         (int)event->motion.x,(int)event->motion.y,      // x, y
210                                         path, // TreeModel::Path&
211                                         column, //TreeViewColumn*&
212                                         cell_x,cell_y //int&cell_x,int&cell_y
213                                         )
214                                 ) break;
215                                 
216                                 if(!get_model()->get_iter(path))
217                                         break;
218                                 
219                                 Gtk::TreeRow row = *(get_model()->get_iter(path));
220                                 
221                                 if((event->motion.state&GDK_BUTTON1_MASK ||event->motion.state&GDK_BUTTON3_MASK) && column && cellrenderer_time_track==column->get_first_cell_renderer())
222                                 {
223                                         Gdk::Rectangle rect;
224                                         get_cell_area(path,*column,rect);
225                                         cellrenderer_time_track->property_value_desc()=row[model.value_desc];
226                                         cellrenderer_time_track->property_canvas()=row[model.canvas];
227                                         cellrenderer_time_track->activate(event,*this,path.to_string(),rect,rect,Gtk::CellRendererState());
228                                         queue_draw();
229                                         //queue_draw_area(rect.get_x(),rect.get_y(),rect.get_width(),rect.get_height());
230                                         return true;
231                                 }
232 /*                              else
233                                 if(last_tooltip_path.get_depth()<=0 || path!=last_tooltip_path)
234                                 {
235                                         tooltips_.unset_tip(*this);
236                                         Glib::ustring tooltips_string(row[layer_model.tooltip]);
237                                         last_tooltip_path=path;
238                                         if(!tooltips_string.empty())
239                                         {
240                                                 tooltips_.set_tip(*this,tooltips_string);
241                                                 tooltips_.force_window();
242                                         }
243                                 }
244 */
245                                 return true;
246                         }
247                         break;
248                 case GDK_BUTTON_RELEASE:
249                         {
250                                 Gtk::TreeModel::Path path;
251                                 Gtk::TreeViewColumn *column;
252                                 int cell_x, cell_y;
253                                 if(!get_path_at_pos(
254                                         (int)event->button.x,(int)event->button.y,      // x, y
255                                         path, // TreeModel::Path&
256                                         column, //TreeViewColumn*&
257                                         cell_x,cell_y //int&cell_x,int&cell_y
258                                         )
259                                 ) break;
260                                 
261                                 if(!get_model()->get_iter(path))
262                                         break;
263                                 
264                                 Gtk::TreeRow row = *(get_model()->get_iter(path));
265                                 
266                                 if(column && cellrenderer_time_track==column->get_first_cell_renderer())
267                                 {
268                                         Gdk::Rectangle rect;
269                                         get_cell_area(path,*column,rect);
270                                         cellrenderer_time_track->property_value_desc()=row[model.value_desc];
271                                         cellrenderer_time_track->property_canvas()=row[model.canvas];
272                                         cellrenderer_time_track->activate(event,*this,path.to_string(),rect,rect,Gtk::CellRendererState());
273                                         queue_draw();
274                                         queue_draw_area(rect.get_x(),rect.get_y(),rect.get_width(),rect.get_height());
275                                         return true;
276                                 }
277                         }
278                         break;
279                 default:
280                         break;
281                 }
282                 mimic_resync();
283                 return Gtk::TreeView::on_event(event);
284         }
285
286         void
287         queue_draw_msg()
288         {
289                 sinfg::info("*************QUEUE_DRAW***************** (time track view)");
290                 Widget::queue_draw();
291         }
292         void set_model(Glib::RefPtr<LayerParamTreeStore> store)
293         {
294                 Gtk::TreeView::set_model(store);
295                 param_tree_store_=store;
296                 cellrenderer_time_track->set_canvas_interface(param_tree_store_->canvas_interface());
297                 store->signal_changed().connect(sigc::mem_fun(*this, &TimeTrackView::queue_draw));
298         }
299         
300         void
301         on_waypoint_changed( sinfg::Waypoint waypoint , sinfg::ValueNode::Handle value_node)
302         {
303                 sinfgapp::Action::ParamList param_list;
304                 param_list.add("canvas",param_tree_store_->canvas_interface()->get_canvas());
305                 param_list.add("canvas_interface",param_tree_store_->canvas_interface());
306                 param_list.add("value_node",value_node);
307                 param_list.add("waypoint",waypoint);
308         //      param_list.add("time",canvas_interface()->get_time());
309         
310                 etl::handle<studio::Instance>::cast_static(param_tree_store_->canvas_interface()->get_instance())->process_action("waypoint_set_smart", param_list);
311         }
312
313         void mimic(Gtk::TreeView *param_tree_view)
314         {       
315                 mimic_tree_view=param_tree_view;
316                 param_tree_view->signal_row_expanded().connect(
317                         sigc::hide<0>(
318                         sigc::hide_return(
319                                 sigc::bind<-1>(
320                                         sigc::mem_fun(
321                                                 *this,
322                                                 &Gtk::TreeView::expand_row
323                                         ),
324                                         false
325                                 )
326                         ))
327                 );
328                 param_tree_view->signal_row_collapsed().connect(
329                         sigc::hide<0>(
330                         sigc::hide_return(
331                                         sigc::mem_fun(
332                                                 *this,
333                                                 &Gtk::TreeView::collapse_row
334                                         )
335                         ))
336                 );
337                 mimic_resync();
338         }
339         
340         void mimic_resync()
341         {
342                 
343                 if(mimic_tree_view)
344                 {
345                         Gtk::Adjustment &adjustment(*mimic_tree_view->get_vadjustment());
346                         set_vadjustment(adjustment);
347                         
348                         if(adjustment.get_page_size()>get_height())
349                                 adjustment.set_page_size(get_height());
350                         
351                         cellrenderer_time_track->set_fixed_size(-1,18);
352                 }
353         }
354         
355         void
356         on_waypoint_clicked(const Glib::ustring &path_string, sinfg::Waypoint waypoint,int button)
357         {
358 /*
359                 Gtk::TreePath path(path_string);
360                 
361                 const Gtk::TreeRow row = *(get_model()->get_iter(path));
362                 if(!row)
363                         return;
364 */
365                 
366                 ValueNode::Handle value_node(waypoint.get_parent_value_node());
367                 assert(value_node);
368
369                 Gtk::TreeRow row;
370                 if(!param_tree_store_->find_first_value_node(value_node, row))
371                 {
372                         sinfg::error(__FILE__":%d: Unable to find the valuenode",__LINE__);
373                         return;
374                 }
375                 
376                 if(!row)
377                         return;
378                 
379                 sinfgapp::ValueDesc value_desc(static_cast<sinfgapp::ValueDesc>(row[model.value_desc]));
380
381                 signal_waypoint_clicked(value_desc,waypoint,button);
382         }
383 };
384
385 /* === G L O B A L S ======================================================= */
386
387 /* === P R O C E D U R E S ================================================= */
388
389 /* === M E T H O D S ======================================================= */
390
391 Dock_Timetrack::Dock_Timetrack():
392         Dock_CanvasSpecific("timetrack",_("Timetrack"),Gtk::StockID("sinfg-timetrack"))
393 {
394         table_=0;
395         widget_timeslider_= new Widget_Timeslider();
396         widget_timeslider_->set_size_request(-1,22);
397         hscrollbar_=new Gtk::HScrollbar();
398         vscrollbar_=new Gtk::VScrollbar();
399 }
400
401 Dock_Timetrack::~Dock_Timetrack()
402 {
403         if(table_)delete table_;
404         delete hscrollbar_;
405         delete vscrollbar_;
406         delete widget_timeslider_;
407 }
408
409 void
410 Dock_Timetrack::init_canvas_view_vfunc(etl::loose_handle<CanvasView> canvas_view)
411 {
412         LayerParamTreeStore::Model model;
413         
414         Glib::RefPtr<LayerParamTreeStore> tree_store(
415                 Glib::RefPtr<LayerParamTreeStore>::cast_dynamic(
416                         canvas_view->get_tree_model("params")
417                 )
418         );
419
420         TimeTrackView* tree_view(new TimeTrackView());
421         tree_view->set_canvas_view(canvas_view);
422         tree_view->set_model(tree_store);
423         Gtk::TreeView* param_tree_view(dynamic_cast<Gtk::TreeView*>(canvas_view->get_ext_widget("params")));
424         tree_view->mimic(param_tree_view);
425
426         tree_view->signal_waypoint_clicked.connect(sigc::mem_fun(*canvas_view, &studio::CanvasView::on_waypoint_clicked));
427
428         
429         canvas_view->time_adjustment().signal_value_changed().connect(sigc::mem_fun(*tree_view,&Gtk::TreeView::queue_draw));
430         canvas_view->time_adjustment().signal_changed().connect(sigc::mem_fun(*tree_view,&Gtk::TreeView::queue_draw));
431
432         canvas_view->set_ext_widget(get_name(),tree_view);
433 }
434
435 void
436 Dock_Timetrack::refresh_selected_param()
437 {
438 /*      Gtk::TreeView* tree_view(
439                 static_cast<Gtk::TreeView*>(get_canvas_view()->get_ext_widget(get_name()))
440         );
441         Gtk::TreeModel::iterator iter(tree_view->get_selection()->get_selected());
442         
443         if(iter)
444         {
445                 LayerParamTreeStore::Model model;
446                 get_canvas_view()->work_area->set_selected_value_node(
447                         (sinfg::ValueNode::Handle)(*iter)[model.value_node]
448                 );
449         }
450         else
451         {
452                 get_canvas_view()->work_area->set_selected_value_node(0);
453         }
454 */
455 }
456
457 void
458 Dock_Timetrack::changed_canvas_view_vfunc(etl::loose_handle<CanvasView> canvas_view)
459 {
460         if(table_)
461         {
462                 table_->hide();
463                 delete table_;
464                 hscrollbar_->unset_adjustment();
465                 vscrollbar_->unset_adjustment();
466                 //widget_timeslider_->unset_adjustment();
467                 table_=0;
468         }
469
470         
471         if(canvas_view)
472         {
473                 TimeTrackView* tree_view(dynamic_cast<TimeTrackView*>(canvas_view->get_ext_widget(get_name())));
474         Gtk::TreeView* param_tree_view(dynamic_cast<Gtk::TreeView*>(canvas_view->get_ext_widget("params")));
475         tree_view->set_vadjustment(*param_tree_view->get_vadjustment());
476                 
477                 assert(tree_view);
478
479                 widget_timeslider_->set_time_adjustment(&canvas_view->time_adjustment());
480                 widget_timeslider_->set_bounds_adjustment(&canvas_view->time_window_adjustment());
481                 widget_timeslider_->set_global_fps(canvas_view->get_canvas()->rend_desc().get_frame_rate());
482
483                 vscrollbar_->set_adjustment(*tree_view->get_vadjustment());
484                 hscrollbar_->set_adjustment(canvas_view->time_window_adjustment());
485                 table_=new Gtk::Table(2,2);
486                 table_->attach(*widget_timeslider_, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::SHRINK);
487                 table_->attach(*tree_view, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
488                 table_->attach(*hscrollbar_, 0, 1, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::SHRINK);
489                 table_->attach(*vscrollbar_, 1, 2, 0, 2, Gtk::FILL|Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
490                 add(*table_);
491                 
492                 //add(*last_widget_curves_);
493                 table_->show_all();
494                 show_all();
495         }
496         else
497         {
498                 //clear_previous();
499         }
500 }