add auto zoombar/status color, fix 3 batchrender boobies, rotate plugin tweaks, add...
[goodguy/cinelerra.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, 640, 800, 640, 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(x2, y, _("Tracking file:")));
112         add_subwindow(tracking_file = new MotionTrackingFile(plugin,
113                 plugin->config.tracking_file, this, x2+title->get_w() + 20, y));
114
115         int y1 = y;
116         add_subwindow(title = new BC_Title(x, y + 10, _("Block X:")));
117         add_subwindow(block_x =
118                 new MotionBlockX(plugin, this, x + title->get_w() + 10, y));
119         add_subwindow(block_x_text =
120                 new MotionBlockXText(plugin, this,
121                         x + title->get_w() + 10 + block_x->get_w() + 10, y + 10));
122
123         y += 40;
124         add_subwindow(title = new BC_Title(x2, y, _("Rotation center:")));
125         add_subwindow(rotation_center =
126                 new RotationCenter(plugin, x2 + title->get_w() + 10, y));
127
128         y += 40;
129         add_subwindow(title = new BC_Title(x2, y + 10, _("Maximum angle offset:")));
130         add_subwindow(rotate_magnitude =
131                 new MotionRMagnitude(plugin, x2 + title->get_w() + 10, y));
132
133         y += 40;
134         add_subwindow(title = new BC_Title(x2, y + 10, _("Rotation settling speed:")));
135         add_subwindow(rotate_return_speed =
136                 new MotionRReturnSpeed(plugin, x2 + title->get_w() + 10, y));
137         y += 40;
138         add_subwindow(vectors = new MotionDrawVectors(plugin, this, x2, y));
139
140         y = y1 + 60;
141         add_subwindow(title = new BC_Title(x, y + 10, _("Block Y:")));
142         add_subwindow(block_y =
143                 new MotionBlockY(plugin, this, x + title->get_w() + 10, y));
144         add_subwindow(block_y_text =
145                 new MotionBlockYText(plugin, this,
146                         x + title->get_w() + 10 + block_y->get_w() + 10, y + 10));
147
148         y += 50;
149         add_subwindow(title = new BC_Title(x, y + 10, _("Maximum absolute offset:")));
150         add_subwindow(magnitude = new MotionMagnitude(plugin,
151                 x + title->get_w() + 10,
152                 y));
153
154         y += 40;
155         add_subwindow(title = new BC_Title(x, y + 10, _("Motion settling speed:")));
156         add_subwindow(return_speed =
157                 new MotionReturnSpeed(plugin, x + title->get_w() + 10, y));
158
159         y += 40;
160         add_subwindow(track_single =
161                 new TrackSingleFrame(plugin, this, x, y));
162         y += 20;
163         add_subwindow(track_previous =
164                 new TrackPreviousFrame(plugin, this, x, y));
165         y += 20;
166         add_subwindow(previous_same =
167                 new PreviousFrameSameBlock(plugin, this, x, y));
168
169         y += 40;
170         x1 = x;  y1 = y;
171         add_subwindow(title =
172                 new BC_Title(x1=x2, y1, _("Frame number:")));
173         add_subwindow(track_frame_number =
174                 new TrackFrameNumber(plugin, this, x1 += title->get_w(), y1));
175         if(plugin->config.tracking_object != MotionScan::TRACK_SINGLE)
176                 track_frame_number->disable();
177
178         add_subwindow(addtrackedframeoffset =
179                 new AddTrackedFrameOffset(plugin, this, x1=x2, y1+=track_frame_number->get_h()));
180         int pef = client->server->mwindow->edl->session->video_every_frame;
181         add_subwindow(pef_title = new BC_Title(x1=x2+50, y1+=addtrackedframeoffset->get_h() + 5,
182                 !pef ?  _("For best results\n"
183                                 " Set: Play every frame\n"
184                                 " Preferences-> Playback-> Video Out") :
185                         _("Currently using: Play every frame"), MEDIUMFONT,
186                 !pef ? RED : GREEN));
187
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 }
612
613 int TrackFrameNumber::handle_event()
614 {
615         plugin->config.track_frame = atol(get_text());
616         plugin->send_configure_change();
617         return 1;
618 }
619
620
621 TrackPreviousFrame::TrackPreviousFrame(MotionMain *plugin,
622         MotionWindow *gui,
623         int x,
624         int y)
625  : BC_Radial(x,
626         y,
627         plugin->config.tracking_object == MotionScan::TRACK_PREVIOUS,
628         _("Track previous frame"))
629 {
630         this->plugin = plugin;
631         this->gui = gui;
632 }
633 int TrackPreviousFrame::handle_event()
634 {
635         plugin->config.tracking_object = MotionScan::TRACK_PREVIOUS;
636         gui->track_single->update(0);
637         gui->previous_same->update(0);
638         gui->track_frame_number->disable();
639         plugin->send_configure_change();
640         return 1;
641 }
642
643
644 PreviousFrameSameBlock::PreviousFrameSameBlock(MotionMain *plugin,
645         MotionWindow *gui,
646         int x,
647         int y)
648  : BC_Radial(x,
649         y,
650         plugin->config.tracking_object == MotionScan::PREVIOUS_SAME_BLOCK,
651         _("Previous frame same block"))
652 {
653         this->plugin = plugin;
654         this->gui = gui;
655 }
656 int PreviousFrameSameBlock::handle_event()
657 {
658         plugin->config.tracking_object = MotionScan::PREVIOUS_SAME_BLOCK;
659         gui->track_single->update(0);
660         gui->track_previous->update(0);
661         gui->track_frame_number->disable();
662         plugin->send_configure_change();
663         return 1;
664 }
665
666
667 MasterLayer::MasterLayer(MotionMain *plugin, MotionWindow *gui, int x, int y)
668  : BC_PopupMenu(x,
669         y,
670         calculate_w(gui),
671         to_text(plugin->config.bottom_is_master))
672 {
673         this->plugin = plugin;
674         this->gui = gui;
675 }
676
677 int MasterLayer::handle_event()
678 {
679         plugin->config.bottom_is_master = from_text(get_text());
680         plugin->send_configure_change();
681         return 1;
682 }
683
684 void MasterLayer::create_objects()
685 {
686         add_item(new BC_MenuItem(to_text(0)));
687         add_item(new BC_MenuItem(to_text(1)));
688 }
689
690 int MasterLayer::from_text(char *text)
691 {
692         if(!strcmp(text, _("Top"))) return 0;
693         return 1;
694 }
695
696 char* MasterLayer::to_text(int mode)
697 {
698         return mode ? _("Bottom") : _("Top");
699 }
700
701 int MasterLayer::calculate_w(MotionWindow *gui)
702 {
703         int result = 0;
704         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0)));
705         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1)));
706         return result + 50;
707 }
708
709
710 ActionType::ActionType(MotionMain *plugin, MotionWindow *gui, int x, int y)
711  : BC_PopupMenu(x,
712         y,
713         calculate_w(gui),
714         to_text(plugin->config.action_type))
715 {
716         this->plugin = plugin;
717         this->gui = gui;
718 }
719
720 int ActionType::handle_event()
721 {
722         plugin->config.action_type = from_text(get_text());
723         plugin->send_configure_change();
724         return 1;
725 }
726
727 void ActionType::create_objects()
728 {
729         add_item(new BC_MenuItem(to_text(MotionScan::TRACK)));
730         add_item(new BC_MenuItem(to_text(MotionScan::TRACK_PIXEL)));
731         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE)));
732         add_item(new BC_MenuItem(to_text(MotionScan::STABILIZE_PIXEL)));
733         add_item(new BC_MenuItem(to_text(MotionScan::NOTHING)));
734 }
735
736 int ActionType::from_text(char *text)
737 {
738         if(!strcmp(text, _("Track Subpixel"))) return MotionScan::TRACK;
739         if(!strcmp(text, _("Track Pixel"))) return MotionScan::TRACK_PIXEL;
740         if(!strcmp(text, _("Stabilize Subpixel"))) return MotionScan::STABILIZE;
741         if(!strcmp(text, _("Stabilize Pixel"))) return MotionScan::STABILIZE_PIXEL;
742         //if(!strcmp(text, _("Do Nothing"))) return MotionScan::NOTHING;
743         return MotionScan::NOTHING;
744 }
745
746 char* ActionType::to_text(int mode)
747 {
748         switch(mode)
749         {
750                 case MotionScan::TRACK:
751                         return _("Track Subpixel");
752                 case MotionScan::TRACK_PIXEL:
753                         return _("Track Pixel");
754                 case MotionScan::STABILIZE:
755                         return _("Stabilize Subpixel");
756                 case MotionScan::STABILIZE_PIXEL:
757                         return _("Stabilize Pixel");
758                 default:
759                 case MotionScan::NOTHING:
760                         return _("Do Nothing");
761         }
762 }
763
764 int ActionType::calculate_w(MotionWindow *gui)
765 {
766         int result = 0;
767         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK)));
768         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::TRACK_PIXEL)));
769         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE)));
770         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::STABILIZE_PIXEL)));
771         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NOTHING)));
772         return result + 50;
773 }
774
775
776 TrackingType::TrackingType(MotionMain *plugin, MotionWindow *gui, int x, int y)
777  : BC_PopupMenu(x,
778         y,
779         calculate_w(gui),
780         to_text(plugin->config.tracking_type))
781 {
782         this->plugin = plugin;
783         this->gui = gui;
784 }
785
786 int TrackingType::handle_event()
787 {
788         plugin->config.tracking_type = from_text(get_text());
789         plugin->send_configure_change();
790         return 1;
791 }
792
793 void TrackingType::create_objects()
794 {
795         add_item(new BC_MenuItem(to_text(MotionScan::SAVE)));
796         add_item(new BC_MenuItem(to_text(MotionScan::LOAD)));
797         add_item(new BC_MenuItem(to_text(MotionScan::CALCULATE)));
798         add_item(new BC_MenuItem(to_text(MotionScan::NO_CALCULATE)));
799 }
800
801 int TrackingType::from_text(char *text)
802 {
803         if(!strcmp(text, _("Save coords to tracking file"))) return MotionScan::SAVE;
804         if(!strcmp(text, _("Load coords from tracking file"))) return MotionScan::LOAD;
805         if(!strcmp(text, _("Recalculate"))) return MotionScan::CALCULATE;
806         //if(!strcmp(text, _("Don't Calculate"))) return MotionScan::NO_CALCULATE;
807         return MotionScan::NO_CALCULATE;
808 }
809
810 char* TrackingType::to_text(int mode)
811 {
812         switch(mode)
813         {
814                 case MotionScan::SAVE:          return _("Save coords to tracking file");
815                 case MotionScan::LOAD:          return _("Load coords from tracking file");
816                 case MotionScan::CALCULATE:     return _("Recalculate");
817                 default:
818                 case MotionScan::NO_CALCULATE:  return _("Don't Calculate");
819         }
820 }
821
822 int TrackingType::calculate_w(MotionWindow *gui)
823 {
824         int result = 0;
825         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::NO_CALCULATE)));
826         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::CALCULATE)));
827         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::SAVE)));
828         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionScan::LOAD)));
829         return result + 50;
830 }
831
832
833 TrackDirection::TrackDirection(MotionMain *plugin, MotionWindow *gui, int x, int y)
834  : BC_PopupMenu(x,
835         y,
836         calculate_w(gui),
837         to_text(plugin->config.horizontal_only, plugin->config.vertical_only))
838 {
839         this->plugin = plugin;
840         this->gui = gui;
841 }
842
843 int TrackDirection::handle_event()
844 {
845         from_text(&plugin->config.horizontal_only, &plugin->config.vertical_only, get_text());
846         plugin->send_configure_change();
847         return 1;
848 }
849
850 void TrackDirection::create_objects()
851 {
852         add_item(new BC_MenuItem(to_text(1, 0)));
853         add_item(new BC_MenuItem(to_text(0, 1)));
854         add_item(new BC_MenuItem(to_text(0, 0)));
855 }
856
857 void TrackDirection::from_text(int *horizontal_only, int *vertical_only, char *text)
858 {
859         *horizontal_only = 0;
860         *vertical_only = 0;
861         if(!strcmp(text, to_text(1, 0))) *horizontal_only = 1;
862         if(!strcmp(text, to_text(0, 1))) *vertical_only = 1;
863 }
864
865 char* TrackDirection::to_text(int horizontal_only, int vertical_only)
866 {
867         if(horizontal_only) return _("Horizontal only");
868         if(vertical_only) return _("Vertical only");
869         return _("Both");
870 }
871
872 int TrackDirection::calculate_w(MotionWindow *gui)
873 {
874         int result = 0;
875         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0)));
876         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1)));
877         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0)));
878         return result + 50;
879 }
880