Exciting new Alt/h help key provided by sge (Georgy) with many thanks!
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / transitionpopup.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 "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "edit.h"
25 #include "edl.h"
26 #include "edlsession.h"
27 #include "language.h"
28 #include "mwindow.h"
29 #include "mwindowgui.h"
30 #include "plugin.h"
31 #include "transition.h"
32 #include "track.h"
33 #include "tracks.h"
34 #include "transitionpopup.h"
35
36
37 TransitionLengthThread::TransitionLengthThread(MWindow *mwindow)
38  : BC_DialogThread()
39 {
40         this->mwindow = mwindow;
41 }
42
43 TransitionLengthThread::~TransitionLengthThread()
44 {
45         close_window();
46 }
47
48 void TransitionLengthThread::start(Transition *transition, double length)
49 {
50         this->transition = transition;
51         this->orig_length = length;
52         this->new_length = length;
53         BC_DialogThread::start();
54 }
55
56 #define TLW_W xS(300)
57 #define TLW_H yS(100)
58
59 BC_Window* TransitionLengthThread::new_gui()
60 {
61         BC_DisplayInfo display_info;
62         int x = display_info.get_abs_cursor_x() - TLW_W / 2;
63         int y = display_info.get_abs_cursor_y() - TLW_H / 2;
64         TransitionLengthDialog *gui = new TransitionLengthDialog(mwindow, this, x, y);
65         gui->create_objects();
66         return gui;
67 }
68
69 void TransitionLengthThread::handle_close_event(int result)
70 {
71         if( mwindow->in_destructor ) return;
72         if( !result ) {
73                 if( transition )
74                         mwindow->set_transition_length(transition, new_length);
75                 else
76                         mwindow->set_transition_length(new_length);
77         }
78         else
79                 update(orig_length);
80 }
81
82 int TransitionLengthThread::update(double length)
83 {
84         if( !EQUIV(this->new_length, length) ) {
85                 this->new_length = length;
86                 if( transition ) {
87                         transition->length = transition->track->to_units(length, 1);
88                         mwindow->sync_parameters(CHANGE_EDL);
89                         mwindow->gui->lock_window();
90                         mwindow->gui->draw_overlays(1);
91                         mwindow->gui->unlock_window();
92                 }
93         }
94         return 1;
95 }
96
97
98 TransitionUnitsItem::TransitionUnitsItem(TransitionUnitsPopup *popup,
99                 const char *text, int id)
100  : BC_MenuItem(text)
101 {
102         this->popup = popup;
103         this->id = id;
104 }
105
106 TransitionUnitsItem::~TransitionUnitsItem()
107 {
108 }
109
110 int TransitionUnitsItem::handle_event()
111 {
112         TransitionUnitsPopup *units_popup = (TransitionUnitsPopup *)get_popup_menu();
113         TransitionLengthDialog *gui = units_popup->gui;
114         double length = gui->thread->new_length;
115         units_popup->units = id;
116         gui->update_text(length);
117         units_popup->set_text(get_text());
118         return 1;
119 }
120
121 TransitionUnitsPopup::TransitionUnitsPopup(TransitionLengthDialog *gui, int x, int y)
122  : BC_PopupMenu(x, y, xS(120), "", 1)
123 {
124         this->gui = gui;
125         units = TIME_SECONDS;
126 }
127
128 TransitionUnitsPopup::~TransitionUnitsPopup()
129 {
130 }
131
132 void TransitionUnitsPopup::create_objects()
133 {
134         TransitionUnitsItem *units_item;
135         add_item(units_item = new TransitionUnitsItem(this, _("Seconds"), TIME_SECONDS));
136         add_item(new TransitionUnitsItem(this, _("Frames"), TIME_FRAMES));
137         add_item(new TransitionUnitsItem(this, _("Samples"), TIME_SAMPLES));
138         add_item(new TransitionUnitsItem(this, _("H:M:S.xxx"), TIME_HMS));
139         add_item(new TransitionUnitsItem(this, _("H:M:S:frm"), TIME_HMSF));
140         set_text(units_item->get_text());
141 }
142
143
144 TransitionLengthDialog::TransitionLengthDialog(MWindow *mwindow,
145         TransitionLengthThread *thread, int x, int y)
146  : BC_Window(_(PROGRAM_NAME ": Transition length"), x, y,
147                 TLW_W, TLW_H, -1, -1, 0, 0, 1)
148 {
149         this->mwindow = mwindow;
150         this->thread = thread;
151 // *** CONTEXT_HELP ***
152         context_help_set_keyword("Transition Plugins");
153 }
154
155 TransitionLengthDialog::~TransitionLengthDialog()
156 {
157 }
158
159
160 void TransitionLengthDialog::create_objects()
161 {
162         lock_window("TransitionLengthDialog::create_objects");
163         add_subwindow(units_popup = new TransitionUnitsPopup(this, xS(10), yS(10)));
164         units_popup->create_objects();
165         text = new TransitionLengthText(mwindow, this, xS(160), yS(10));
166         text->create_objects();
167         text->set_precision(3);
168         text->set_increment(0.1);
169         add_subwindow(new BC_OKButton(this));
170         add_subwindow(new BC_CancelButton(this));
171         show_window();
172         unlock_window();
173 }
174
175 int TransitionLengthDialog::close_event()
176 {
177         set_done(0);
178         return 1;
179 }
180
181 void TransitionLengthDialog::update_text(double length)
182 {
183         int units = units_popup->units;
184         EDLSession *session = mwindow->edl->session;
185         char string[BCSTRLEN];
186         Units::totext(string, length, units,
187                 session->sample_rate, session->frame_rate,
188                 session->frames_per_foot);
189         text->update(string);
190 }
191
192
193 TransitionLengthText::TransitionLengthText(MWindow *mwindow,
194         TransitionLengthDialog *gui, int x, int y)
195  : BC_TumbleTextBox(gui, (float)gui->thread->new_length,
196                 0.f, 100.f, x, y, xS(100))
197 {
198         this->mwindow = mwindow;
199         this->gui = gui;
200 }
201
202 int TransitionLengthText::handle_event()
203 {
204         const char *text = get_text();
205         int units = gui->units_popup->units;
206         EDLSession *session = gui->mwindow->edl->session;
207         double result = Units::text_to_seconds(text, session->sample_rate,
208                 units, session->frame_rate, session->frames_per_foot);
209         return gui->thread->update(result);
210 }
211
212 int TransitionLengthText::handle_up_down(int dir)
213 {
214         double delta = 0;
215         int units = gui->units_popup->units;
216         EDLSession *session = gui->mwindow->edl->session;
217         switch( units ) {
218         case TIME_SECONDS:
219         case TIME_HMS:
220                 delta = 0.1;
221                 break;
222         case TIME_HMSF:
223         case TIME_FRAMES:
224                 delta = session->frame_rate > 0 ? 1./session->frame_rate : 0;
225                 break;
226         case TIME_SAMPLES:
227                 delta = session->sample_rate > 0 ? 1./session->sample_rate : 0;
228                 break;
229         }
230         double length = gui->thread->new_length + delta * dir;
231         gui->update_text(length);
232         return gui->thread->update(length);
233 }
234
235 int TransitionLengthText::handle_up_event()
236 {
237         return handle_up_down(+1);
238 }
239 int TransitionLengthText::handle_down_event()
240 {
241         return handle_up_down(-1);
242 }
243
244
245 TransitionPopup::TransitionPopup(MWindow *mwindow, MWindowGUI *gui)
246  : BC_PopupMenu(0, 0, 0, "", 0)
247 {
248         this->mwindow = mwindow;
249         this->gui = gui;
250 }
251
252 TransitionPopup::~TransitionPopup()
253 {
254         delete length_thread;
255 //      delete dialog_thread;
256 }
257
258
259 void TransitionPopup::create_objects()
260 {
261         length_thread = new TransitionLengthThread(mwindow);
262 //      add_item(attach = new TransitionPopupAttach(mwindow, this));
263         add_item(show = new TransitionPopupShow(mwindow, this));
264         add_item(on = new TransitionPopupOn(mwindow, this));
265         add_item(length_item = new TransitionPopupLength(mwindow, this));
266         add_item(detach = new TransitionPopupDetach(mwindow, this));
267 }
268
269 int TransitionPopup::update(Transition *transition)
270 {
271         this->transition = transition;
272         show->set_checked(transition->show);
273         on->set_checked(transition->on);
274         char len_text[50];
275         sprintf(len_text, _("Length: %2.2f sec"), transition->track->from_units(transition->length));
276         length_item->set_text(len_text);
277         return 0;
278 }
279
280
281 TransitionPopupAttach::TransitionPopupAttach(MWindow *mwindow, TransitionPopup *popup)
282  : BC_MenuItem(_("Attach..."))
283 {
284         this->mwindow = mwindow;
285         this->popup = popup;
286 }
287
288 TransitionPopupAttach::~TransitionPopupAttach()
289 {
290 }
291
292 int TransitionPopupAttach::handle_event()
293 {
294 //      popup->dialog_thread->start();
295         return 1;
296 }
297
298
299 TransitionPopupDetach::TransitionPopupDetach(MWindow *mwindow, TransitionPopup *popup)
300  : BC_MenuItem(_("Detach"))
301 {
302         this->mwindow = mwindow;
303         this->popup = popup;
304 }
305
306 TransitionPopupDetach::~TransitionPopupDetach()
307 {
308 }
309
310 int TransitionPopupDetach::handle_event()
311 {
312         mwindow->detach_transition(popup->transition);
313         return 1;
314 }
315
316
317 TransitionPopupOn::TransitionPopupOn(MWindow *mwindow, TransitionPopup *popup)
318  : BC_MenuItem(_("On"))
319 {
320         this->mwindow = mwindow;
321         this->popup = popup;
322 }
323
324 TransitionPopupOn::~TransitionPopupOn()
325 {
326 }
327
328 int TransitionPopupOn::handle_event()
329 {
330         popup->transition->on = !get_checked();
331         mwindow->sync_parameters(CHANGE_EDL);
332         return 1;
333 }
334
335
336 TransitionPopupShow::TransitionPopupShow(MWindow *mwindow, TransitionPopup *popup)
337  : BC_MenuItem(_("Show"))
338 {
339         this->mwindow = mwindow;
340         this->popup = popup;
341 }
342
343 TransitionPopupShow::~TransitionPopupShow()
344 {
345 }
346
347 int TransitionPopupShow::handle_event()
348 {
349         mwindow->show_plugin(popup->transition);
350         return 1;
351 }
352
353
354 TransitionPopupLength::TransitionPopupLength(MWindow *mwindow, TransitionPopup *popup)
355  : BC_MenuItem(_("Length"))
356 {
357         this->mwindow = mwindow;
358         this->popup = popup;
359 }
360
361 TransitionPopupLength::~TransitionPopupLength()
362 {
363 }
364
365 int TransitionPopupLength::handle_event()
366 {
367         Transition *transition = popup->transition;
368         double length = transition->edit->track->from_units(transition->length);
369         popup->length_thread->start(popup->transition, length);
370         return 1;
371 }
372