fix bug in mixer audio track/pan association
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / histogram / histogramwindow.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 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 "cursors.h"
25 #include "histogram.h"
26 #include "histogramconfig.h"
27 #include "histogramwindow.h"
28 #include "keys.h"
29 #include "language.h"
30 #include "theme.h"
31
32 #include <unistd.h>
33
34
35
36
37 HistogramWindow::HistogramWindow(HistogramMain *plugin)
38  : PluginClientWindow(plugin,
39         plugin->w,
40         plugin->h,
41         440,
42         500,
43         1)
44 {
45         this->plugin = plugin;
46         active_value = 0;
47 }
48
49 HistogramWindow::~HistogramWindow()
50 {
51 }
52
53
54 void HistogramWindow::create_objects()
55 {
56         int margin = plugin->get_theme()->widget_border;
57         int x = margin, y = margin, x1 = margin;
58
59         add_subwindow(mode_v = new HistogramMode(plugin,
60                 x,
61                 y,
62                 HISTOGRAM_VALUE,
63                 _("Value")));
64         x += mode_v->get_w() + margin;
65         add_subwindow(mode_r = new HistogramMode(plugin,
66                 x,
67                 y,
68                 HISTOGRAM_RED,
69                 _("Red")));
70         x += mode_r->get_w() + margin;
71         add_subwindow(mode_g = new HistogramMode(plugin,
72                 x,
73                 y,
74                 HISTOGRAM_GREEN,
75                 _("Green")));
76         x += mode_g->get_w() + margin;
77         add_subwindow(mode_b = new HistogramMode(plugin,
78                 x,
79                 y,
80                 HISTOGRAM_BLUE,
81                 _("Blue")));
82
83
84         x = get_w() - margin - plugin->get_theme()->get_image_set("histogram_rgb_toggle")[0]->get_w();
85         add_subwindow(parade_on = new HistogramParade(plugin,
86                 this,
87                 x,
88                 y,
89                 1));
90         x -= parade_on->get_w() + margin;
91         add_subwindow(parade_off = new HistogramParade(plugin,
92                 this,
93                 x,
94                 y,
95                 0));
96
97
98         x = x1;
99         y += parade_on->get_h() + margin;
100         add_subwindow(canvas_title1 = new BC_Title(margin,
101                 y,
102                 "-10%"));
103         add_subwindow(canvas_title2 = new BC_Title(get_w() - get_text_width(MEDIUMFONT, "110%") - margin,
104                 y,
105                 "110%"));
106
107         y += canvas_title2->get_h() + margin;
108         x = x1;
109         canvas_h = get_h() - y - 210;
110
111
112         add_subwindow(low_input_carrot = new HistogramCarrot(plugin,
113                 this,
114                 x,
115                 y + canvas_h));
116
117         x = low_input_carrot->get_w() / 2 + x;
118         canvas_w = get_w() - x - x;
119
120         title1_x = x;
121         title2_x = x + (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE);
122         title3_x = x + (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE);
123         title4_x = x + (int)(canvas_w);
124
125
126
127
128
129         add_subwindow(canvas = new HistogramCanvas(plugin,
130                 this,
131                 x,
132                 y,
133                 canvas_w,
134                 canvas_h));
135
136 // Canvas border
137         draw_3d_border(x - 2,
138                 y - 2,
139                 canvas_w + 4,
140                 canvas_h + 4,
141                 get_bg_color(),
142                 BLACK,
143                 MDGREY,
144                 get_bg_color());
145
146 // Calculate output curve with no value function
147         plugin->tabulate_curve(plugin->mode, 0);
148
149         y += canvas->get_h();
150         x = margin;
151
152         add_subwindow(gamma_carrot = new HistogramCarrot(plugin,
153                 this,
154                 canvas->get_x() +
155                         canvas->get_w() / 2 -
156                         low_input_carrot->get_w() / 2 ,
157                 y));
158
159         add_subwindow(high_input_carrot = new HistogramCarrot(plugin,
160                 this,
161                 canvas->get_x() +
162                         canvas->get_w() -
163                         low_input_carrot->get_w() / 2,
164                 y));
165         y += low_input_carrot->get_h() + margin;
166
167
168 //      add_subwindow(title = new BC_Title(x, y, _("Input:")));
169 //      x += title->get_w() + margin;
170         low_input = new HistogramText(plugin,
171                 this,
172                 x,
173                 y);
174         low_input->create_objects();
175
176         x = get_w() / 2 - low_input->get_w() / 2;
177         gamma = new HistogramText(plugin,
178                 this,
179                 x,
180                 y);
181         gamma->create_objects();
182
183
184         x = get_w() - low_input->get_w() - margin;
185         high_input = new HistogramText(plugin,
186                 this,
187                 x,
188                 y);
189         high_input->create_objects();
190
191
192         y += high_input->get_h() + margin;
193         x = x1;
194
195
196
197         add_subwindow(output = new HistogramSlider(plugin,
198                 this,
199                 canvas->get_x(),
200                 y,
201                 canvas->get_w(),
202                 20,
203                 0));
204         output->update();
205
206 // Output border
207         draw_3d_border(output->get_x() - 2,
208                 output->get_y() - 2,
209                 output->get_w() + 4,
210                 output->get_h() + 4,
211                 get_bg_color(),
212                 BLACK,
213                 MDGREY,
214                 get_bg_color());
215
216
217         y += output->get_h();
218
219
220
221         add_subwindow(low_output_carrot = new HistogramCarrot(plugin,
222                 this,
223                 margin,
224                 y));
225
226         add_subwindow(high_output_carrot = new HistogramCarrot(plugin,
227                 this,
228                 canvas->get_x() +
229                         canvas->get_w() -
230                         low_output_carrot->get_w() / 2,
231                 y));
232         y += high_output_carrot->get_h() + margin;
233
234
235 //      add_subwindow(title = new BC_Title(x, y, _("Output:")));
236 //      x += title->get_w() + margin;
237         low_output = new HistogramText(plugin,
238                 this,
239                 x,
240                 y);
241         low_output->create_objects();
242         high_output = new HistogramText(plugin,
243                 this,
244                 get_w() - low_output->get_w() - margin,
245                 y);
246         high_output->create_objects();
247
248         x = x1;
249         y += high_output->get_h() + margin;
250
251         add_subwindow(bar = new BC_Bar(x, y, get_w() - margin * 2));
252         y += bar->get_h() + margin;
253
254         add_subwindow(automatic = new HistogramAuto(plugin,
255                 x,
256                 y));
257
258         //int y1 = y;
259         x = 200;
260         add_subwindow(threshold_title = new BC_Title(x, y, _("Threshold:")));
261         x += threshold_title->get_w() + margin;
262         threshold = new HistogramText(plugin,
263                 this,
264                 x,
265                 y);
266         threshold->create_objects();
267
268         x = get_w() / 2;
269         add_subwindow(reset = new HistogramReset(plugin,
270                 x,
271                 y + threshold->get_h() + margin));
272
273         x = x1;
274         y += automatic->get_h() + margin;
275         add_subwindow(plot = new HistogramPlot(plugin,
276                 x,
277                 y));
278
279         y += plot->get_h() + 5;
280         add_subwindow(split = new HistogramSplit(plugin,
281                 x,
282                 y));
283
284         update(1, 1, 1, 1);
285
286         flash(0);
287         show_window();
288 }
289
290
291
292 int HistogramWindow::resize_event(int w, int h)
293 {
294         int xdiff = w - get_w();
295         int ydiff = h - get_h();
296
297         parade_on->reposition_window(parade_on->get_x() + xdiff,
298                 parade_on->get_y());
299         parade_off->reposition_window(parade_off->get_x() + xdiff,
300                 parade_on->get_y());
301         canvas_title2->reposition_window(canvas_title2->get_x() + xdiff,
302                 canvas_title2->get_y());
303
304 // Canvas follows window size
305         canvas_w = canvas_w + xdiff;
306         canvas_h = canvas_h + ydiff;
307         canvas->reposition_window(canvas->get_x(),
308                 canvas->get_y(),
309                 canvas_w,
310                 canvas_h);
311
312 // Canvas border
313         draw_3d_border(canvas->get_x() - 2,
314                 canvas->get_y() - 2,
315                 canvas_w + 4,
316                 canvas_h + 4,
317                 get_bg_color(),
318                 BLACK,
319                 MDGREY,
320                 get_bg_color());
321
322         low_input_carrot->reposition_window(low_input_carrot->get_x(),
323                 low_input_carrot->get_y() + ydiff);
324         gamma_carrot->reposition_window(gamma_carrot->get_x(),
325                 gamma_carrot->get_y() + ydiff);
326         high_input_carrot->reposition_window(high_input_carrot->get_x(),
327                 high_input_carrot->get_y() + ydiff);
328
329         low_input->reposition_window(low_input->get_x(),
330                 low_input->get_y() + ydiff);
331         gamma->reposition_window(w / 2 - gamma->get_w() / 2,
332                 gamma->get_y() + ydiff);
333         high_input->reposition_window(high_input->get_x() + xdiff,
334                 low_input->get_y() + ydiff);
335
336         output->reposition_window(output->get_x(),
337                 output->get_y() + ydiff,
338                 output->get_w() + xdiff,
339                 output->get_h());
340         output->update();
341
342 // Output border
343         draw_3d_border(output->get_x() - 2,
344                 output->get_y() - 2,
345                 output->get_w() + 4,
346                 output->get_h() + 4,
347                 get_bg_color(),
348                 BLACK,
349                 MDGREY,
350                 get_bg_color());
351
352         low_output_carrot->reposition_window(low_output_carrot->get_x(),
353                 low_output_carrot->get_y() + ydiff);
354         high_output_carrot->reposition_window(high_output_carrot->get_x(),
355                 high_output_carrot->get_y() + ydiff);
356
357         low_output->reposition_window(low_output->get_x(),
358                 low_output->get_y() + ydiff);
359         high_output->reposition_window(high_output->get_x() + xdiff,
360                 high_output->get_y() + ydiff);
361
362         bar->reposition_window(bar->get_x(),
363                 bar->get_y() + ydiff,
364                 bar->get_w() + xdiff);
365
366         automatic->reposition_window(automatic->get_x(),
367                 automatic->get_y() + ydiff);
368         threshold_title->reposition_window(threshold_title->get_x(),
369                 threshold_title->get_y() + ydiff);
370         threshold->reposition_window(threshold->get_x(),
371                 threshold->get_y() + ydiff);
372         reset->reposition_window(reset->get_x(),
373                 reset->get_y() + ydiff);
374
375         plot->reposition_window(plot->get_x(),
376                 plot->get_y() + ydiff);
377         split->reposition_window(split->get_x(),
378                 split->get_y() + ydiff);
379
380         update(1, 1, 1, 1);
381
382         plugin->w = w;
383         plugin->h = h;
384         flash();
385         return 1;
386 }
387
388
389
390 int HistogramWindow::keypress_event()
391 {
392         int result = 0;
393
394         if(active_value)
395         {
396                 float sign = 1;
397                 for(int i = 0; i < HISTOGRAM_MODES; i++)
398                 {
399                         if(active_value == &plugin->config.gamma[i])
400                                 sign = -1;
401                 }
402
403                 if(get_keypress() == RIGHT || get_keypress() == UP)
404                 {
405                         *active_value += sign * PRECISION;
406                         plugin->config.boundaries();
407                         update(1, 1, 1, 0);
408                         plugin->send_configure_change();
409                         return 1;
410                 }
411                 else
412                 if(get_keypress() == LEFT || get_keypress() == DOWN)
413                 {
414                         *active_value -= sign * PRECISION;
415                         plugin->config.boundaries();
416                         update(1, 1, 1, 0);
417                         plugin->send_configure_change();
418                         return 1;
419                 }
420         }
421
422         return result;
423 }
424
425 void HistogramWindow::update(int do_canvases,
426         int do_carrots,
427         int do_text,
428         int do_toggles)
429 {
430         if(do_toggles)
431         {
432                 automatic->update(plugin->config.automatic);
433                 mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
434                 mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
435                 mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
436                 mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
437                 plot->update(plugin->config.plot);
438                 split->update(plugin->config.split);
439                 parade_on->update(plugin->parade ? 1 : 0);
440                 parade_off->update(plugin->parade ? 0 : 1);
441                 output->update();
442         }
443
444         if(do_canvases)
445         {
446                 update_canvas();
447         }
448
449         if(do_carrots)
450         {
451                 low_input_carrot->update();
452                 high_input_carrot->update();
453                 gamma_carrot->update();
454                 low_output_carrot->update();
455                 high_output_carrot->update();
456         }
457
458         if(do_text)
459         {
460                 low_input->update();
461                 gamma->update();
462                 high_input->update();
463                 low_output->update();
464                 high_output->update();
465                 threshold->update();
466         }
467
468
469 }
470
471
472 void HistogramWindow::draw_canvas_mode(int mode, int color, int y, int h)
473 {
474         int *accum = plugin->accum[mode];
475         int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1;
476         float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w;
477         int normalize = 0;
478         int max = 0;
479
480
481 // Draw histogram
482         for(int i = 0; i < HISTOGRAM_SLOTS; i++)
483         {
484                 if(accum && accum[i] > normalize) normalize = accum[i];
485         }
486
487
488         if(normalize)
489         {
490                 for(int i = 0; i < canvas_w; i++)
491                 {
492                         int accum_start = (int)(accum_per_canvas_f * i);
493                         int accum_end = accum_start + accum_per_canvas_i;
494                         max = 0;
495                         for(int j = accum_start; j < accum_end; j++)
496                         {
497                                 max = MAX(accum[j], max);
498                         }
499
500 //                      max = max * h / normalize;
501                         max = (int)(log(max) / log(normalize) * h);
502
503                         canvas->set_color(BLACK);
504                         canvas->draw_line(i, y, i, y + h - max);
505                         canvas->set_color(color);
506                         canvas->draw_line(i, y + h - max, i, y + h);
507                 }
508         }
509         else
510         {
511                 canvas->set_color(BLACK);
512                 canvas->draw_box(0, y, canvas_w, h);
513         }
514
515 // Draw overlays
516         canvas->set_color(WHITE);
517         canvas->set_line_width(2);
518         int y1 = 0;
519
520 // Draw output line
521         for(int i = 0; i < canvas_w; i++)
522         {
523                 float input = (float)i /
524                                 canvas_w *
525                                 FLOAT_RANGE +
526                                 HIST_MIN_INPUT;
527                 float output = plugin->calculate_level(input,
528                         mode,
529                         0);
530
531                 int y2 = h - (int)(output * h);
532                 if(i > 0)
533                 {
534                         canvas->draw_line(i - 1, y + y1, i, y + y2);
535                 }
536                 y1 = y2;
537         }
538
539         canvas->set_line_width(1);
540
541 }
542
543
544 void HistogramWindow::update_canvas()
545 {
546         if(plugin->parade)
547         {
548                 draw_canvas_mode(HISTOGRAM_RED, RED, 0, canvas_h / 3);
549                 draw_canvas_mode(HISTOGRAM_GREEN, GREEN, canvas_h / 3, canvas_h / 3);
550                 draw_canvas_mode(HISTOGRAM_BLUE, BLUE, canvas_h * 2 / 3, canvas_h - canvas_h * 2 / 3);
551         }
552         else
553         {
554                 draw_canvas_mode(plugin->mode, MEGREY, 0, canvas_h);
555         }
556
557
558 // Draw 0 and 100% lines.
559         canvas->set_color(RED);
560         int x = (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE);
561         canvas->draw_line(x,
562                 0,
563                 x,
564                 canvas_h);
565         x = (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE);
566         canvas->draw_line(x,
567                 0,
568                 x,
569                 canvas_h);
570         canvas->flash();
571 }
572
573
574
575
576 HistogramParade::HistogramParade(HistogramMain *plugin,
577         HistogramWindow *gui,
578         int x,
579         int y,
580         int value)
581  : BC_Toggle(x,
582         y,
583         value ? plugin->get_theme()->get_image_set("histogram_rgb_toggle") :
584                 plugin->get_theme()->get_image_set("histogram_toggle"),
585         0)
586 {
587         this->plugin = plugin;
588         this->gui = gui;
589         this->value = value;
590         if(value)
591                 set_tooltip(_("RGB Parade on"));
592         else
593                 set_tooltip(_("RGB Parade off"));
594 }
595
596 int HistogramParade::handle_event()
597 {
598         update(1);
599         plugin->parade = value;
600         gui->update(1,
601                 0,
602                 0,
603                 1);
604         return 1;
605 }
606
607
608
609
610
611
612
613 HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
614         HistogramWindow *gui,
615         int x,
616         int y,
617         int w,
618         int h)
619  : BC_SubWindow(x,
620         y,
621         w,
622         h,
623         BLACK)
624 {
625         this->plugin = plugin;
626         this->gui = gui;
627 }
628
629 int HistogramCanvas::button_press_event()
630 {
631         int result = 0;
632         if(is_event_win() && cursor_inside())
633         {
634                 if(!plugin->dragging_point &&
635                         (!plugin->config.automatic || plugin->mode == HISTOGRAM_VALUE))
636                 {
637                         gui->deactivate();
638                 }
639         }
640         return result;
641 }
642
643 int HistogramCanvas::cursor_motion_event()
644 {
645         if(is_event_win() && cursor_inside())
646         {
647         }
648         return 0;
649 }
650
651 int HistogramCanvas::button_release_event()
652 {
653         return 0;
654 }
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669 HistogramReset::HistogramReset(HistogramMain *plugin,
670         int x,
671         int y)
672  : BC_GenericButton(x, y, _("Reset"))
673 {
674         this->plugin = plugin;
675 }
676 int HistogramReset::handle_event()
677 {
678         plugin->config.reset(0);
679         ((HistogramWindow*)plugin->thread->window)->update(1, 1, 1, 1);
680         plugin->send_configure_change();
681         return 1;
682 }
683
684
685
686
687
688
689
690 HistogramCarrot::HistogramCarrot(HistogramMain *plugin,
691         HistogramWindow *gui,
692         int x,
693         int y)
694  : BC_Toggle(x,
695         y,
696         plugin->get_theme()->get_image_set("histogram_carrot"),
697         0)
698 {
699         this->plugin = plugin;
700         this->gui = gui;
701         drag_operation = 0;
702 }
703
704 HistogramCarrot::~HistogramCarrot()
705 {
706 }
707
708 float* HistogramCarrot::get_value()
709 {
710         if(this == gui->low_input_carrot)
711         {
712                 return &plugin->config.low_input[plugin->mode];
713         }
714         else
715         if(this == gui->high_input_carrot)
716         {
717                 return &plugin->config.high_input[plugin->mode];
718         }
719         else
720         if(this == gui->gamma_carrot)
721         {
722                 return &plugin->config.gamma[plugin->mode];
723         }
724         else
725         if(this == gui->low_output_carrot)
726         {
727                 return &plugin->config.low_output[plugin->mode];
728         }
729         else
730         if(this == gui->high_output_carrot)
731         {
732                 return &plugin->config.high_output[plugin->mode];
733         }
734         return 0;
735 }
736
737 void HistogramCarrot::update()
738 {
739         int new_x = 0;
740         float *value = get_value();
741
742         if(this != gui->gamma_carrot)
743         {
744                 new_x = (int)(gui->canvas->get_x() +
745                         (*value - HIST_MIN_INPUT) *
746                         gui->canvas->get_w() /
747                         (HIST_MAX_INPUT - HIST_MIN_INPUT) -
748                         get_w() / 2);
749         }
750         else
751         {
752                 float min = plugin->config.low_input[plugin->mode];
753                 float max = plugin->config.high_input[plugin->mode];
754                 float delta = (max - min) / 2.0;
755                 float mid = min + delta;
756                 float tmp = log10(1.0 / *value);
757                 tmp = mid + delta * tmp;
758
759 //printf("HistogramCarrot::update %d %f %f\n", __LINE__, *value, tmp);
760
761                         new_x = gui->canvas->get_x() -
762                                 get_w() / 2 +
763                                 (int)(gui->canvas->get_w() *
764                                 (tmp - HIST_MIN_INPUT) /
765                                 (HIST_MAX_INPUT - HIST_MIN_INPUT));
766         }
767
768         reposition_window(new_x, get_y());
769 }
770
771 int HistogramCarrot::button_press_event()
772 {
773         if(is_event_win() && get_buttonpress() == 1)
774         {
775                 //int w = get_w();
776                 gui->deactivate();
777                 set_status(BC_Toggle::TOGGLE_DOWN);
778
779                 BC_Toggle::update(0);
780                 gui->active_value = get_value();
781 // Disable the other toggles
782                 if(this != gui->low_input_carrot) gui->low_input_carrot->BC_Toggle::update(0);
783                 if(this != gui->high_input_carrot) gui->high_input_carrot->BC_Toggle::update(0);
784                 if(this != gui->gamma_carrot) gui->gamma_carrot->BC_Toggle::update(0);
785                 if(this != gui->low_output_carrot) gui->low_output_carrot->BC_Toggle::update(0);
786                 if(this != gui->high_output_carrot) gui->high_output_carrot->BC_Toggle::update(0);
787                 starting_x = get_x();
788                 offset_x = gui->get_relative_cursor_x();
789                 offset_y = gui->get_relative_cursor_y();
790 //printf("HistogramCarrot::button_press_event %d %d %d\n", __LINE__, starting_x, offset_x);
791                 drag_operation = 1;
792                 draw_face(1, 1);
793                 return 1;
794         }
795         return 0;
796 }
797
798 int HistogramCarrot::button_release_event()
799 {
800         int result = BC_Toggle::button_release_event();
801         handle_event();
802         drag_operation = 0;
803         return result;
804 }
805
806 int HistogramCarrot::cursor_motion_event()
807 {
808         int cursor_x = gui->get_relative_cursor_x();
809
810         if(drag_operation)
811         {
812 //printf("HistogramCarrot::cursor_motion_event %d %d\n", __LINE__, cursor_x);
813                 int new_x = starting_x + cursor_x - offset_x;
814
815 // Clamp x
816 // Get level from x
817                 float *value = get_value();
818                 if(this == gui->gamma_carrot)
819                 {
820                         float min = gui->low_input_carrot->get_x();
821                         float max = gui->high_input_carrot->get_x();
822                         float delta = (max - min) / 2.0;
823                         if(delta >= 0.5)
824                         {
825                                 float mid = min + delta;
826                                 float tmp = (float)(new_x - mid) /
827                                         delta;
828                                 tmp = 1.0 / pow(10, tmp);
829                                 CLAMP(tmp, MIN_GAMMA, MAX_GAMMA);
830                                 *value = tmp;
831 //printf("HistogramCarrot::update %d %f\n", __LINE__, tmp);
832                         }
833                 }
834                 else
835                 {
836                         int min_x = gui->canvas->get_x() - get_w() / 2;
837                         int max_x = gui->canvas->get_x() + gui->canvas->get_w() - get_w() / 2;
838                         CLAMP(new_x, min_x, max_x);
839                         *value = HIST_MIN_INPUT +
840                                 (HIST_MAX_INPUT - HIST_MIN_INPUT) *
841                                 (new_x - min_x) /
842                                 (max_x - min_x);
843                 }
844
845                 reposition_window(new_x, get_y());
846                 flush();
847
848                 gui->update(1,
849                         (this == gui->low_input_carrot || this == gui->high_input_carrot),
850                         1,
851                         0);
852                 plugin->send_configure_change();
853
854                 return 1;
855         }
856         return 0;
857 }
858
859
860
861
862
863
864
865
866 HistogramSlider::HistogramSlider(HistogramMain *plugin,
867         HistogramWindow *gui,
868         int x,
869         int y,
870         int w,
871         int h,
872         int is_input)
873  : BC_SubWindow(x, y, w, h)
874 {
875         this->plugin = plugin;
876         this->gui = gui;
877         this->is_input = is_input;
878         operation = NONE;
879 }
880
881 int HistogramSlider::input_to_pixel(float input)
882 {
883         return (int)((input - HIST_MIN_INPUT) / FLOAT_RANGE * get_w());
884 }
885
886 void HistogramSlider::update()
887 {
888         int w = get_w();
889         int h = get_h();
890         //int half_h = get_h() / 2;
891         //int quarter_h = get_h() / 4;
892         int mode = plugin->mode;
893         int r = 0xff;
894         int g = 0xff;
895         int b = 0xff;
896
897         clear_box(0, 0, w, h);
898
899         switch(mode)
900         {
901                 case HISTOGRAM_RED:
902                         g = b = 0x00;
903                         break;
904                 case HISTOGRAM_GREEN:
905                         r = b = 0x00;
906                         break;
907                 case HISTOGRAM_BLUE:
908                         r = g = 0x00;
909                         break;
910         }
911
912         for(int i = 0; i < w; i++)
913         {
914                 int color = (int)(i * 0xff / w);
915                 set_color(((r * color / 0xff) << 16) |
916                         ((g * color / 0xff) << 8) |
917                         (b * color / 0xff));
918
919                 draw_line(i, 0, i, h);
920         }
921
922
923         flash();
924 }
925
926
927
928
929
930
931
932
933
934 HistogramAuto::HistogramAuto(HistogramMain *plugin,
935         int x,
936         int y)
937  : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
938 {
939         this->plugin = plugin;
940 }
941
942 int HistogramAuto::handle_event()
943 {
944         plugin->config.automatic = get_value();
945         plugin->send_configure_change();
946         return 1;
947 }
948
949
950
951
952 HistogramPlot::HistogramPlot(HistogramMain *plugin,
953         int x,
954         int y)
955  : BC_CheckBox(x, y, plugin->config.plot, _("Plot histogram"))
956 {
957         this->plugin = plugin;
958 }
959
960 int HistogramPlot::handle_event()
961 {
962         plugin->config.plot = get_value();
963         plugin->send_configure_change();
964         return 1;
965 }
966
967
968
969
970 HistogramSplit::HistogramSplit(HistogramMain *plugin,
971         int x,
972         int y)
973  : BC_CheckBox(x, y, plugin->config.split, _("Split output"))
974 {
975         this->plugin = plugin;
976 }
977
978 int HistogramSplit::handle_event()
979 {
980         plugin->config.split = get_value();
981         plugin->send_configure_change();
982         return 1;
983 }
984
985
986
987 HistogramMode::HistogramMode(HistogramMain *plugin,
988         int x,
989         int y,
990         int value,
991         char *text)
992  : BC_Radial(x, y, plugin->mode == value, text)
993 {
994         this->plugin = plugin;
995         this->value = value;
996 }
997 int HistogramMode::handle_event()
998 {
999         HistogramWindow *gui = (HistogramWindow*)plugin->thread->window;
1000         plugin->mode = value;
1001         plugin->current_point= -1;
1002         gui->active_value = 0;
1003         gui->low_input_carrot->BC_Toggle::update(0);
1004         gui->gamma_carrot->BC_Toggle::update(0);
1005         gui->high_input_carrot->BC_Toggle::update(0);
1006         gui->low_output_carrot->BC_Toggle::update(0);
1007         gui->high_output_carrot->BC_Toggle::update(0);
1008         gui->update(1, 1, 1, 1);
1009 //      plugin->send_configure_change();
1010         return 1;
1011 }
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 HistogramText::HistogramText(HistogramMain *plugin,
1023         HistogramWindow *gui,
1024         int x,
1025         int y)
1026  : BC_TumbleTextBox(gui,
1027                 0.0,
1028                 (float)HIST_MIN_INPUT,
1029                 (float)HIST_MAX_INPUT,
1030                 x,
1031                 y,
1032                 70)
1033 {
1034         this->plugin = plugin;
1035         this->gui = gui;
1036         set_precision(DIGITS);
1037         set_increment(PRECISION);
1038 }
1039
1040 float* HistogramText::get_value()
1041 {
1042         if(this == gui->low_input)
1043         {
1044                 return &plugin->config.low_input[plugin->mode];
1045         }
1046         else
1047         if(this == gui->high_input)
1048         {
1049                 return &plugin->config.high_input[plugin->mode];
1050         }
1051         else
1052         if(this == gui->gamma)
1053         {
1054                 return &plugin->config.gamma[plugin->mode];
1055         }
1056         else
1057         if(this == gui->low_output)
1058         {
1059                 return &plugin->config.low_output[plugin->mode];
1060         }
1061         else
1062         if(this == gui->high_output)
1063         {
1064                 return &plugin->config.high_output[plugin->mode];
1065         }
1066         else
1067         if(this == gui->threshold)
1068         {
1069                 return &plugin->config.threshold;
1070         }
1071
1072         return 0;
1073 }
1074
1075 int HistogramText::handle_event()
1076 {
1077         float *output = get_value();
1078         if(output)
1079         {
1080                 *output = atof(get_text());
1081         }
1082
1083         gui->update(1, 1, 0, 0);
1084         plugin->send_configure_change();
1085         return 1;
1086 }
1087
1088 void HistogramText::update()
1089 {
1090         float *output = get_value();
1091         if(output)
1092         {
1093                 BC_TumbleTextBox::update(*output);
1094         }
1095 }
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110