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