78097b8c7e583238d99c9dff9ff46dcd28301093
[goodguy/history.git] / cinelerra-5.1 / plugins / motion / motionwindow.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2012 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 "edl.h"
25 #include "fonts.h"
26 #include "edlsession.h"
27 #include "language.h"
28 #include "motion.h"
29 #include "motionscan.h"
30 #include "motionwindow.h"
31 #include "mwindow.h"
32 #include "pluginserver.h"
33
34 MotionWindow::MotionWindow(MotionMain *plugin)
35  : PluginClientWindow(plugin, 800, 660, 800, 660, 0)
36 {
37         this->plugin = plugin;
38 }
39
40 MotionWindow::~MotionWindow()
41 {
42 }
43
44 void MotionWindow::create_objects()
45 {
46         int x = 10, y = 10;
47         int x1 = x, x2 = get_w() / 2;
48         BC_Title *title;
49
50         add_subwindow(global = new MotionGlobal(plugin, this, x1, y));
51         add_subwindow(rotate = new MotionRotate(plugin, this, x2, y));
52         y += 50;
53
54         add_subwindow(title = new BC_Title(x1, y,
55                 _("Translation search radius:\n(W/H Percent of image)")));
56         add_subwindow(global_range_w = new GlobalRange(plugin,
57                 x1 + title->get_w() + 10, y,
58                 &plugin->config.global_range_w));
59         add_subwindow(global_range_h = new GlobalRange(plugin,
60                 x1 + title->get_w() + 10 + global_range_w->get_w(), y,
61                 &plugin->config.global_range_h));
62
63         add_subwindow(title = new BC_Title(x2, y,
64                 _("Rotation search radius:\n(Degrees)")));
65         add_subwindow(rotation_range = new RotationRange(plugin,
66                 x2 + title->get_w() + 10, y));
67
68         y += 50;
69         add_subwindow(title = new BC_Title(x1, y,
70                 _("Translation block size:\n(W/H Percent of image)")));
71         add_subwindow(global_block_w =
72                 new BlockSize(plugin, x1 + title->get_w() + 10, y,
73                 &plugin->config.global_block_w));
74         add_subwindow(global_block_h =
75                 new BlockSize(plugin, x1 + title->get_w() + 10 +
76                         global_block_w->get_w(), y,
77                         &plugin->config.global_block_h));
78
79 //      add_subwindow(title = new BC_Title(x2,
80 //              y,
81 //              _("Rotation block size:\n(W/H Percent of image)")));
82 //      add_subwindow(rotation_block_w = new BlockSize(plugin,
83 //              x2 + title->get_w() + 10,
84 //              y,
85 //              &plugin->config.rotation_block_w));
86 //      add_subwindow(rotation_block_h = new BlockSize(plugin,
87 //              x2 + title->get_w() + 10 + rotation_block_w->get_w(),
88 //              y,
89 //              &plugin->config.rotation_block_h));
90
91         y += 50;
92         add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:")));
93         add_subwindow(global_search_positions =
94                 new GlobalSearchPositions(plugin, x1 + title->get_w() + 10, y, 80));
95         global_search_positions->create_objects();
96
97         add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:")));
98         add_subwindow(rotation_search_positions =
99                 new RotationSearchPositions(plugin, x2 + title->get_w() + 10, y, 80));
100         rotation_search_positions->create_objects();
101
102         y += 50;
103         add_subwindow(title = new BC_Title(x, y, _("Translation direction:")));
104         add_subwindow(track_direction = new TrackDirection(plugin,
105                 this,
106                 x + title->get_w() + 10,
107                 y));
108         track_direction->create_objects();
109
110         y += 40;
111         add_subwindow(title = new BC_Title(x, y + 10, _("Block X:")));
112         add_subwindow(block_x =
113                 new MotionBlockX(plugin, this, x + title->get_w() + 10, y));
114         add_subwindow(block_x_text =
115                 new MotionBlockXText(plugin, this,
116                         x + title->get_w() + 10 + block_x->get_w() + 10, y + 10));
117
118         add_subwindow(title = new BC_Title(x2, y, _("Rotation center:")));
119         add_subwindow(rotation_center =
120                 new RotationCenter(plugin, x2 + title->get_w() + 10, y));
121
122         int y1 = y;
123         y += 50;
124         add_subwindow(title = new BC_Title(x2, y + 10, _("Maximum angle offset:")));
125         add_subwindow(rotate_magnitude =
126                 new MotionRMagnitude(plugin, x2 + title->get_w() + 10, y));
127
128         y += 40;
129         add_subwindow(title = new BC_Title(x2, y + 10, _("Rotation settling speed:")));
130         add_subwindow(rotate_return_speed =
131                 new MotionRReturnSpeed(plugin, x2 + title->get_w() + 10, y));
132
133         y = y1;
134         y += 40;
135         add_subwindow(title = new BC_Title(x, y + 10, _("Block Y:")));
136         add_subwindow(block_y =
137                 new MotionBlockY(plugin, this, x + title->get_w() + 10, y));
138         add_subwindow(block_y_text =
139                 new MotionBlockYText(plugin, this,
140                         x + title->get_w() + 10 + block_y->get_w() + 10, y + 10));
141
142         y += 50;
143         add_subwindow(title = new BC_Title(x, y + 10, _("Maximum absolute offset:")));
144         add_subwindow(magnitude = new MotionMagnitude(plugin,
145                 x + title->get_w() + 10,
146                 y));
147
148         y += 40;
149         add_subwindow(title = new BC_Title(x, y + 10, _("Motion settling speed:")));
150         add_subwindow(return_speed =
151                 new MotionReturnSpeed(plugin, x + title->get_w() + 10, y));
152
153         y += 40;
154         add_subwindow(vectors = new MotionDrawVectors(plugin, this, x, y));
155
156         add_subwindow(title = new BC_Title(x2, y, _("Tracking file:")));
157         add_subwindow(tracking_file = new MotionTrackingFile(plugin,
158                 plugin->config.tracking_file, this, x2+title->get_w() + 20, y));
159
160         y += 40;
161         x1 = x;  y1 = y;
162         add_subwindow(track_single =
163                 new TrackSingleFrame(plugin, this, x1, y1));
164         add_subwindow(title =
165                 new BC_Title(x1=x2, y1, _("Frame number:")));
166         add_subwindow(track_frame_number =
167                 new TrackFrameNumber(plugin, this, x1 += title->get_w(), y1));
168         add_subwindow(addtrackedframeoffset =
169                 new AddTrackedFrameOffset(plugin, this, x1=x2, y1+=track_frame_number->get_h()));
170         int pef = client->server->mwindow->edl->session->video_every_frame;
171         add_subwindow(pef_title = new BC_Title(x1=x2, y1+=addtrackedframeoffset->get_h() + 5,
172                 !pef ?  _("For best results\n"
173                                 " Set: Play every frame\n"
174                                 " Preferences-> Playback-> Video Out") :
175                         _("Currently using: Play every frame"), MEDIUMFONT,
176                 !pef ? RED : GREEN));
177
178         y += 20;
179         add_subwindow(track_previous =
180                 new TrackPreviousFrame(plugin, this, x, y));
181
182         y += 20;
183         add_subwindow(previous_same =
184                 new PreviousFrameSameBlock(plugin, this, x, y));
185
186         y += 40;
187         y1 = y;
188         add_subwindow(title = new BC_Title(x, y, _("Master layer:")));
189         add_subwindow(master_layer = new MasterLayer(plugin,
190                 this, x + title->get_w() + 10, y));
191         master_layer->create_objects();
192         y += 30;
193
194         add_subwindow(title = new BC_Title(x, y, _("Action:")));
195         add_subwindow(action_type = new ActionType(plugin,
196                 this, x + title->get_w() + 10, y));
197         action_type->create_objects();
198         y += 30;
199
200         add_subwindow(title = new BC_Title(x, y, _("Calculation:")));
201         add_subwindow(tracking_type = new TrackingType(plugin,
202                 this, x + title->get_w() + 10, y));
203         tracking_type->create_objects();
204
205         show_window(1);
206 }
207
208 void MotionWindow::update_mode()
209 {
210         global_range_w->update(plugin->config.global_range_w,
211                 MIN_RADIUS, MAX_RADIUS);
212         global_range_h->update(plugin->config.global_range_h,
213                 MIN_RADIUS, MAX_RADIUS);
214         rotation_range->update(plugin->config.rotation_range,
215                 MIN_ROTATION, MAX_ROTATION);
216         vectors->update(plugin->config.draw_vectors);
217         tracking_file->update(plugin->config.tracking_file);
218         global->update(plugin->config.global);
219         rotate->update(plugin->config.rotate);
220         addtrackedframeoffset->update(plugin->config.addtrackedframeoffset);
221 }
222
223 MotionTrackingFile::MotionTrackingFile(MotionMain *plugin,
224         const char *filename, MotionWindow *gui, int x, int y)
225  : BC_TextBox(x, y, 150, 1, filename)
226 {
227         this->plugin = plugin;
228         this->gui = gui;
229 };
230
231 int MotionTrackingFile::handle_event()
232 {
233         strcpy(plugin->config.tracking_file, get_text());
234         plugin->send_configure_change();
235         return 1;
236 }
237
238
239 GlobalRange::GlobalRange(MotionMain *plugin,
240         int x, int y, int *value)
241  : BC_IPot(x, y, (int64_t)*value,
242         (int64_t)MIN_RADIUS, (int64_t)MAX_RADIUS)
243 {
244         this->plugin = plugin;
245         this->value = value;
246 }
247
248
249 int GlobalRange::handle_event()
250 {
251         *value = (int)get_value();
252         plugin->send_configure_change();
253         return 1;
254 }
255
256
257
258
259 RotationRange::RotationRange(MotionMain *plugin, int x, int y)
260  : BC_IPot(x, y, (int64_t)plugin->config.rotation_range,
261         (int64_t)MIN_ROTATION, (int64_t)MAX_ROTATION)
262 {
263         this->plugin = plugin;
264 }
265
266
267 int RotationRange::handle_event()
268 {
269         plugin->config.rotation_range = (int)get_value();
270         plugin->send_configure_change();
271         return 1;
272 }
273
274
275 RotationCenter::RotationCenter(MotionMain *plugin, int x, int y)
276  : BC_IPot(x, y, (int64_t)plugin->config.rotation_center,
277         (int64_t)-MAX_ROTATION, (int64_t)MAX_ROTATION)
278 {
279         this->plugin = plugin;
280 }
281
282
283 int RotationCenter::handle_event()
284 {
285         plugin->config.rotation_center = (int)get_value();
286         plugin->send_configure_change();
287         return 1;
288 }
289
290
291 BlockSize::BlockSize(MotionMain *plugin,
292         int x,
293         int y,
294         int *value)
295  : BC_IPot(x,
296                 y,
297                 (int64_t)*value,
298                 (int64_t)MIN_BLOCK,
299                 (int64_t)MAX_BLOCK)
300 {
301         this->plugin = plugin;
302         this->value = value;
303 }
304
305
306 int BlockSize::handle_event()
307 {
308         *value = (int)get_value();
309         plugin->send_configure_change();
310         return 1;
311 }
312
313
314 GlobalSearchPositions::GlobalSearchPositions(MotionMain *plugin,
315         int x, int y, int w)
316  : BC_PopupMenu(x, y, w, "", 1)
317 {
318         this->plugin = plugin;
319 }
320 void GlobalSearchPositions::create_objects()
321 {
322         add_item(new BC_MenuItem("16"));
323         add_item(new BC_MenuItem("32"));
324         add_item(new BC_MenuItem("64"));
325         add_item(new BC_MenuItem("128"));
326         add_item(new BC_MenuItem("256"));
327         add_item(new BC_MenuItem("512"));
328         add_item(new BC_MenuItem("1024"));
329         add_item(new BC_MenuItem("2048"));
330         add_item(new BC_MenuItem("4096"));
331         add_item(new BC_MenuItem("8192"));
332         add_item(new BC_MenuItem("16384"));
333         add_item(new BC_MenuItem("32768"));
334         add_item(new BC_MenuItem("65536"));
335         add_item(new BC_MenuItem("131072"));
336         char string[BCTEXTLEN];
337         sprintf(string, "%d", plugin->config.global_positions);
338         set_text(string);
339 }
340
341 int GlobalSearchPositions::handle_event()
342 {
343         plugin->config.global_positions = atoi(get_text());
344         plugin->send_configure_change();
345         return 1;
346 }
347
348
349 RotationSearchPositions::RotationSearchPositions(MotionMain *plugin,
350         int x, int y, int w)
351  : BC_PopupMenu(x, y, w, "", 1)
352 {
353         this->plugin = plugin;
354 }
355 void RotationSearchPositions::create_objects()
356 {
357         add_item(new BC_MenuItem("4"));
358         add_item(new BC_MenuItem("8"));
359         add_item(new BC_MenuItem("16"));
360         add_item(new BC_MenuItem("32"));
361         char string[BCTEXTLEN];
362         sprintf(string, "%d", plugin->config.rotate_positions);
363         set_text(string);
364 }
365
366 int RotationSearchPositions::handle_event()
367 {
368         plugin->config.rotate_positions = atoi(get_text());
369         plugin->send_configure_change();
370         return 1;
371 }
372
373
374 MotionMagnitude::MotionMagnitude(MotionMain *plugin, int x, int y)
375  : BC_IPot(x, y,
376         (int64_t)plugin->config.magnitude, (int64_t)0, (int64_t)100)
377 {
378         this->plugin = plugin;
379 }
380
381 int MotionMagnitude::handle_event()
382 {
383         plugin->config.magnitude = (int)get_value();
384         plugin->send_configure_change();
385         return 1;
386 }
387
388
389 MotionReturnSpeed::MotionReturnSpeed(MotionMain *plugin, int x, int y)
390  : BC_IPot(x, y,
391         (int64_t)plugin->config.return_speed, (int64_t)0, (int64_t)100)
392 {
393         this->plugin = plugin;
394 }
395
396 int MotionReturnSpeed::handle_event()
397 {
398         plugin->config.return_speed = (int)get_value();
399         plugin->send_configure_change();
400         return 1;
401 }
402
403
404
405 AddTrackedFrameOffset::AddTrackedFrameOffset(MotionMain *plugin,
406         MotionWindow *gui, int x, int y)
407  : BC_CheckBox(x, y, plugin->config.addtrackedframeoffset,
408         _("Add (loaded) offset from tracked frame"))
409 {
410         this->plugin = plugin;
411         this->gui = gui;
412 }
413
414 int AddTrackedFrameOffset::handle_event()
415 {
416         plugin->config.addtrackedframeoffset = get_value();
417         plugin->send_configure_change();
418         return 1;
419 }
420
421
422 MotionRMagnitude::MotionRMagnitude(MotionMain *plugin, int x, int y)
423  : BC_IPot(x, y,
424         (int64_t)plugin->config.rotate_magnitude, (int64_t)0, (int64_t)90)
425 {
426         this->plugin = plugin;
427 }
428
429 int MotionRMagnitude::handle_event()
430 {
431         plugin->config.rotate_magnitude = (int)get_value();
432         plugin->send_configure_change();
433         return 1;
434 }
435
436
437
438 MotionRReturnSpeed::MotionRReturnSpeed(MotionMain *plugin, int x, int y)
439  : BC_IPot(x, y,
440         (int64_t)plugin->config.rotate_return_speed, (int64_t)0, (int64_t)100)
441 {
442         this->plugin = plugin;
443 }
444
445 int MotionRReturnSpeed::handle_event()
446 {
447         plugin->config.rotate_return_speed = (int)get_value();
448         plugin->send_configure_change();
449         return 1;
450 }
451
452
453 MotionGlobal::MotionGlobal(MotionMain *plugin,
454         MotionWindow *gui, int x, int y)
455  : BC_CheckBox(x, y, plugin->config.global, _("Track translation"))
456 {
457         this->plugin = plugin;
458         this->gui = gui;
459 }
460
461 int MotionGlobal::handle_event()
462 {
463         plugin->config.global = get_value();
464         plugin->send_configure_change();
465         return 1;
466 }
467
468 MotionRotate::MotionRotate(MotionMain *plugin,
469         MotionWindow *gui, int x, int y)
470  : BC_CheckBox(x, y, plugin->config.rotate, _("Track rotation"))
471 {
472         this->plugin = plugin;
473         this->gui = gui;
474 }
475
476 int MotionRotate::handle_event()
477 {
478         plugin->config.rotate = get_value();
479         plugin->send_configure_change();
480         return 1;
481 }
482
483
484 MotionBlockX::MotionBlockX(MotionMain *plugin,
485         MotionWindow *gui, int x, int y)
486  : BC_FPot(x, y, plugin->config.block_x, (float)0, (float)100)
487 {
488         this->plugin = plugin;
489         this->gui = gui;
490 }
491
492 int MotionBlockX::handle_event()
493 {
494         plugin->config.block_x = get_value();
495         gui->block_x_text->update((float)plugin->config.block_x);
496         plugin->send_configure_change();
497         return 1;
498 }
499
500
501 MotionBlockY::MotionBlockY(MotionMain *plugin,
502         MotionWindow *gui,
503         int x,
504         int y)
505  : BC_FPot(x,
506         y,
507         (float)plugin->config.block_y,
508         (float)0,
509         (float)100)
510 {
511         this->plugin = plugin;
512         this->gui = gui;
513 }
514
515 int MotionBlockY::handle_event()
516 {
517         plugin->config.block_y = get_value();
518         gui->block_y_text->update((float)plugin->config.block_y);
519         plugin->send_configure_change();
520         return 1;
521 }
522
523 MotionBlockXText::MotionBlockXText(MotionMain *plugin,
524         MotionWindow *gui, int x, int y)
525  : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_x)
526 {
527         this->plugin = plugin;
528         this->gui = gui;
529         set_precision(4);
530 }
531
532 int MotionBlockXText::handle_event()
533 {
534         plugin->config.block_x = atof(get_text());
535         gui->block_x->update(plugin->config.block_x);
536         plugin->send_configure_change();
537         return 1;
538 }
539
540
541
542
543 MotionBlockYText::MotionBlockYText(MotionMain *plugin,
544         MotionWindow *gui, int x, int y)
545  : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_y)
546 {
547         this->plugin = plugin;
548         this->gui = gui;
549         set_precision(4);
550 }
551
552 int MotionBlockYText::handle_event()
553 {
554         plugin->config.block_y = atof(get_text());
555         gui->block_y->update(plugin->config.block_y);
556         plugin->send_configure_change();
557         return 1;
558 }
559
560
561 MotionDrawVectors::MotionDrawVectors(MotionMain *plugin,
562         MotionWindow *gui, int x, int y)
563  : BC_CheckBox(x,
564         y,
565         plugin->config.draw_vectors,
566         _("Draw vectors"))
567 {
568         this->gui = gui;
569         this->plugin = plugin;
570 }
571
572 int MotionDrawVectors::handle_event()
573 {
574         plugin->config.draw_vectors = get_value();
575         plugin->send_configure_change();
576         return 1;
577 }
578
579
580 TrackSingleFrame::TrackSingleFrame(MotionMain *plugin,
581         MotionWindow *gui,
582         int x,
583         int y)
584  : BC_Radial(x,
585         y,
586         plugin->config.tracking_object == MotionScan::TRACK_SINGLE,
587         _("Track single frame"))
588 {
589         this->plugin = plugin;
590         this->gui = gui;
591 }
592
593 int TrackSingleFrame::handle_event()
594 {
595         plugin->config.tracking_object = MotionScan::TRACK_SINGLE;
596         gui->track_previous->update(0);
597         gui->previous_same->update(0);
598         gui->track_frame_number->enable();
599         plugin->send_configure_change();
600         return 1;
601 }
602
603 TrackFrameNumber::TrackFrameNumber(MotionMain *plugin,
604         MotionWindow *gui,
605         int x,
606         int y)
607  : BC_TextBox(x, y, 100, 1, plugin->config.track_frame)
608 {
609         this->plugin = plugin;
610         this->gui = gui;
611         if(plugin->config.tracking_object != MotionScan::TRACK_SINGLE) disable();
612 }
613
614 int TrackFrameNumber::handle_event()
615 {
616         plugin->config.track_frame = atol(get_text());
617         plugin->send_configure_change();
618         return 1;
619 }
620
621
622 TrackPreviousFrame::TrackPreviousFrame(MotionMain *plugin,
623         MotionWindow *gui,
624         int x,
625         int y)
626  : BC_Radial(x,
627         y,
628         plugin->config.tracking_object == MotionScan::TRACK_PREVIOUS,
629         _("Track previous frame"))
630 {
631         this->plugin = plugin;
632         this->gui = gui;
633 }
634 int TrackPreviousFrame::handle_event()
635 {
636         plugin->config.tracking_object = MotionScan::TRACK_PREVIOUS;
637         gui->track_single->update(0);
638         gui->previous_same->update(0);
639         gui->track_frame_number->disable();
640         plugin->send_configure_change();
641         return 1;
642 }
643
644
645 PreviousFrameSameBlock::PreviousFrameSameBlock(MotionMain *plugin,
646         MotionWindow *gui,
647         int x,
648         int y)
649  : BC_Radial(x,
650         y,
651         plugin->config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK,
652         _("Previous frame same block"))
653 {
654         this->plugin = plugin;
655         this->gui = gui;
656 }
657 int PreviousFrameSameBlock::handle_event()
658 {
659         plugin->config.tracking_object = MotionScan::PREVIOUS_SAME_BLOCK;
660         gui->track_single->update(0);
661         gui->track_previous->update(0);
662         gui->track_frame_number->disable();
663         plugin->send_configure_change();
664         return 1;
665 }
666
667
668 MasterLayer::MasterLayer(MotionMain *plugin, MotionWindow *gui, int x, int y)
669  : BC_PopupMenu(x,
670         y,
671         calculate_w(gui),
672         to_text(plugin->config.bottom_is_master))
673 {
674         this->plugin = plugin;
675         this->gui = gui;
676 }
677
678 int MasterLayer::handle_event()
679 {
680         plugin->config.bottom_is_master = from_text(get_text());
681         plugin->send_configure_change();
682         return 1;
683 }
684
685 void MasterLayer::create_objects()
686 {
687         add_item(new BC_MenuItem(to_text(0)));
688         add_item(new BC_MenuItem(to_text(1)));
689 }
690
691 int MasterLayer::from_text(char *text)
692 {
693         if(!strcmp(text, _("Top"))) return 0;
694         return 1;
695 }
696
697 char* MasterLayer::to_text(int mode)
698 {
699         return mode ? _("Bottom") : _("Top");
700 }
701
702 int MasterLayer::calculate_w(MotionWindow *gui)
703 {
704         int result = 0;
705         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0)));
706         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1)));
707         return result + 50;
708 }
709
710
711 ActionType::ActionType(MotionMain *plugin, MotionWindow *gui, int x, int y)
712  : BC_PopupMenu(x,
713         y,
714         calculate_w(gui),
715         to_text(plugin->config.action_type))
716 {
717         this->plugin = plugin;
718         this->gui = gui;
719 }
720
721 int ActionType::handle_event()
722 {
723         plugin->config.action_type = from_text(get_text());
724         plugin->send_configure_change();
725         return 1;
726 }
727
728 void ActionType::create_objects()
729 {
730         add_item(new BC_MenuItem(to_text(MotionScan::TRACK)));
731         add_item(new BC_MenuItem(to_text(MotionScan::TRACK_PIXEL)));
732         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE)));
733         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE_PIXEL)));
734         add_item(new BC_MenuItem(to_text(MotionScan::NOTHING)));
735 }
736
737 int ActionType::from_text(char *text)
738 {
739         if(!strcmp(text, _("Track Subpixel"))) return MotionScan::TRACK;
740         if(!strcmp(text, _("Track Pixel"))) return MotionScan::TRACK_PIXEL;
741         if(!strcmp(text, _("Stabilize Subpixel"))) return MotionScan::STABILIZE;
742         if(!strcmp(text, _("Stabilize Pixel"))) return MotionScan::STABILIZE_PIXEL;
743         //if(!strcmp(text, _("Do Nothing"))) return MotionScan::NOTHING;
744         return MotionScan::NOTHING;
745 }
746
747 char* ActionType::to_text(int mode)
748 {
749         switch(mode)
750         {
751                 case MotionScan::TRACK:
752                         return _("Track Subpixel");
753                 case MotionScan::TRACK_PIXEL:
754                         return _("Track Pixel");
755                 case MotionScan::STABILIZE:
756                         return _("Stabilize Subpixel");
757                 case MotionScan::STABILIZE_PIXEL:
758                         return _("Stabilize Pixel");
759                 default:
760                 case MotionScan::NOTHING:
761                         return _("Do Nothing");
762         }
763 }
764
765 int ActionType::calculate_w(MotionWindow *gui)
766 {
767         int result = 0;
768         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK)));
769         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK_PIXEL)));
770         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE)));
771         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE_PIXEL)));
772         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NOTHING)));
773         return result + 50;
774 }
775
776
777 TrackingType::TrackingType(MotionMain *plugin, MotionWindow *gui, int x, int y)
778  : BC_PopupMenu(x,
779         y,
780         calculate_w(gui),
781         to_text(plugin->config.tracking_type))
782 {
783         this->plugin = plugin;
784         this->gui = gui;
785 }
786
787 int TrackingType::handle_event()
788 {
789         plugin->config.tracking_type = from_text(get_text());
790         plugin->send_configure_change();
791         return 1;
792 }
793
794 void TrackingType::create_objects()
795 {
796         add_item(new BC_MenuItem(to_text(MotionScan::SAVE)));
797         add_item(new BC_MenuItem(to_text(MotionScan::LOAD)));
798         add_item(new BC_MenuItem(to_text(MotionScan::CALCULATE)));
799         add_item(new BC_MenuItem(to_text(MotionScan::NO_CALCULATE)));
800 }
801
802 int TrackingType::from_text(char *text)
803 {
804         if(!strcmp(text, _("Save coords to tracking file"))) return MotionScan::SAVE;
805         if(!strcmp(text, _("Load coords from tracking file"))) return MotionScan::LOAD;
806         if(!strcmp(text, _("Recalculate"))) return MotionScan::CALCULATE;
807         //if(!strcmp(text, _("Don't Calculate"))) return MotionScan::NO_CALCULATE;
808         return MotionScan::NO_CALCULATE;
809 }
810
811 char* TrackingType::to_text(int mode)
812 {
813         switch(mode)
814         {
815                 case MotionScan::SAVE:          return _("Save coords to tracking file");
816                 case MotionScan::LOAD:          return _("Load coords from tracking file");
817                 case MotionScan::CALCULATE:     return _("Recalculate");
818                 default:
819                 case MotionScan::NO_CALCULATE:  return _("Don't Calculate");
820         }
821 }
822
823 int TrackingType::calculate_w(MotionWindow *gui)
824 {
825         int result = 0;
826         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NO_CALCULATE)));
827         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::CALCULATE)));
828         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::SAVE)));
829         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::LOAD)));
830         return result + 50;
831 }
832
833
834 TrackDirection::TrackDirection(MotionMain *plugin, MotionWindow *gui, int x, int y)
835  : BC_PopupMenu(x,
836         y,
837         calculate_w(gui),
838         to_text(plugin->config.horizontal_only, plugin->config.vertical_only))
839 {
840         this->plugin = plugin;
841         this->gui = gui;
842 }
843
844 int TrackDirection::handle_event()
845 {
846         from_text(&plugin->config.horizontal_only, &plugin->config.vertical_only, get_text());
847         plugin->send_configure_change();
848         return 1;
849 }
850
851 void TrackDirection::create_objects()
852 {
853         add_item(new BC_MenuItem(to_text(1, 0)));
854         add_item(new BC_MenuItem(to_text(0, 1)));
855         add_item(new BC_MenuItem(to_text(0, 0)));
856 }
857
858 void TrackDirection::from_text(int *horizontal_only, int *vertical_only, char *text)
859 {
860         *horizontal_only = 0;
861         *vertical_only = 0;
862         if(!strcmp(text, to_text(1, 0))) *horizontal_only = 1;
863         if(!strcmp(text, to_text(0, 1))) *vertical_only = 1;
864 }
865
866 char* TrackDirection::to_text(int horizontal_only, int vertical_only)
867 {
868         if(horizontal_only) return _("Horizontal only");
869         if(vertical_only) return _("Vertical only");
870         return _("Both");
871 }
872
873 int TrackDirection::calculate_w(MotionWindow *gui)
874 {
875         int result = 0;
876         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0)));
877         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1)));
878         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0)));
879         return result + 50;
880 }
881