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