rework keyframe hide popup, keyframe auto render, textbox set_selection wide text
[goodguy/history.git] / cinelerra-5.1 / cinelerra / keyframepopup.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "apatchgui.h"
23 #include "autoconf.h"
24 #include "autos.h"
25 #include "bcwindowbase.h"
26 #include "cpanel.h"
27 #include "cwindowgui.h" 
28 #include "cwindow.h"
29 #include "edl.h"
30 #include "edlsession.h"
31 #include "filexml.h"
32 #include "gwindow.h"
33 #include "gwindowgui.h"
34 #include "keyframe.h"
35 #include "keyframepopup.h"
36 #include "language.h"
37 #include "localsession.h"
38 #include "maincursor.h"
39 #include "mainmenu.h"
40 #include "mainundo.h"
41 #include "mwindowgui.h"
42 #include "mwindow.h"
43 #include "patchbay.h"
44 #include "patchgui.h" 
45 #include "track.h"
46 #include "vpatchgui.h"
47
48 KeyframePopup::KeyframePopup(MWindow *mwindow, MWindowGUI *gui)
49  : BC_PopupMenu(0, 0, 0, "", 0)
50 {
51         this->mwindow = mwindow;
52         this->gui = gui;
53         key_show = 0;
54         key_delete = 0;
55         key_copy = 0;
56         key_smooth = 0;
57         key_linear = 0;
58         key_free = 0;
59         key_mbar = 0;
60         key_mode_displayed = false;
61         key_edit_displayed = false;
62 }
63
64 KeyframePopup::~KeyframePopup()
65 {
66         if( !key_mode_displayed ) {
67                 delete key_mbar;
68                 delete key_smooth;
69                 delete key_linear;
70                 delete key_free_t;
71                 delete key_free;
72         }
73         if( !key_edit_displayed ) {
74                 delete key_edit;
75         }
76 }
77
78 void KeyframePopup::create_objects()
79 {
80         add_item(key_show = new KeyframePopupShow(mwindow, this));
81         add_item(key_delete = new KeyframePopupDelete(mwindow, this));
82         add_item(key_copy = new KeyframePopupCopy(mwindow, this));
83
84         key_edit   = new KeyframePopupEdit(mwindow, this);
85         key_mbar   = new BC_MenuItem("-");
86         key_smooth = new KeyframePopupCurveMode(mwindow, this, FloatAuto::SMOOTH);
87         key_linear = new KeyframePopupCurveMode(mwindow, this, FloatAuto::LINEAR);
88         key_free_t = new KeyframePopupCurveMode(mwindow, this, FloatAuto::TFREE );
89         key_free   = new KeyframePopupCurveMode(mwindow, this, FloatAuto::FREE  );
90 }
91
92 int KeyframePopup::update(Plugin *plugin, KeyFrame *keyframe)
93 {
94         this->keyframe_plugin = plugin;
95         this->keyframe_auto = keyframe;
96         this->keyframe_autos = 0;
97         this->keyframe_automation = 0;
98         handle_curve_mode(0, 0);
99         return 0;
100 }
101
102 int KeyframePopup::update(Automation *automation, Autos *autos, Auto *auto_keyframe)
103 {
104         this->keyframe_plugin = 0;
105         this->keyframe_automation = automation;
106         this->keyframe_autos = autos;
107         this->keyframe_auto = auto_keyframe;
108         handle_curve_mode(autos, auto_keyframe);
109
110         /* snap to cursor */
111         double current_position = mwindow->edl->local_session->get_selectionstart(1);
112         double new_position = keyframe_automation->track->from_units(keyframe_auto->position);
113         mwindow->edl->local_session->set_selectionstart(new_position);
114         mwindow->edl->local_session->set_selectionend(new_position);
115         if (current_position != new_position)
116         {
117                 mwindow->edl->local_session->set_selectionstart(new_position);
118                 mwindow->edl->local_session->set_selectionend(new_position);
119                 mwindow->gui->lock_window();
120                 mwindow->gui->update(1, 1, 1, 1, 1, 1, 0);      
121                 mwindow->gui->unlock_window();
122         }
123         return 0;
124 }
125
126 void KeyframePopup::handle_curve_mode(Autos *autos, Auto *auto_keyframe)
127 // determines the type of automation node. if floatauto, adds
128 // menu entries showing the curve mode of the node
129 {
130         if( !key_edit_displayed && keyframe_plugin ) {
131                 add_item(key_edit);
132                 key_edit_displayed = true;
133         }
134         else if( key_edit_displayed && !keyframe_plugin ) {
135                 remove_item(key_mbar);
136                 key_edit_displayed = false;
137         }
138
139         if(!key_mode_displayed && autos && autos->get_type() == AUTOMATION_TYPE_FLOAT)
140         { // append additional menu entries showing the curve_mode
141                 add_item(key_mbar);
142                 add_item(key_smooth);
143                 add_item(key_linear);
144                 add_item(key_free_t);
145                 add_item(key_free);
146                 key_mode_displayed = true;
147         }
148         else if(key_mode_displayed && (!autos || autos->get_type() != AUTOMATION_TYPE_FLOAT))
149         { // remove additional menu entries
150                 remove_item(key_free);
151                 remove_item(key_free_t);
152                 remove_item(key_linear);
153                 remove_item(key_smooth);
154                 remove_item(key_mbar);
155                 key_mode_displayed = false;
156         }
157         if(key_mode_displayed && auto_keyframe)
158         { // set checkmarks to display current mode
159                 key_smooth->toggle_mode((FloatAuto*)auto_keyframe);
160                 key_linear->toggle_mode((FloatAuto*)auto_keyframe);
161                 key_free_t->toggle_mode((FloatAuto*)auto_keyframe);
162                 key_free  ->toggle_mode((FloatAuto*)auto_keyframe);
163         }
164 }
165
166 KeyframePopupDelete::KeyframePopupDelete(MWindow *mwindow, KeyframePopup *popup)
167  : BC_MenuItem(_("Delete keyframe"))
168 {
169         this->mwindow = mwindow;
170         this->popup = popup;
171 }
172
173 KeyframePopupDelete::~KeyframePopupDelete()
174 {
175 }
176
177 int KeyframePopupDelete::handle_event()
178 {
179         mwindow->undo->update_undo_before(_("delete keyframe"), 0);
180         delete popup->keyframe_auto;
181         mwindow->undo->update_undo_after(_("delete keyframe"), LOAD_ALL);
182
183         mwindow->save_backup();
184         mwindow->gui->update(0, 1,      // 1 for incremental drawing.  2 for full refresh
185                 0, 0, 0, 0, 0);
186         mwindow->update_plugin_guis();
187         mwindow->restart_brender();
188         mwindow->sync_parameters(CHANGE_EDL);
189
190         return 1;
191 }
192
193 KeyframePopupShow::KeyframePopupShow(MWindow *mwindow, KeyframePopup *popup)
194  : BC_MenuItem(_("Show keyframe settings"))
195 {
196         this->mwindow = mwindow;
197         this->popup = popup;
198 }
199
200 KeyframePopupShow::~KeyframePopupShow()
201 {
202 }
203
204 int KeyframePopupShow::handle_event()
205 {
206         if (popup->keyframe_plugin)
207         {
208                 mwindow->update_plugin_guis();
209                 mwindow->show_plugin(popup->keyframe_plugin);
210         }
211         else if( popup->keyframe_automation ) {
212 /*
213
214                 mwindow->cwindow->gui->lock_window();
215                 int show_window = 1;
216                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos ||
217                    popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos)
218                    
219                 {
220                         mwindow->cwindow->gui->set_operation(CWINDOW_PROJECTOR);        
221                 } else
222                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos ||
223                    popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos)
224                    
225                 {
226                         mwindow->cwindow->gui->set_operation(CWINDOW_CAMERA);   
227                 } else
228                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos)
229                    
230                 {
231                         // no window to be shown
232                         show_window = 0;
233                         // first find the appropriate patchgui
234                         PatchBay *patchbay = mwindow->gui->patchbay;
235                         PatchGUI *patchgui = 0;
236                         for (int i = 0; i < patchbay->patches.total; i++)
237                                 if (patchbay->patches.values[i]->track == popup->keyframe_automation->track)
238                                         patchgui = patchbay->patches.values[i];         
239                         if (patchgui != 0)
240                         {
241 // FIXME: repositioning of the listbox needs support in guicast
242 //                              int cursor_x = popup->get_relative_cursor_x();
243 //                              int cursor_y = popup->get_relative_cursor_y();
244 //                              vpatchgui->mode->reposition_window(cursor_x, cursor_y);
245
246
247 // Open the popup menu
248                                 VPatchGUI *vpatchgui = (VPatchGUI *)patchgui;
249                                 vpatchgui->mode->activate_menu();
250                         }
251                 } else
252                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos)
253                    
254                 {
255                         mwindow->cwindow->gui->set_operation(CWINDOW_MASK);     
256                 } else
257                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos)
258                    
259                 {
260                         // no window to be shown
261                         show_window = 0;
262                         // first find the appropriate patchgui
263                         PatchBay *patchbay = mwindow->gui->patchbay;
264                         PatchGUI *patchgui = 0;
265                         for (int i = 0; i < patchbay->patches.total; i++)
266                                 if (patchbay->patches.values[i]->track == popup->keyframe_automation->track)
267                                         patchgui = patchbay->patches.values[i];         
268                         if (patchgui != 0)
269                         {
270 // Open the popup menu at current mouse position
271                                 APatchGUI *apatchgui = (APatchGUI *)patchgui;
272                                 int cursor_x = popup->get_relative_cursor_x();
273                                 int cursor_y = popup->get_relative_cursor_y();
274                                 apatchgui->pan->activate(cursor_x, cursor_y);
275                         }
276                         
277
278                 } else
279                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos)
280                    
281                 {
282                         // no window to be shown, so do nothing
283                         // IDEA: open window for fading
284                         show_window = 0;
285                 } else
286                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos)
287                    
288                 {
289                         // no window to be shown, so do nothing
290                         // IDEA: directly switch
291                         show_window = 0;
292                 } else;
293                 
294
295 // ensure bringing to front
296                 if (show_window)
297                 {
298                         ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(0);
299                         ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(1);
300                 }
301                 mwindow->cwindow->gui->unlock_window();
302
303
304 */
305         }
306         return 1;
307 }
308
309
310
311 KeyframePopupCopy::KeyframePopupCopy(MWindow *mwindow, KeyframePopup *popup)
312  : BC_MenuItem(_("Copy keyframe"))
313 {
314         this->mwindow = mwindow;
315         this->popup = popup;
316 }
317
318 KeyframePopupCopy::~KeyframePopupCopy()
319 {
320 }
321
322 int KeyframePopupCopy::handle_event()
323 {
324 /*
325         FIXME:
326         we want to copy just keyframe under cursor, NOT all keyframes at this frame
327         - very hard to do, so this is good approximation for now...
328 */
329         
330 #if 0
331         if (popup->keyframe_automation)
332         {
333                 FileXML file;
334                 EDL *edl = mwindow->edl;
335                 Track *track = popup->keyframe_automation->track;
336                 int64_t position = popup->keyframe_auto->position;
337                 AutoConf autoconf;
338 // first find out type of our auto
339                 autoconf.set_all(0);
340                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos)
341                         autoconf.projector = 1;
342                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos)
343                         autoconf.pzoom = 1;
344                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos)
345                         autoconf.camera = 1;
346                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos)
347                         autoconf.czoom = 1;             
348                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos)
349                         autoconf.mode = 1;
350                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos)
351                         autoconf.mask = 1;
352                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos)
353                         autoconf.pan = 1;                  
354                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos)
355                         autoconf.fade = 1;
356                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos)
357                         autoconf.mute = 1;              
358
359
360 // now create a clipboard
361                 file.tag.set_title("AUTO_CLIPBOARD");
362                 file.tag.set_property("LENGTH", 0);
363                 file.tag.set_property("FRAMERATE", edl->session->frame_rate);
364                 file.tag.set_property("SAMPLERATE", edl->session->sample_rate);
365                 file.append_tag();
366                 file.append_newline();
367                 file.append_newline();
368
369 /*              track->copy_automation(position, 
370                         position, 
371                         &file,
372                         0,
373                         0);
374                         */
375                 file.tag.set_title("TRACK");
376 // Video or audio
377                 track->save_header(&file);
378                 file.append_tag();
379                 file.append_newline();
380
381                 track->automation->copy(position, 
382                         position, 
383                         &file,
384                         0,
385                         0,
386                         &autoconf);
387                 
388                 
389                 
390                 file.tag.set_title("/TRACK");
391                 file.append_tag();
392                 file.append_newline();
393                 file.append_newline();
394                 file.append_newline();
395                 file.append_newline();
396
397
398
399                 file.tag.set_title("/AUTO_CLIPBOARD");
400                 file.append_tag();
401                 file.append_newline();
402                 file.terminate_string();
403
404                 mwindow->gui->lock_window();
405                 mwindow->gui->get_clipboard()->to_clipboard(file.string, 
406                         strlen(file.string), 
407                         SECONDARY_SELECTION);
408                 mwindow->gui->unlock_window();
409
410         } else
411 #endif
412                 mwindow->copy_automation();
413         return 1;
414 }
415
416
417
418 KeyframePopupCurveMode::KeyframePopupCurveMode(
419         MWindow *mwindow, 
420         KeyframePopup *popup, 
421         int curve_mode)
422  : BC_MenuItem( get_labeltext(curve_mode))
423 {
424         this->curve_mode = curve_mode;
425         this->mwindow = mwindow;
426         this->popup = popup;
427 }
428
429 KeyframePopupCurveMode::~KeyframePopupCurveMode() { }
430
431
432 const char* KeyframePopupCurveMode::get_labeltext(int mode)
433 {
434         switch(mode) {
435         case FloatAuto::SMOOTH: return _("smooth curve");
436         case FloatAuto::LINEAR: return _("linear segments");
437         case FloatAuto::TFREE:  return _("tangent edit");
438         case FloatAuto::FREE:   return _("disjoint edit");
439         }
440         return "misconfigured";
441 }
442
443
444 void KeyframePopupCurveMode::toggle_mode(FloatAuto *keyframe)
445 {
446         set_checked(curve_mode == keyframe->curve_mode);
447 }
448
449
450 int KeyframePopupCurveMode::handle_event()
451 {
452         if (popup->keyframe_autos && 
453             popup->keyframe_autos->get_type() == AUTOMATION_TYPE_FLOAT)
454         {
455                 mwindow->undo->update_undo_before(_("change keyframe curve mode"), 0);
456                 ((FloatAuto*)popup->keyframe_auto)->
457                         change_curve_mode((FloatAuto::t_mode)curve_mode);
458                 
459                 // if we switched to some "auto" mode, this may imply a
460                 // real change to parameters, so this needs to be undoable...
461                 mwindow->undo->update_undo_after(_("change keyframe curve mode"), LOAD_ALL);
462                 mwindow->save_backup();
463                 
464                 mwindow->gui->update(0, 1, 0,0,0,0,0); // incremental redraw for canvas
465                 mwindow->cwindow->update(0,0, 1, 0,0); // redraw tool window in compositor
466                 mwindow->update_plugin_guis();
467                 mwindow->restart_brender();
468                 mwindow->sync_parameters(CHANGE_EDL);
469         }
470         return 1;
471 }
472
473
474 KeyframePopupEdit::KeyframePopupEdit(MWindow *mwindow, KeyframePopup *popup)
475  : BC_MenuItem(_("Edit Params..."))
476 {
477         this->mwindow = mwindow;
478         this->popup = popup;
479 }
480
481 int KeyframePopupEdit::handle_event()
482 {
483         mwindow->show_keyframe_gui(popup->keyframe_plugin);
484         return 1;
485 }
486
487
488 KeyframeHidePopup::KeyframeHidePopup(MWindow *mwindow, MWindowGUI *gui)
489  : BC_PopupMenu(0, 0, 0, "", 0)
490 {
491         this->mwindow = mwindow;
492         this->gui = gui;
493         this->keyframe_autos = 0;
494 }
495
496 KeyframeHidePopup::~KeyframeHidePopup()
497 {
498 }
499
500 void KeyframeHidePopup::create_objects()
501 {
502         add_item(new KeyframePopupHide(mwindow, this));
503 }
504
505 int KeyframeHidePopup::update(Autos *autos)
506 {
507         this->keyframe_autos = autos;
508         return 0;
509 }
510
511 KeyframePopupHide::KeyframePopupHide(MWindow *mwindow, KeyframeHidePopup *popup)
512  : BC_MenuItem(_("Hide keyframe type"))
513 {
514         this->mwindow = mwindow;
515         this->popup = popup;
516 }
517
518 int KeyframePopupHide::handle_event()
519 {
520 // Get the array index of the curve
521         int update_gui = 0;
522         if(popup->keyframe_autos)
523         {
524                 if(popup->keyframe_autos->type == Autos::AUTOMATION_TYPE_PLUGIN)
525                 {
526                         mwindow->edl->session->auto_conf->plugins = 0;
527                         update_gui = 1;
528                 }
529                 else
530                 {
531                         Track *track = popup->keyframe_autos->track;
532                         if(track)
533                         {
534                                 Automation *automation = track->automation;
535                                 if(automation)
536                                 {
537                                         for(int i = 0; i < AUTOMATION_TOTAL; i++)
538                                         {
539                                                 if(automation->autos[i] == popup->keyframe_autos)
540                                                 {
541                                                         mwindow->edl->session->auto_conf->autos[i] = 0;
542                                                         update_gui = 1;
543                                                         break;
544                                                 }
545                                         }
546                                 }
547                         }
548                 }
549         }
550
551         if(update_gui)
552         {
553                 mwindow->gui->update(0,
554                         1,      // 1 for incremental drawing.  2 for full refresh
555                         0,
556                         0,
557                         0,
558                 0,   
559                 0);
560                 mwindow->gui->mainmenu->update_toggles(1);
561                 mwindow->gui->unlock_window();
562                 mwindow->gwindow->gui->update_toggles(1);
563                 mwindow->gui->lock_window("KeyframePopupHide::handle_event");
564         }
565
566         return 1;
567 }
568