filebox changes, mts fix, dvd/bd create changes, motionwindow layout
[goodguy/history.git] / cinelerra-5.1 / plugins / motion-cv / motionwindow-cv.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcdisplayinfo.h"
23 #include "clip.h"
24 #include "edl.h"
25 #include "fonts.h"
26 #include "edlsession.h"
27 #include "language.h"
28 #include "motion-cv.h"
29 #include "motionwindow-cv.h"
30 #include "mwindow.h"
31 #include "pluginserver.h"
32
33 MotionCVWindow::MotionCVWindow(MotionCVMain *plugin)
34  : PluginClientWindow(plugin, 815, 600, 815, 600, 0)
35 {
36         this->plugin = plugin;
37 }
38
39 MotionCVWindow::~MotionCVWindow()
40 {
41 }
42
43 void MotionCVWindow::create_objects()
44 {
45         int x1 = 10, x = 10, y = 10;
46         int x2 = 410;
47         BC_Title *title;
48
49         add_subwindow(global = new MotionCVGlobal(plugin, this, x1, y));
50         add_subwindow(rotate = new MotionCVRotate(plugin, this, x2, y));
51         y += 50;
52
53         add_subwindow(title = new BC_Title(x1, y,
54                 _("Translation search radius:\n(W/H Percent of image)")));
55         add_subwindow(global_range_w = new GlobalRange(plugin,
56                         x1 + title->get_w() + 10, y,
57                         &plugin->config.global_range_w));
58         add_subwindow(global_range_h = new GlobalRange(plugin,
59                         x1 + title->get_w() + 30 + global_range_w->get_w(), y,
60                         &plugin->config.global_range_h));
61
62         add_subwindow(title = new BC_Title(x2, y,
63                 _("Rotation search radius:\n(Degrees)")));
64         add_subwindow(rotation_range =
65                       new RotationRange(plugin, x2 + title->get_w() + 10, y));
66
67         y += 50;
68         add_subwindow(title = new BC_Title(x1, y,
69                 _("Translation block size:\n(W/H Percent of image)")));
70         add_subwindow(global_block_w = new BlockSize(plugin,
71                         x1 + title->get_w() + 10, y,
72                         &plugin->config.global_block_w));
73         add_subwindow(global_block_h = new BlockSize(plugin,
74                         x1 + title->get_w() + 30 + global_block_w->get_w(), y,
75                         &plugin->config.global_block_h));
76
77         add_subwindow(title = new BC_Title(x2, y,
78                 _("Rotation block size:\n(W/H Percent of image)")));
79         add_subwindow(rotation_block_w = new BlockSize(plugin,
80                         x2 + title->get_w() + 10, y,
81                         &plugin->config.rotation_block_w));
82         add_subwindow(rotation_block_h = new BlockSize(plugin,
83                         x2 + title->get_w() + 30 + rotation_block_w->get_w(), y,
84                         &plugin->config.rotation_block_h));
85
86         y += 50;
87         add_subwindow(title = new BC_Title(x1, y, _("Translation search steps:")));
88         add_subwindow(global_search_positions = new GlobalSearchPositions(plugin,
89                         x1 + title->get_w() + 10, y, 80));
90         global_search_positions->create_objects();
91
92         add_subwindow(title = new BC_Title(x2, y, _("Rotation search steps:")));
93         add_subwindow(rotation_search_positions = new RotationSearchPositions(plugin,
94                         x2 + title->get_w() + 10, y, 80));
95         rotation_search_positions->create_objects();
96
97         y += 50;
98         add_subwindow(title = new BC_Title(x, y, _("Translation direction:")));
99         add_subwindow(mode3 = new Mode3(plugin,
100                         this, x + title->get_w() + 10, y));
101         mode3->create_objects();
102
103         y += 40;  int y1 = y;
104         add_subwindow(title = new BC_Title(x2, y, _("Tracking file:")));
105         add_subwindow(tracking_file = new MotionCVTrackingFile(plugin,
106                         plugin->config.  tracking_file, this,
107                         x2 + title->get_w() + 20, y));
108         y1 += tracking_file->get_h() + 10;
109
110         add_subwindow(title = new BC_Title(x, y + 10, _("Block X:")));
111         add_subwindow(block_x = new MotionCVBlockX(plugin, this,
112                         x + title->get_w() + 10, y));
113         add_subwindow(block_x_text = new MotionCVBlockXText(plugin,
114                         this, x + title->get_w() + 10 + block_x->get_w() + 10, y + 10));
115
116         y += 40;
117         add_subwindow(title = new BC_Title(x, y + 10, _("Block Y:")));
118         add_subwindow(block_y = new MotionCVBlockY(plugin, this,
119                         x + title->get_w() + 10, y));
120         add_subwindow(block_y_text = new MotionCVBlockYText(plugin, this,
121                         x + title->get_w() + 10 + block_y->get_w() + 10, y + 10));
122
123         add_subwindow(title = new BC_Title(x2, y1 + 10, _("Maximum absolute offset:")));
124         add_subwindow(magnitude = new MotionCVMagnitude(plugin,
125                         x2 + title->get_w() + 10, y1));
126
127         y1 += 40;
128         add_subwindow(title = new BC_Title(x2, y1 + 10, _("Settling speed:")));
129         add_subwindow(return_speed = new MotionCVReturnSpeed(plugin,
130                         x2 + title->get_w() + 10, y1));
131
132         y1 += 40;
133         add_subwindow(vectors = new MotionCVDrawVectors(plugin, this, x2, y1));
134         y = y1 + vectors->get_h() + 10;
135
136         x1 = x;  y1 = y;
137         add_subwindow(track_single =
138                 new TrackSingleFrame(plugin, this, x1, y1));
139         y += 20;
140         add_subwindow(track_previous = new TrackPreviousFrame(plugin, this, x, y));
141         y += 20;
142         add_subwindow(previous_same = new PreviousFrameSameBlock(plugin, this, x, y));
143
144         y += 40;
145         add_subwindow(title = new BC_Title(x, y, _("Master layer:")));
146         add_subwindow(master_layer = new MasterLayer(plugin, this,
147                         x + title->get_w() + 10, y));
148         master_layer->create_objects();
149         add_subwindow(title =
150                 new BC_Title(x1=x2, y1=y, _("Frame number:")));
151         add_subwindow(track_frame_number =
152                 new TrackFrameNumber(plugin, this, x1 += title->get_w(), y1));
153         add_subwindow(addtrackedframeoffset =
154                 new AddTrackedFrameOffset(plugin, this, x1=x2, y1+=track_frame_number->get_h()));
155         int pef = client->server->mwindow->edl->session->video_every_frame;
156         add_subwindow(pef_title = new BC_Title(x1=x2+50, y1+=addtrackedframeoffset->get_h() + 5,
157                 !pef ?  _("For best results\n"
158                                 " Set: Play every frame\n"
159                                 " Preferences-> Playback-> Video Out") :
160                         _("Currently using: Play every frame"), MEDIUMFONT,
161                 !pef ? RED : GREEN));
162
163         y += 30;
164         add_subwindow(title = new BC_Title(x, y, _("Action:")));
165         add_subwindow(mode1 = new Mode1(plugin, this,
166                         x + title->get_w() + 10, y));
167         mode1->create_objects();
168
169         y += 30;
170         add_subwindow(title = new BC_Title(x, y, _("Calculation:")));
171         add_subwindow(mode2 = new Mode2(plugin, this,
172                         x + title->get_w() + 10, y));
173         mode2->create_objects();
174
175         show_window(1);
176 }
177
178 void MotionCVWindow::update_mode()
179 {
180         global_range_w->update(plugin->config.global_range_w, MIN_RADIUS, MAX_RADIUS);
181         global_range_h->update(plugin->config.global_range_h, MIN_RADIUS, MAX_RADIUS);
182         rotation_range->update(plugin->config.rotation_range, MIN_ROTATION, MAX_ROTATION);
183         vectors->update(plugin->config.draw_vectors);
184         tracking_file->update(plugin->config.tracking_file);
185         global->update(plugin->config.global);
186         rotate->update(plugin->config.rotate);
187         addtrackedframeoffset->update(plugin->config.addtrackedframeoffset);
188 }
189
190 GlobalRange::GlobalRange(MotionCVMain *plugin, int x, int y, int *value)
191 :BC_IPot(x, y, (int64_t) * value, (int64_t) MIN_RADIUS, (int64_t) MAX_RADIUS)
192 {
193         this->plugin = plugin;
194         this->value = value;
195 }
196
197 int GlobalRange::handle_event()
198 {
199         *value = (int)get_value();
200         plugin->send_configure_change();
201         return 1;
202 }
203
204 RotationRange::RotationRange(MotionCVMain *plugin, int x, int y)
205  :
206 BC_IPot(x,
207     y, (int64_t) plugin->config.rotation_range,
208     (int64_t) MIN_ROTATION, (int64_t) MAX_ROTATION)
209 {
210         this->plugin = plugin;
211 }
212
213 int RotationRange::handle_event()
214 {
215         plugin->config.rotation_range = (int)get_value();
216         plugin->send_configure_change();
217         return 1;
218 }
219
220 BlockSize::BlockSize(MotionCVMain *plugin, int x, int y, int *value)
221  : BC_IPot(x, y, (int64_t) * value, (int64_t) MIN_BLOCK, (int64_t) MAX_BLOCK)
222 {
223         this->plugin = plugin;
224         this->value = value;
225 }
226
227 int BlockSize::handle_event()
228 {
229         *value = (int)get_value();
230         plugin->send_configure_change();
231         return 1;
232 }
233
234 GlobalSearchPositions::GlobalSearchPositions(MotionCVMain *plugin,
235                                              int x, int y, int w)
236  : BC_PopupMenu(x, y, w, "", 1)
237 {
238         this->plugin = plugin;
239 }
240
241 void GlobalSearchPositions::create_objects()
242 {
243         add_item(new BC_MenuItem("64"));
244         add_item(new BC_MenuItem("128"));
245         add_item(new BC_MenuItem("256"));
246         add_item(new BC_MenuItem("512"));
247         add_item(new BC_MenuItem("1024"));
248         add_item(new BC_MenuItem("2048"));
249         add_item(new BC_MenuItem("4096"));
250         add_item(new BC_MenuItem("8192"));
251         add_item(new BC_MenuItem("16384"));
252         add_item(new BC_MenuItem("32768"));
253         add_item(new BC_MenuItem("65536"));
254         add_item(new BC_MenuItem("131072"));
255         char string[BCTEXTLEN];
256         sprintf(string, "%d", plugin->config.global_positions);
257         set_text(string);
258 }
259
260 int GlobalSearchPositions::handle_event()
261 {
262         plugin->config.global_positions = atoi(get_text());
263         plugin->send_configure_change();
264         return 1;
265 }
266
267 RotationSearchPositions::RotationSearchPositions(MotionCVMain *plugin,
268                 int x, int y, int w)
269  : BC_PopupMenu(x, y, w, "", 1)
270 {
271         this->plugin = plugin;
272 }
273
274 void RotationSearchPositions::create_objects()
275 {
276         add_item(new BC_MenuItem("4"));
277         add_item(new BC_MenuItem("8"));
278         add_item(new BC_MenuItem("16"));
279         add_item(new BC_MenuItem("32"));
280         char string[BCTEXTLEN];
281         sprintf(string, "%d", plugin->config.rotate_positions);
282         set_text(string);
283 }
284
285 int RotationSearchPositions::handle_event()
286 {
287         plugin->config.rotate_positions = atoi(get_text());
288         plugin->send_configure_change();
289         return 1;
290 }
291
292 MotionCVMagnitude::MotionCVMagnitude(MotionCVMain *plugin, int x, int y)
293  : BC_IPot(x, y, (int64_t) plugin->config.magnitude, (int64_t) 0, (int64_t) 100)
294 {
295         this->plugin = plugin;
296 }
297
298 int MotionCVMagnitude::handle_event()
299 {
300         plugin->config.magnitude = (int)get_value();
301         plugin->send_configure_change();
302         return 1;
303 }
304
305 MotionCVReturnSpeed::MotionCVReturnSpeed(MotionCVMain *plugin, int x, int y)
306  : BC_IPot(x, y, (int64_t) plugin->config.return_speed, (int64_t) 0, (int64_t) 100)
307 {
308         this->plugin = plugin;
309 }
310
311 int MotionCVReturnSpeed::handle_event()
312 {
313         plugin->config.return_speed = (int)get_value();
314         plugin->send_configure_change();
315         return 1;
316 }
317
318 AddTrackedFrameOffset::AddTrackedFrameOffset(MotionCVMain *plugin,
319                 MotionCVWindow *gui, int x, int y)
320  : BC_CheckBox(x, y, plugin->config.addtrackedframeoffset,
321         _("Add (loaded) offset from tracked frame"))
322 {
323         this->plugin = plugin;
324         this->gui = gui;
325 }
326
327 int AddTrackedFrameOffset::handle_event()
328 {
329         plugin->config.addtrackedframeoffset = get_value();
330         plugin->send_configure_change();
331         return 1;
332 }
333
334 MotionCVTrackingFile::MotionCVTrackingFile(MotionCVMain *plugin,
335                 const char *filename, MotionCVWindow *gui, int x, int y)
336  : BC_TextBox(x, y, 250, 1, filename)
337 {
338         this->plugin = plugin;
339         this->gui = gui;
340 };
341
342 int MotionCVTrackingFile::handle_event()
343 {
344         strcpy(plugin->config.tracking_file, get_text());
345         plugin->send_configure_change();
346         return 1;
347 }
348
349 MotionCVGlobal::MotionCVGlobal(MotionCVMain *plugin,
350                 MotionCVWindow *gui, int x, int y)
351  :BC_CheckBox(x, y, plugin->config.global, _("Track translation"))
352 {
353         this->plugin = plugin;
354         this->gui = gui;
355 }
356
357 int MotionCVGlobal::handle_event()
358 {
359         plugin->config.global = get_value();
360         plugin->send_configure_change();
361         return 1;
362 }
363
364 MotionCVRotate::MotionCVRotate(MotionCVMain *plugin,
365                 MotionCVWindow *gui, int x, int y)
366  : BC_CheckBox(x, y, plugin->config.rotate, _("Track rotation"))
367 {
368         this->plugin = plugin;
369         this->gui = gui;
370 }
371
372 int MotionCVRotate::handle_event()
373 {
374         plugin->config.rotate = get_value();
375         plugin->send_configure_change();
376         return 1;
377 }
378
379 MotionCVBlockX::MotionCVBlockX(MotionCVMain *plugin,
380                 MotionCVWindow *gui, int x, int y)
381  : BC_FPot(x, y, plugin->config.block_x, (float)0, (float)100)
382 {
383         this->plugin = plugin;
384         this->gui = gui;
385 }
386
387 int MotionCVBlockX::handle_event()
388 {
389         plugin->config.block_x = get_value();
390         gui->block_x_text->update((float)plugin->config.block_x);
391         plugin->send_configure_change();
392         return 1;
393 }
394
395 MotionCVBlockY::MotionCVBlockY(MotionCVMain *plugin,
396                 MotionCVWindow *gui, int x, int y)
397  : BC_FPot(x, y, (float)plugin->config.block_y, (float)0, (float)100)
398 {
399         this->plugin = plugin;
400         this->gui = gui;
401 }
402
403 int MotionCVBlockY::handle_event()
404 {
405         plugin->config.block_y = get_value();
406         gui->block_y_text->update((float)plugin->config.block_y);
407         plugin->send_configure_change();
408         return 1;
409 }
410
411 MotionCVBlockXText::MotionCVBlockXText(MotionCVMain *plugin,
412                 MotionCVWindow *gui, int x, int y)
413  : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_x)
414 {
415         this->plugin = plugin;
416         this->gui = gui;
417         set_precision(4);
418 }
419
420 int MotionCVBlockXText::handle_event()
421 {
422         plugin->config.block_x = atof(get_text());
423         gui->block_x->update(plugin->config.block_x);
424         plugin->send_configure_change();
425         return 1;
426 }
427
428 MotionCVBlockYText::MotionCVBlockYText(MotionCVMain *plugin,
429                 MotionCVWindow *gui, int x, int y)
430  : BC_TextBox(x, y, 75, 1, (float)plugin->config.block_y)
431 {
432         this->plugin = plugin;
433         this->gui = gui;
434         set_precision(4);
435 }
436
437 int MotionCVBlockYText::handle_event()
438 {
439         plugin->config.block_y = atof(get_text());
440         gui->block_y->update(plugin->config.block_y);
441         plugin->send_configure_change();
442         return 1;
443 }
444
445 MotionCVDrawVectors::MotionCVDrawVectors(MotionCVMain *plugin,
446                 MotionCVWindow *gui, int x, int y)
447  : BC_CheckBox(x, y, plugin->config.draw_vectors, _("Draw vectors"))
448 {
449         this->gui = gui;
450         this->plugin = plugin;
451 }
452
453 int MotionCVDrawVectors::handle_event()
454 {
455         plugin->config.draw_vectors = get_value();
456         plugin->send_configure_change();
457         return 1;
458 }
459
460 TrackSingleFrame::TrackSingleFrame(MotionCVMain *plugin,
461                 MotionCVWindow *gui, int x, int y)
462  :
463 BC_Radial(x,
464       y, plugin->config.mode3 == MotionCVConfig::TRACK_SINGLE,
465       _("Track single frame"))
466 {
467         this->plugin = plugin;
468         this->gui = gui;
469 }
470
471 int TrackSingleFrame::handle_event()
472 {
473         plugin->config.mode3 = MotionCVConfig::TRACK_SINGLE;
474         gui->track_previous->update(0);
475         gui->previous_same->update(0);
476         gui->track_frame_number->enable();
477         plugin->send_configure_change();
478         return 1;
479 }
480
481 TrackFrameNumber::TrackFrameNumber(MotionCVMain *plugin,
482                 MotionCVWindow *gui, int x, int y)
483  : BC_TextBox(x, y, 100, 1, plugin->config.track_frame)
484 {
485         this->plugin = plugin;
486         this->gui = gui;
487         if( plugin->config.mode3 != MotionCVConfig::TRACK_SINGLE )
488                 disable();
489 }
490
491 int TrackFrameNumber::handle_event()
492 {
493         plugin->config.track_frame = atol(get_text());
494         plugin->send_configure_change();
495         return 1;
496 }
497
498 TrackPreviousFrame::TrackPreviousFrame(MotionCVMain *plugin,
499                 MotionCVWindow *gui, int x, int y)
500  :
501 BC_Radial(x,
502       y, plugin->config.mode3 == MotionCVConfig::TRACK_PREVIOUS,
503       _("Track previous frame"))
504 {
505         this->plugin = plugin;
506         this->gui = gui;
507 }
508
509 int TrackPreviousFrame::handle_event()
510 {
511         plugin->config.mode3 = MotionCVConfig::TRACK_PREVIOUS;
512         gui->track_single->update(0);
513         gui->previous_same->update(0);
514         gui->track_frame_number->disable();
515         plugin->send_configure_change();
516         return 1;
517 }
518
519 PreviousFrameSameBlock::PreviousFrameSameBlock(MotionCVMain *plugin,
520                 MotionCVWindow *gui, int x, int y)
521  :
522 BC_Radial(x,
523       y, plugin->config.mode3 == MotionCVConfig::PREVIOUS_SAME_BLOCK,
524       _("Previous frame same block"))
525 {
526         this->plugin = plugin;
527         this->gui = gui;
528 }
529
530 int PreviousFrameSameBlock::handle_event()
531 {
532         plugin->config.mode3 = MotionCVConfig::PREVIOUS_SAME_BLOCK;
533         gui->track_single->update(0);
534         gui->track_previous->update(0);
535         gui->track_frame_number->disable();
536         plugin->send_configure_change();
537         return 1;
538 }
539
540 MasterLayer::MasterLayer(MotionCVMain *plugin, MotionCVWindow *gui, int x,
541                          int y)
542  : BC_PopupMenu(x, y, calculate_w(gui),
543              to_text(plugin->config.bottom_is_master))
544 {
545         this->plugin = plugin;
546         this->gui = gui;
547 }
548
549 int MasterLayer::handle_event()
550 {
551         plugin->config.bottom_is_master = from_text(get_text());
552         plugin->send_configure_change();
553         return 1;
554 }
555
556 void MasterLayer::create_objects()
557 {
558         add_item(new BC_MenuItem(to_text(0)));
559         add_item(new BC_MenuItem(to_text(1)));
560 }
561
562 int MasterLayer::from_text(char *text)
563 {
564         if( !strcmp(text, _("Top")) ) return 0;
565         return 1;
566 }
567
568 const char *MasterLayer::to_text(int mode)
569 {
570         return mode ? _("Bottom") : _("Top");
571 }
572
573 int MasterLayer::calculate_w(MotionCVWindow *gui)
574 {
575         int result = 0;
576         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0)));
577         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1)));
578         return result + 50;
579 }
580
581 Mode1::Mode1(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y)
582  : BC_PopupMenu(x, y, calculate_w(gui), to_text(plugin->config.mode1))
583 {
584         this->plugin = plugin;
585         this->gui = gui;
586 }
587
588 int Mode1::handle_event()
589 {
590         plugin->config.mode1 = from_text(get_text());
591         plugin->send_configure_change();
592         return 1;
593 }
594
595 void Mode1::create_objects()
596 {
597         add_item(new BC_MenuItem(to_text(MotionCVConfig::TRACK)));
598         add_item(new BC_MenuItem(to_text(MotionCVConfig::TRACK_PIXEL)));
599         add_item(new BC_MenuItem(to_text(MotionCVConfig::STABILIZE)));
600         add_item(new BC_MenuItem(to_text(MotionCVConfig::STABILIZE_PIXEL)));
601         add_item(new BC_MenuItem(to_text(MotionCVConfig::NOTHING)));
602 }
603
604 int Mode1::from_text(char *text)
605 {
606         if( !strcmp(text, _("Track Subpixel")) ) return MotionCVConfig::TRACK;
607         if( !strcmp(text, _("Track Pixel")) ) return MotionCVConfig::TRACK_PIXEL;
608         if( !strcmp(text, _("Stabilize Subpixel")) ) return MotionCVConfig::STABILIZE;
609         if( !strcmp(text, _("Stabilize Pixel")) ) return MotionCVConfig::STABILIZE_PIXEL;
610         //if( !strcmp(text, _("Do Nothing")) ) return MotionCVConfig::NOTHING;
611         return MotionCVConfig::NOTHING;
612 }
613
614 const char *Mode1::to_text(int mode)
615 {
616         switch( mode ) {
617         case MotionCVConfig::TRACK: return _("Track Subpixel");
618         case MotionCVConfig::TRACK_PIXEL: return _("Track Pixel");
619         case MotionCVConfig::STABILIZE: return _("Stabilize Subpixel");
620         case MotionCVConfig::STABILIZE_PIXEL: return _("Stabilize Pixel");
621         case MotionCVConfig::NOTHING: return _("Do Nothing");
622         }
623         return "";
624 }
625
626 int Mode1::calculate_w(MotionCVWindow *gui)
627 {
628         int result = 0;
629         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::TRACK)));
630         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::TRACK_PIXEL)));
631         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::STABILIZE)));
632         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::STABILIZE_PIXEL)));
633         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::NOTHING)));
634         return result + 50;
635 }
636
637 Mode2::Mode2(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y)
638  : BC_PopupMenu(x, y, calculate_w(gui), to_text(plugin->config.mode2))
639 {
640         this->plugin = plugin;
641         this->gui = gui;
642 }
643
644 int Mode2::handle_event()
645 {
646         plugin->config.mode2 = from_text(get_text());
647         plugin->send_configure_change();
648         return 1;
649 }
650
651 void Mode2::create_objects()
652 {
653         add_item(new BC_MenuItem(to_text(MotionCVConfig::SAVE)));
654         add_item(new BC_MenuItem(to_text(MotionCVConfig::LOAD)));
655         add_item(new BC_MenuItem(to_text(MotionCVConfig::RECALCULATE)));
656         add_item(new BC_MenuItem(to_text(MotionCVConfig::NO_CALCULATE)));
657 }
658
659 int Mode2::from_text(char *text)
660 {
661         if( !strcmp(text, _("Recalculate")) ) return MotionCVConfig::RECALCULATE;
662         if( !strcmp(text, _("Save coords to tracking file")) ) return MotionCVConfig::SAVE;
663         if( !strcmp(text, _("Load coords from tracking file")) ) return MotionCVConfig::LOAD;
664         //if( !strcmp(text, _("Don't Calculate")) ) return MotionCVConfig::NO_CALCULATE;
665         return MotionCVConfig::NO_CALCULATE;
666 }
667
668 const char *Mode2::to_text(int mode)
669 {
670         switch( mode ) {
671         case MotionCVConfig::NO_CALCULATE: return _("Don't Calculate");
672         case MotionCVConfig::RECALCULATE: return _("Recalculate");
673         case MotionCVConfig::SAVE: return _("Save coords to tracking file");
674         case MotionCVConfig::LOAD: return _("Load coords from tracking file");
675         }
676         return "";
677 }
678
679 int Mode2::calculate_w(MotionCVWindow *gui)
680 {
681         int result = 0;
682         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::NO_CALCULATE)));
683         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::RECALCULATE)));
684         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::SAVE)));
685         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(MotionCVConfig::LOAD)));
686         return result + 50;
687 }
688
689 Mode3::Mode3(MotionCVMain *plugin, MotionCVWindow *gui, int x, int y)
690  :
691 BC_PopupMenu(x, y, calculate_w(gui),
692          to_text(plugin->config.horizontal_only, plugin->config.vertical_only))
693 {
694         this->plugin = plugin;
695         this->gui = gui;
696 }
697
698 int Mode3::handle_event()
699 {
700         from_text(&plugin->config.horizontal_only,
701                   &plugin->config.vertical_only, get_text());
702         plugin->send_configure_change();
703         return 1;
704 }
705
706 void Mode3::create_objects()
707 {
708         add_item(new BC_MenuItem(to_text(1, 0)));
709         add_item(new BC_MenuItem(to_text(0, 1)));
710         add_item(new BC_MenuItem(to_text(0, 0)));
711 }
712
713 void Mode3::from_text(int *horizontal_only, int *vertical_only, char *text)
714 {
715         *horizontal_only = 0;
716         *vertical_only = 0;
717         if( !strcmp(text, to_text(1, 0)) ) *horizontal_only = 1;
718         if( !strcmp(text, to_text(0, 1)) ) *vertical_only = 1;
719 }
720
721 const char *Mode3::to_text(int horizontal_only, int vertical_only)
722 {
723         if( horizontal_only ) return _("Horizontal only");
724         if( vertical_only ) return _("Vertical only");
725         return _("Both");
726 }
727
728 int Mode3::calculate_w(MotionCVWindow *gui)
729 {
730         int result = 0;
731         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(1, 0)));
732         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 1)));
733         result = MAX(result, gui->get_text_width(MEDIUMFONT, to_text(0, 0)));
734         return result + 50;
735 }
736
737