improve resize flash operation, fixup xv grab/ungrab, fixup label updates
[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         deactivate();
131         if( !key_edit_displayed && keyframe_plugin ) {
132                 add_item(key_edit);
133                 key_edit_displayed = true;
134         }
135         else if( key_edit_displayed && !keyframe_plugin ) {
136                 remove_item(key_edit);
137                 key_edit_displayed = false;
138         }
139
140         if(!key_mode_displayed && autos && autos->get_type() == AUTOMATION_TYPE_FLOAT)
141         { // append additional menu entries showing the curve_mode
142                 add_item(key_mbar);
143                 add_item(key_smooth);
144                 add_item(key_linear);
145                 add_item(key_free_t);
146                 add_item(key_free);
147                 key_mode_displayed = true;
148         }
149         else if(key_mode_displayed && (!autos || autos->get_type() != AUTOMATION_TYPE_FLOAT))
150         { // remove additional menu entries
151                 remove_item(key_free);
152                 remove_item(key_free_t);
153                 remove_item(key_linear);
154                 remove_item(key_smooth);
155                 remove_item(key_mbar);
156                 key_mode_displayed = false;
157         }
158         if(key_mode_displayed && auto_keyframe)
159         { // set checkmarks to display current mode
160                 key_smooth->toggle_mode((FloatAuto*)auto_keyframe);
161                 key_linear->toggle_mode((FloatAuto*)auto_keyframe);
162                 key_free_t->toggle_mode((FloatAuto*)auto_keyframe);
163                 key_free  ->toggle_mode((FloatAuto*)auto_keyframe);
164         }
165         activate();
166 }
167
168 KeyframePopupDelete::KeyframePopupDelete(MWindow *mwindow, KeyframePopup *popup)
169  : BC_MenuItem(_("Delete keyframe"))
170 {
171         this->mwindow = mwindow;
172         this->popup = popup;
173 }
174
175 KeyframePopupDelete::~KeyframePopupDelete()
176 {
177 }
178
179 int KeyframePopupDelete::handle_event()
180 {
181         mwindow->undo->update_undo_before(_("delete keyframe"), 0);
182         delete popup->keyframe_auto;
183         mwindow->undo->update_undo_after(_("delete keyframe"), LOAD_ALL);
184
185         mwindow->save_backup();
186         mwindow->gui->update(0, 1,      // 1 for incremental drawing.  2 for full refresh
187                 0, 0, 0, 0, 0);
188         mwindow->update_plugin_guis();
189         mwindow->restart_brender();
190         mwindow->sync_parameters(CHANGE_EDL);
191
192         return 1;
193 }
194
195 KeyframePopupShow::KeyframePopupShow(MWindow *mwindow, KeyframePopup *popup)
196  : BC_MenuItem(_("Show keyframe settings"))
197 {
198         this->mwindow = mwindow;
199         this->popup = popup;
200 }
201
202 KeyframePopupShow::~KeyframePopupShow()
203 {
204 }
205
206 int KeyframePopupShow::handle_event()
207 {
208         if (popup->keyframe_plugin)
209         {
210                 mwindow->update_plugin_guis();
211                 mwindow->show_plugin(popup->keyframe_plugin);
212         }
213         else if( popup->keyframe_automation ) {
214 /*
215
216                 mwindow->cwindow->gui->lock_window();
217                 int show_window = 1;
218                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos ||
219                    popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos)
220                    
221                 {
222                         mwindow->cwindow->gui->set_operation(CWINDOW_PROJECTOR);        
223                 } else
224                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos ||
225                    popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos)
226                    
227                 {
228                         mwindow->cwindow->gui->set_operation(CWINDOW_CAMERA);   
229                 } else
230                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos)
231                    
232                 {
233                         // no window to be shown
234                         show_window = 0;
235                         // first find the appropriate patchgui
236                         PatchBay *patchbay = mwindow->gui->patchbay;
237                         PatchGUI *patchgui = 0;
238                         for (int i = 0; i < patchbay->patches.total; i++)
239                                 if (patchbay->patches.values[i]->track == popup->keyframe_automation->track)
240                                         patchgui = patchbay->patches.values[i];         
241                         if (patchgui != 0)
242                         {
243 // FIXME: repositioning of the listbox needs support in guicast
244 //                              int cursor_x = popup->get_relative_cursor_x();
245 //                              int cursor_y = popup->get_relative_cursor_y();
246 //                              vpatchgui->mode->reposition_window(cursor_x, cursor_y);
247
248
249 // Open the popup menu
250                                 VPatchGUI *vpatchgui = (VPatchGUI *)patchgui;
251                                 vpatchgui->mode->activate_menu();
252                         }
253                 } else
254                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos)
255                    
256                 {
257                         mwindow->cwindow->gui->set_operation(CWINDOW_MASK);     
258                 } else
259                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos)
260                    
261                 {
262                         // no window to be shown
263                         show_window = 0;
264                         // first find the appropriate patchgui
265                         PatchBay *patchbay = mwindow->gui->patchbay;
266                         PatchGUI *patchgui = 0;
267                         for (int i = 0; i < patchbay->patches.total; i++)
268                                 if (patchbay->patches.values[i]->track == popup->keyframe_automation->track)
269                                         patchgui = patchbay->patches.values[i];         
270                         if (patchgui != 0)
271                         {
272 // Open the popup menu at current mouse position
273                                 APatchGUI *apatchgui = (APatchGUI *)patchgui;
274                                 int cursor_x = popup->get_relative_cursor_x();
275                                 int cursor_y = popup->get_relative_cursor_y();
276                                 apatchgui->pan->activate(cursor_x, cursor_y);
277                         }
278                         
279
280                 } else
281                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos)
282                    
283                 {
284                         // no window to be shown, so do nothing
285                         // IDEA: open window for fading
286                         show_window = 0;
287                 } else
288                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos)
289                    
290                 {
291                         // no window to be shown, so do nothing
292                         // IDEA: directly switch
293                         show_window = 0;
294                 } else;
295                 
296
297 // ensure bringing to front
298                 if (show_window)
299                 {
300                         ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(0);
301                         ((CPanelToolWindow *)(mwindow->cwindow->gui->composite_panel->operation[CWINDOW_TOOL_WINDOW]))->set_shown(1);
302                 }
303                 mwindow->cwindow->gui->unlock_window();
304
305
306 */
307         }
308         return 1;
309 }
310
311
312
313 KeyframePopupCopy::KeyframePopupCopy(MWindow *mwindow, KeyframePopup *popup)
314  : BC_MenuItem(_("Copy keyframe"))
315 {
316         this->mwindow = mwindow;
317         this->popup = popup;
318 }
319
320 KeyframePopupCopy::~KeyframePopupCopy()
321 {
322 }
323
324 int KeyframePopupCopy::handle_event()
325 {
326 /*
327         FIXME:
328         we want to copy just keyframe under cursor, NOT all keyframes at this frame
329         - very hard to do, so this is good approximation for now...
330 */
331         
332 #if 0
333         if (popup->keyframe_automation)
334         {
335                 FileXML file;
336                 EDL *edl = mwindow->edl;
337                 Track *track = popup->keyframe_automation->track;
338                 int64_t position = popup->keyframe_auto->position;
339                 AutoConf autoconf;
340 // first find out type of our auto
341                 autoconf.set_all(0);
342                 if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->projector_autos)
343                         autoconf.projector = 1;
344                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pzoom_autos)
345                         autoconf.pzoom = 1;
346                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->camera_autos)
347                         autoconf.camera = 1;
348                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->czoom_autos)
349                         autoconf.czoom = 1;             
350                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mode_autos)
351                         autoconf.mode = 1;
352                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mask_autos)
353                         autoconf.mask = 1;
354                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->pan_autos)
355                         autoconf.pan = 1;                  
356                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->fade_autos)
357                         autoconf.fade = 1;
358                 else if (popup->keyframe_autos == (Autos *)popup->keyframe_automation->mute_autos)
359                         autoconf.mute = 1;              
360
361
362 // now create a clipboard
363                 file.tag.set_title("AUTO_CLIPBOARD");
364                 file.tag.set_property("LENGTH", 0);
365                 file.tag.set_property("FRAMERATE", edl->session->frame_rate);
366                 file.tag.set_property("SAMPLERATE", edl->session->sample_rate);
367                 file.append_tag();
368                 file.append_newline();
369                 file.append_newline();
370
371 /*              track->copy_automation(position, 
372                         position, 
373                         &file,
374                         0,
375                         0);
376                         */
377                 file.tag.set_title("TRACK");
378 // Video or audio
379                 track->save_header(&file);
380                 file.append_tag();
381                 file.append_newline();
382
383                 track->automation->copy(position, 
384                         position, 
385                         &file,
386                         0,
387                         0,
388                         &autoconf);
389                 
390                 
391                 
392                 file.tag.set_title("/TRACK");
393                 file.append_tag();
394                 file.append_newline();
395                 file.append_newline();
396                 file.append_newline();
397                 file.append_newline();
398
399
400
401                 file.tag.set_title("/AUTO_CLIPBOARD");
402                 file.append_tag();
403                 file.append_newline();
404                 file.terminate_string();
405
406                 mwindow->gui->lock_window();
407                 mwindow->gui->get_clipboard()->to_clipboard(file.string, 
408                         strlen(file.string), 
409                         SECONDARY_SELECTION);
410                 mwindow->gui->unlock_window();
411
412         } else
413 #endif
414                 mwindow->copy_automation();
415         return 1;
416 }
417
418
419
420 KeyframePopupCurveMode::KeyframePopupCurveMode(
421         MWindow *mwindow, 
422         KeyframePopup *popup, 
423         int curve_mode)
424  : BC_MenuItem( get_labeltext(curve_mode))
425 {
426         this->curve_mode = curve_mode;
427         this->mwindow = mwindow;
428         this->popup = popup;
429 }
430
431 KeyframePopupCurveMode::~KeyframePopupCurveMode() { }
432
433
434 const char* KeyframePopupCurveMode::get_labeltext(int mode)
435 {
436         switch(mode) {
437         case FloatAuto::SMOOTH: return _("smooth curve");
438         case FloatAuto::LINEAR: return _("linear segments");
439         case FloatAuto::TFREE:  return _("tangent edit");
440         case FloatAuto::FREE:   return _("disjoint edit");
441         }
442         return _("misconfigured");
443 }
444
445
446 void KeyframePopupCurveMode::toggle_mode(FloatAuto *keyframe)
447 {
448         set_checked(curve_mode == keyframe->curve_mode);
449 }
450
451
452 int KeyframePopupCurveMode::handle_event()
453 {
454         if (popup->keyframe_autos && 
455             popup->keyframe_autos->get_type() == AUTOMATION_TYPE_FLOAT)
456         {
457                 mwindow->undo->update_undo_before(_("change keyframe curve mode"), 0);
458                 ((FloatAuto*)popup->keyframe_auto)->
459                         change_curve_mode((FloatAuto::t_mode)curve_mode);
460                 
461                 // if we switched to some "auto" mode, this may imply a
462                 // real change to parameters, so this needs to be undoable...
463                 mwindow->undo->update_undo_after(_("change keyframe curve mode"), LOAD_ALL);
464                 mwindow->save_backup();
465                 
466                 mwindow->gui->update(0, 1, 0,0,0,0,0); // incremental redraw for canvas
467                 mwindow->cwindow->update(0,0, 1, 0,0); // redraw tool window in compositor
468                 mwindow->update_plugin_guis();
469                 mwindow->restart_brender();
470                 mwindow->sync_parameters(CHANGE_EDL);
471         }
472         return 1;
473 }
474
475
476 KeyframePopupEdit::KeyframePopupEdit(MWindow *mwindow, KeyframePopup *popup)
477  : BC_MenuItem(_("Edit Params..."))
478 {
479         this->mwindow = mwindow;
480         this->popup = popup;
481 }
482
483 int KeyframePopupEdit::handle_event()
484 {
485         mwindow->show_keyframe_gui(popup->keyframe_plugin);
486         return 1;
487 }
488
489
490 KeyframeHidePopup::KeyframeHidePopup(MWindow *mwindow, MWindowGUI *gui)
491  : BC_PopupMenu(0, 0, 0, "", 0)
492 {
493         this->mwindow = mwindow;
494         this->gui = gui;
495         this->keyframe_autos = 0;
496 }
497
498 KeyframeHidePopup::~KeyframeHidePopup()
499 {
500 }
501
502 void KeyframeHidePopup::create_objects()
503 {
504         add_item(new KeyframePopupHide(mwindow, this));
505 }
506
507 int KeyframeHidePopup::update(Autos *autos)
508 {
509         this->keyframe_autos = autos;
510         return 0;
511 }
512
513 KeyframePopupHide::KeyframePopupHide(MWindow *mwindow, KeyframeHidePopup *popup)
514  : BC_MenuItem(_("Hide keyframe type"))
515 {
516         this->mwindow = mwindow;
517         this->popup = popup;
518 }
519
520 int KeyframePopupHide::handle_event()
521 {
522 // Get the array index of the curve
523         int update_gui = 0;
524         if(popup->keyframe_autos)
525         {
526                 if(popup->keyframe_autos->type == Autos::AUTOMATION_TYPE_PLUGIN)
527                 {
528                         mwindow->edl->session->auto_conf->plugins = 0;
529                         update_gui = 1;
530                 }
531                 else
532                 {
533                         Track *track = popup->keyframe_autos->track;
534                         if(track)
535                         {
536                                 Automation *automation = track->automation;
537                                 if(automation)
538                                 {
539                                         for(int i = 0; i < AUTOMATION_TOTAL; i++)
540                                         {
541                                                 if(automation->autos[i] == popup->keyframe_autos)
542                                                 {
543                                                         mwindow->edl->session->auto_conf->autos[i] = 0;
544                                                         update_gui = 1;
545                                                         break;
546                                                 }
547                                         }
548                                 }
549                         }
550                 }
551         }
552
553         if(update_gui)
554         {
555                 mwindow->gui->update(0,
556                         1,      // 1 for incremental drawing.  2 for full refresh
557                         0,
558                         0,
559                         0,
560                 0,   
561                 0);
562                 mwindow->gui->mainmenu->update_toggles(1);
563                 mwindow->gui->unlock_window();
564                 mwindow->gwindow->gui->update_toggles(1);
565                 mwindow->gui->lock_window("KeyframePopupHide::handle_event");
566         }
567
568         return 1;
569 }
570