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