4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
23 #include "bcsignals.h"
26 #include "keyframes.h"
27 #include "keyframegui.h"
30 #include "localsession.h"
31 #include "mainsession.h"
34 #include "mwindowgui.h"
37 #include "trackcanvas.h"
41 KeyFrameThread::KeyFrameThread(MWindow *mwindow)
44 this->mwindow = mwindow;
47 keyframe_data = new ArrayList<BC_ListBoxItem*>[KEYFRAME_COLUMNS];
50 column_titles[0] = (char*)_("Parameter");
51 column_titles[1] = (char*)_("Value");
56 KeyFrameThread::~KeyFrameThread()
59 for(int i = 0; i < KEYFRAME_COLUMNS; i++)
60 keyframe_data[i].remove_all_objects();
61 delete [] keyframe_data;
65 void KeyFrameThread::update_values()
67 // Get the current selection before deleting the tables
69 for(int i = 0; i < keyframe_data[0].size(); i++) {
70 if(keyframe_data[0].get(i)->get_selected()) {
76 for(int i = 0; i < KEYFRAME_COLUMNS; i++)
77 keyframe_data[i].remove_all_objects();
80 // Must lock main window to read keyframe
81 mwindow->gui->lock_window("KeyFrameThread::update_values");
82 if(!plugin || !mwindow->edl->tracks->plugin_exists(plugin)) {
83 mwindow->gui->unlock_window();
87 KeyFrame *keyframe = 0;
88 if(this->keyframe && plugin->keyframe_exists(this->keyframe)) {
89 // If user edited a specific keyframe, use it.
90 keyframe = this->keyframe;
92 else if(plugin->track) {
93 // Use currently highlighted keyframe
94 keyframe = plugin->get_prev_keyframe(
95 plugin->track->to_units(
96 mwindow->edl->local_session->get_selectionstart(1), 0),
102 char *text = 0, *extra = 0;
103 keyframe->get_contents(&hash, &text, &extra);
105 for(int i = 0; i < hash.size(); i++)
107 keyframe_data[0].append(new BC_ListBoxItem(hash.get_key(i)));
108 keyframe_data[1].append(new BC_ListBoxItem(hash.get_value(i)));
110 keyframe_data[0].append(new BC_ListBoxItem((char*)_("TEXT")));
111 keyframe_data[1].append(new BC_ListBoxItem(text));
117 column_width[0] = mwindow->session->keyframedialog_column1;
118 column_width[1] = mwindow->session->keyframedialog_column2;
119 if(selection >= 0 && selection < keyframe_data[0].size()) {
120 for(int i = 0; i < KEYFRAME_COLUMNS; i++)
121 keyframe_data[i].get(selection)->set_selected(1);
123 mwindow->gui->unlock_window();
127 void KeyFrameThread::start_window(Plugin *plugin, KeyFrame *keyframe)
130 if(!BC_DialogThread::is_running()) {
131 if(!mwindow->edl->tracks->plugin_exists(plugin)) return;
132 this->keyframe = keyframe;
133 this->plugin = plugin;
134 plugin->calculate_title(plugin_title, 0);
135 sprintf(window_title, _(PROGRAM_NAME ": %s Keyframe"), plugin_title);
137 mwindow->gui->unlock_window();
138 BC_DialogThread::start();
139 mwindow->gui->lock_window("KeyFrameThread::start_window");
142 BC_DialogThread::start();
146 BC_Window* KeyFrameThread::new_gui()
148 mwindow->gui->lock_window("KeyFrameThread::new_gui");
150 int x = mwindow->gui->get_abs_cursor_x(0) -
151 mwindow->session->plugindialog_w / 2;
152 int y = mwindow->gui->get_abs_cursor_y(0) -
153 mwindow->session->plugindialog_h / 2;
155 KeyFrameWindow *window = new KeyFrameWindow(mwindow,
156 this, x, y, window_title);
157 window->create_objects();
159 mwindow->gui->unlock_window();
163 void KeyFrameThread::handle_done_event(int result)
169 void KeyFrameThread::handle_close_event(int result)
176 void KeyFrameThread::update_gui(int update_value_text)
178 if(BC_DialogThread::is_running()) {
179 mwindow->gui->lock_window("KeyFrameThread::update_gui");
181 mwindow->gui->unlock_window();
183 lock_window("KeyFrameThread::update_gui");
184 KeyFrameWindow *window = (KeyFrameWindow*)get_gui();
186 window->lock_window("KeyFrameThread::update_gui");
187 window->keyframe_list->update(keyframe_data,
188 (const char **)column_titles,
191 window->keyframe_list->get_xposition(),
192 window->keyframe_list->get_yposition(),
193 window->keyframe_list->get_highlighted_item());
194 if( update_value_text ) {
195 int selection_number = window->keyframe_list->get_selection_number(0, 0);
196 if( selection_number >= 0 && selection_number < keyframe_data[1].size()) {
197 char *edit_value = keyframe_data[1].get(selection_number)->get_text();
198 window->value_text->update(edit_value);
201 window->unlock_window();
207 void KeyFrameThread::apply_value()
209 const char *text = 0;
211 KeyFrameWindow *window = (KeyFrameWindow*)get_gui();
212 int selection = window->keyframe_list->get_selection_number(0, 0);
213 //printf("KeyFrameThread::apply_value %d %d\n", __LINE__, selection);
214 if(selection < 0) return;
216 if(selection == keyframe_data[0].size() - 1)
217 text = window->value_text->get_text();
219 char *key = keyframe_data[0].get(selection)->get_text();
220 const char *value = window->value_text->get_text();
221 hash.update(key, value);
224 get_gui()->unlock_window();
225 mwindow->gui->lock_window("KeyFrameThread::apply_value");
226 if(plugin && mwindow->edl->tracks->plugin_exists(plugin)) {
227 mwindow->undo->update_undo_before();
228 if(mwindow->session->keyframedialog_all) {
229 // Search for all keyframes in selection but don't create a new one.
230 Track *track = plugin->track;
231 int64_t start = track->to_units(mwindow->edl->local_session->get_selectionstart(0), 0);
232 int64_t end = track->to_units(mwindow->edl->local_session->get_selectionend(0), 0);
234 for(KeyFrame *current = (KeyFrame*)plugin->keyframes->last;
236 current = (KeyFrame*)PREVIOUS) {
238 if(current && current->position < end) {
239 current->update_parameter(&hash, text, 0);
240 // Stop at beginning of range
241 if(current->position <= start) break;
246 KeyFrame* keyframe = (KeyFrame*)plugin->keyframes->default_auto;
247 keyframe->update_parameter(&hash, text, 0);
251 // Create new keyframe if enabled
252 KeyFrame *keyframe = plugin->get_keyframe();
253 keyframe->update_parameter(&hash, text, 0);
257 printf("KeyFrameThread::apply_value %d: plugin doesn't exist\n", __LINE__);
260 mwindow->save_backup();
261 mwindow->undo->update_undo_after(_("edit keyframe"), LOAD_AUTOMATION);
263 mwindow->update_plugin_guis(0);
264 mwindow->gui->draw_overlays(1);
265 mwindow->sync_parameters(CHANGE_PARAMS);
269 mwindow->gui->unlock_window();
273 get_gui()->lock_window("KeyFrameThread::apply_value");
277 KeyFrameWindow::KeyFrameWindow(MWindow *mwindow,
278 KeyFrameThread *thread, int x, int y, char *title_string)
279 : BC_Window(title_string, x, y,
280 mwindow->session->keyframedialog_w,
281 mwindow->session->keyframedialog_h,
284 this->mwindow = mwindow;
285 this->thread = thread;
288 void KeyFrameWindow::create_objects()
290 Theme *theme = mwindow->theme;
292 theme->get_keyframedialog_sizes(this);
293 thread->column_width[0] = mwindow->session->keyframedialog_column1;
294 thread->column_width[1] = mwindow->session->keyframedialog_column2;
295 lock_window("KeyFrameWindow::create_objects");
297 add_subwindow(title1 = new BC_Title(theme->keyframe_list_x,
298 theme->keyframe_list_y -
299 BC_Title::calculate_h(this, (char*)"Py", LARGEFONT) -
300 theme->widget_border,
301 _("Keyframe parameters:"), LARGEFONT));
302 add_subwindow(keyframe_list = new KeyFrameList(thread,
303 this, theme->keyframe_list_x, theme->keyframe_list_y,
304 theme->keyframe_list_w, theme->keyframe_list_h));
305 add_subwindow(title3 = new BC_Title(theme->keyframe_value_x,
306 theme->keyframe_value_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border,
308 add_subwindow(value_text = new KeyFrameValue(thread,
309 this, theme->keyframe_value_x, theme->keyframe_value_y, theme->keyframe_value_w));
310 add_subwindow(all_toggle = new KeyFrameAll(thread,
311 this, theme->keyframe_all_x, theme->keyframe_all_y));
313 add_subwindow(new KeyFrameParamsOK(thread, this));
314 add_subwindow(new BC_CancelButton(this));
320 int KeyFrameWindow::resize_event(int w, int h)
322 Theme *theme = mwindow->theme;
323 mwindow->session->keyframedialog_w = w;
324 mwindow->session->keyframedialog_h = h;
325 theme->get_keyframedialog_sizes(this);
327 title1->reposition_window(theme->keyframe_list_x,
328 theme->keyframe_list_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border);
329 title3->reposition_window(theme->keyframe_value_x,
330 theme->keyframe_value_y - BC_Title::calculate_h(this, (char*)"P") - theme->widget_border);
331 keyframe_list->reposition_window(theme->keyframe_list_x, theme->keyframe_list_y,
332 theme->keyframe_list_w, theme->keyframe_list_h);
333 value_text->reposition_window(theme->keyframe_value_x, theme->keyframe_value_y,
334 theme->keyframe_value_w);
335 all_toggle->reposition_window(theme->keyframe_all_x, theme->keyframe_all_y);
340 KeyFrameList::KeyFrameList(KeyFrameThread *thread,
341 KeyFrameWindow *window, int x, int y, int w, int h)
342 : BC_ListBox(x, y, w, h, LISTBOX_TEXT,
343 thread->keyframe_data, (const char **)thread->column_titles,
344 thread->column_width, KEYFRAME_COLUMNS)
346 this->thread = thread;
347 this->window = window;
350 int KeyFrameList::selection_changed()
352 window->value_text->update(
353 thread->keyframe_data[1].get(get_selection_number(0, 0))->get_text());
357 int KeyFrameList::handle_event()
363 int KeyFrameList::column_resize_event()
365 thread->mwindow->session->keyframedialog_column1 = get_column_width(0);
366 thread->mwindow->session->keyframedialog_column2 = get_column_width(1);
371 KeyFrameValue::KeyFrameValue(KeyFrameThread *thread,
372 KeyFrameWindow *window, int x, int y, int w)
373 : BC_TextBox(x, y, w, 1, "")
375 this->thread = thread;
376 this->window = window;
379 int KeyFrameValue::handle_event()
381 thread->update_values();
386 KeyFrameAll::KeyFrameAll(KeyFrameThread *thread,
387 KeyFrameWindow *window, int x, int y)
388 : BC_CheckBox(x, y, thread->mwindow->session->keyframedialog_all,
389 _("Apply to all selected keyframes"))
391 this->thread = thread;
392 this->window = window;
395 int KeyFrameAll::handle_event()
397 thread->mwindow->session->keyframedialog_all = get_value();
401 KeyFrameParamsOK::KeyFrameParamsOK(KeyFrameThread *thread, KeyFrameWindow *window)
402 : BC_OKButton(window)
404 this->thread = thread;
405 this->window = window;
408 int KeyFrameParamsOK::keypress_event()
410 if( get_keypress() == RETURN ) {
411 thread->apply_value();