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