Exciting new Alt/h help key provided by sge (Georgy) with many thanks!
[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 "edl.h"
26 #include "histogram.h"
27 #include "histogramconfig.h"
28 #include "histogramwindow.h"
29 #include "keys.h"
30 #include "language.h"
31 #include "localsession.h"
32 #include "mwindow.h"
33 #include "pluginserver.h"
34 #include "theme.h"
35
36 #include <unistd.h>
37
38
39
40
41 HistogramWindow::HistogramWindow(HistogramMain *plugin)
42  : PluginClientWindow(plugin,
43         plugin->w,
44         plugin->h,
45         xS(440),
46         yS(500),
47         1)
48 {
49         this->plugin = plugin;
50         active_value = 0;
51 }
52
53 HistogramWindow::~HistogramWindow()
54 {
55 }
56
57
58 void HistogramWindow::create_objects()
59 {
60         int margin = plugin->get_theme()->widget_border;
61         int x = margin, y = margin, x1 = margin;
62
63         add_subwindow(mode_v = new HistogramMode(plugin, x, y,
64                 HISTOGRAM_VALUE, _("Value")));
65         x += mode_v->get_w() + margin;
66         add_subwindow(mode_r = new HistogramMode(plugin, x, y,
67                 HISTOGRAM_RED, _("Red")));
68         x += mode_r->get_w() + margin;
69         add_subwindow(mode_g = new HistogramMode(plugin, x, y,
70                 HISTOGRAM_GREEN, _("Green")));
71         x += mode_g->get_w() + margin;
72         add_subwindow(mode_b = new HistogramMode(plugin, x, y,
73                 HISTOGRAM_BLUE, _("Blue")));
74         x = get_w() - margin - plugin->get_theme()->get_image_set("histogram_rgb_toggle")[0]->get_w();
75         add_subwindow(parade_on = new HistogramParade(plugin, this,
76                 x, y, 1));
77         x -= parade_on->get_w() + margin;
78         add_subwindow(parade_off = new HistogramParade(plugin, this, x, y, 0));
79
80         x = x1;
81         y += parade_on->get_h() + margin;
82         add_subwindow(canvas_title1 = new BC_Title(margin, y, "-10%"));
83         x = get_w() - get_text_width(MEDIUMFONT, "110%") - margin;
84         add_subwindow(canvas_title2 = new BC_Title(x, y, "110%"));
85
86         y += canvas_title2->get_h() + margin;
87         x = x1;
88         canvas_h = get_h() - y - yS(210);
89
90         add_subwindow(low_input_carrot = new HistogramCarrot(plugin, this, x, y + canvas_h));
91
92         x = low_input_carrot->get_w() / 2 + x;
93         canvas_w = get_w() - x - x;
94
95         title1_x = x;
96         title2_x = x + (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE);
97         title3_x = x + (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE);
98         title4_x = x + (int)(canvas_w);
99
100         add_subwindow(canvas = new HistogramCanvas(plugin, this,
101                         x, y, canvas_w, canvas_h));
102
103 // Canvas border
104         draw_3d_border(x - 2, y - 2, canvas_w + 4, canvas_h + 4,
105                 get_bg_color(), BLACK, MDGREY, get_bg_color());
106
107 // Calculate output curve with no value function
108         plugin->tabulate_curve(plugin->preview_lookup, plugin->mode, 0x10000, 0);
109
110         y += canvas->get_h();
111         x = margin;
112
113         add_subwindow(gamma_carrot = new HistogramCarrot(plugin, this,
114                 canvas->get_x() + canvas->get_w() / 2 -
115                         low_input_carrot->get_w() / 2 , y));
116
117         add_subwindow(high_input_carrot = new HistogramCarrot(plugin, this,
118                 canvas->get_x() + canvas->get_w() -
119                         low_input_carrot->get_w() / 2, y));
120         y += low_input_carrot->get_h() + margin;
121
122 //      add_subwindow(title = new BC_Title(x, y, _("Input:")));
123 //      x += title->get_w() + margin;
124         low_input = new HistogramText(plugin, this, x, y);
125         low_input->create_objects();
126
127         x = get_w() / 2 - low_input->get_w() / 2;
128         gamma = new HistogramText(plugin, this, x, y, 0.01, 100.);
129         gamma->create_objects();
130
131         x = get_w() - low_input->get_w() - margin;
132         high_input = new HistogramText(plugin, this, x, y);
133         high_input->create_objects();
134
135         y += high_input->get_h() + margin;
136         x = x1;
137
138         add_subwindow(output = new HistogramSlider(plugin, this,
139                 canvas->get_x(), y, canvas->get_w(), yS(20), 0));
140         output->update();
141
142 // Output border
143         draw_3d_border(output->get_x() - 2, output->get_y() - 2,
144                 output->get_w() + 4, output->get_h() + 4,
145                 get_bg_color(), BLACK, MDGREY, get_bg_color());
146         y += output->get_h();
147
148         add_subwindow(low_output_carrot = new HistogramCarrot(plugin,
149                 this, margin, y));
150
151         add_subwindow(high_output_carrot = new HistogramCarrot(plugin,
152                 this, canvas->get_x() + canvas->get_w() -
153                         low_output_carrot->get_w() / 2, y));
154         y += high_output_carrot->get_h() + margin;
155
156
157 //      add_subwindow(title = new BC_Title(x, y, _("Output:")));
158 //      x += title->get_w() + margin;
159         low_output = new HistogramText(plugin, this, x, y);
160         low_output->create_objects();
161
162         const char *linear_text = _("Linear");
163         int xs = get_w()/2 - xS(50);
164         x = xs - BC_Title::calculate_w(this, linear_text) - margin;
165         add_subwindow(log_title1 = new BC_Title(x, y, linear_text));
166         add_subwindow(log_slider = new HistogramLogSlider(plugin, this, xs, y));
167         xs += log_slider->get_w() + margin;
168         add_subwindow(log_title2 = new BC_Title(xs, y, _("Log")));
169
170         high_output = new HistogramText(plugin, this,
171                 get_w() - low_output->get_w() - margin, y);
172         high_output->create_objects();
173
174         x = x1;
175         y += high_output->get_h() + margin;
176
177         add_subwindow(bar = new BC_Bar(x, y, get_w() - margin * 2));
178         y += bar->get_h() + margin;
179
180         add_subwindow(automatic = new HistogramAuto(plugin, x, y));
181         int x2 = xS(190);
182         add_subwindow(threshold_title = new BC_Title(x2, y, _("Threshold:")));
183         int x3 = xS(305);
184         threshold = new HistogramText(plugin, this, x3, y);
185         threshold->create_objects();
186         y += automatic->get_h() + margin;
187
188         add_subwindow(plot= new HistogramPlot(plugin, x, y));
189         add_subwindow(sum_frames = new HistogramSumFrames(plugin, x2, y));
190         y += plot->get_h() + margin;
191
192         x = x1;
193         add_subwindow(split = new HistogramSplit(plugin, x, y));
194         x = xS(340);
195         add_subwindow(reset = new HistogramReset(plugin, x, y + yS(5)));
196
197         update(1, 1, 1, 1);
198
199         flash(0);
200         show_window();
201 }
202
203
204
205 int HistogramWindow::resize_event(int w, int h)
206 {
207         int xdiff = w - get_w();
208         int ydiff = h - get_h();
209
210         parade_on->reposition_window(parade_on->get_x() + xdiff,
211                 parade_on->get_y());
212         parade_off->reposition_window(parade_off->get_x() + xdiff,
213                 parade_on->get_y());
214         canvas_title2->reposition_window(canvas_title2->get_x() + xdiff,
215                 canvas_title2->get_y());
216
217 // Canvas follows window size
218         canvas_w = canvas_w + xdiff;
219         canvas_h = canvas_h + ydiff;
220         canvas->reposition_window(canvas->get_x(), canvas->get_y(),
221                 canvas_w, canvas_h);
222
223 // Canvas border
224         draw_3d_border(canvas->get_x() - 2, canvas->get_y() - 2,
225                 canvas_w + 4, canvas_h + 4,
226                 get_bg_color(), BLACK, MDGREY, get_bg_color());
227
228         low_input_carrot->reposition_window(low_input_carrot->get_x(),
229                 low_input_carrot->get_y() + ydiff);
230         gamma_carrot->reposition_window(gamma_carrot->get_x(),
231                 gamma_carrot->get_y() + ydiff);
232         high_input_carrot->reposition_window(high_input_carrot->get_x(),
233                 high_input_carrot->get_y() + ydiff);
234
235         low_input->reposition_window(low_input->get_x(),
236                 low_input->get_y() + ydiff);
237         gamma->reposition_window(w / 2 - gamma->get_w() / 2,
238                 gamma->get_y() + ydiff);
239         high_input->reposition_window(high_input->get_x() + xdiff,
240                 low_input->get_y() + ydiff);
241
242         output->reposition_window(output->get_x(),
243                 output->get_y() + ydiff,
244                 output->get_w() + xdiff,
245                 output->get_h());
246         output->update();
247
248 // Output border
249         draw_3d_border(output->get_x() - 2, output->get_y() - 2,
250                 output->get_w() + 4, output->get_h() + 4,
251                 get_bg_color(), BLACK, MDGREY, get_bg_color());
252
253         low_output_carrot->reposition_window(low_output_carrot->get_x(),
254                 low_output_carrot->get_y() + ydiff);
255         high_output_carrot->reposition_window(high_output_carrot->get_x(),
256                 high_output_carrot->get_y() + ydiff);
257
258         low_output->reposition_window(low_output->get_x(),
259                 low_output->get_y() + ydiff);
260         int xs = (w - log_slider->get_w()) / 2;
261         int margin = plugin->get_theme()->widget_border;
262         log_title1->reposition_window(xs - log_title1->get_w() - margin,
263                 log_title1->get_y() + ydiff);
264         log_slider->reposition_window(xs,
265                 log_slider->get_y() + ydiff);
266         log_title2->reposition_window(xs + log_slider->get_w() + margin,
267                 log_title2->get_y() + ydiff);
268         high_output->reposition_window(high_output->get_x() + xdiff,
269                 high_output->get_y() + ydiff);
270
271         bar->reposition_window(bar->get_x(),
272                 bar->get_y() + ydiff,
273                 bar->get_w() + xdiff);
274
275         automatic->reposition_window(automatic->get_x(),
276                 automatic->get_y() + ydiff);
277         threshold_title->reposition_window(threshold_title->get_x(),
278                 threshold_title->get_y() + ydiff);
279         threshold->reposition_window(threshold->get_x(),
280                 threshold->get_y() + ydiff);
281         plot->reposition_window(plot->get_x(),
282                 plot->get_y() + ydiff);
283         sum_frames->reposition_window(sum_frames->get_x(),
284                 sum_frames->get_y() + ydiff);
285
286         split->reposition_window(split->get_x(),
287                 split->get_y() + ydiff);
288         reset->reposition_window(reset->get_x(),
289                 reset->get_y() + ydiff);
290
291         update(1, 1, 1, 1);
292
293         plugin->w = w;
294         plugin->h = h;
295         flash();
296         return 1;
297 }
298
299
300
301 int HistogramWindow::keypress_event()
302 {
303         int result = 0;
304
305         if(active_value)
306         {
307                 float sign = 1;
308                 for(int i = 0; i < HISTOGRAM_MODES; i++)
309                 {
310                         if(active_value == &plugin->config.gamma[i])
311                                 sign = -1;
312                 }
313
314                 if(get_keypress() == RIGHT || get_keypress() == UP)
315                 {
316                         *active_value += sign * PRECISION;
317                         plugin->config.boundaries();
318                         update(1, 1, 1, 0);
319                         plugin->send_configure_change();
320                         return 1;
321                 }
322                 else
323                 if(get_keypress() == LEFT || get_keypress() == DOWN)
324                 {
325                         *active_value -= sign * PRECISION;
326                         plugin->config.boundaries();
327                         update(1, 1, 1, 0);
328                         plugin->send_configure_change();
329                         return 1;
330                 }
331         }
332
333         if (! result)
334                 result = context_help_check_and_show();
335
336         return result;
337 }
338
339 void HistogramWindow::update(int do_canvases, int do_carrots, int do_text, int do_toggles)
340 {
341         if(do_toggles) {
342                 automatic->update(plugin->config.automatic);
343                 mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
344                 mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
345                 mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
346                 mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
347                 plot->update(plugin->config.plot);
348                 sum_frames->update(plugin->config.sum_frames);
349                 split->update(plugin->config.split);
350                 parade_on->update(plugin->parade ? 1 : 0);
351                 parade_off->update(plugin->parade ? 0 : 1);
352                 log_slider->update(plugin->config.log_slider);
353                 output->update();
354         }
355
356         if(do_canvases) {
357                 update_canvas();
358         }
359
360         if(do_carrots) {
361                 low_input_carrot->update();
362                 high_input_carrot->update();
363                 gamma_carrot->update();
364                 low_output_carrot->update();
365                 high_output_carrot->update();
366         }
367
368         if(do_text) {
369                 low_input->update();
370                 gamma->update();
371                 high_input->update();
372                 low_output->update();
373                 high_output->update();
374                 threshold->update();
375         }
376 }
377
378
379 void HistogramWindow::draw_canvas_mode(int mode, int color, int y, int h)
380 {
381 // Draw histogram
382         int64_t max = 0;
383         int64_t *accum = plugin->accum[mode];
384         for( int k0=0,x=0; x<canvas_w; ++x ) {
385                 int k1 = (HISTOGRAM_SLOTS * (x+1)) / canvas_w;
386                 if( k0 == k1 ) continue;
387                 int64_t m = accum[k0];
388                 for( int k=k0; ++k<k1; ) {
389                         if( m < accum[k] ) m = accum[k];
390                 }
391                 if( max < m ) max = m;
392                 k0 = k1;
393         }
394         if( max > 0 ) {
395                 double log_slider = plugin->config.log_slider;
396                 double lin_slider = 1. - log_slider;
397                 double lin_max = (lin_slider * h) / max;
398                 double log_max = (log_slider * h) / log(max);
399                 for( int k0=0,x=0; x<canvas_w; ++x ) {
400                         int k1 = (HISTOGRAM_SLOTS * (x+1)) / canvas_w;
401                         if( k0 == k1 ) continue;
402                         int64_t m = accum[k0];
403                         for( int k=k0; ++k<k1; ) {
404                                 if( m < accum[k] ) m = accum[k];
405                         }
406                         int y1 = y+h;
407                         double vv = m > 0 ? (double)m : 0;
408                         m = vv > 0 ? vv*lin_max + log(vv)*log_max : 0;
409                         canvas->set_color(BLACK);
410                         int y0 = y1 - m;
411                         canvas->draw_line(x, y, x, y0);
412                         canvas->set_color(color);
413                         canvas->draw_line(x, y0, x, y1);
414                         k0 = k1;
415                 }
416         }
417         else {
418                 canvas->set_color(BLACK);
419                 canvas->draw_box(0, y, canvas_w, h);
420         }
421
422 // Draw overlays
423         canvas->set_color(WHITE);
424         canvas->set_line_width(2);
425         int y1 = 0;
426
427 // Draw output line
428         for( int x=0; x<canvas_w; ++x ) {
429                 float input = (float)x / canvas_w * FLOAT_RANGE + HIST_MIN_INPUT;
430                 float output = plugin->calculate_level(input, mode, 0);
431                 int y2 = h - (int)(output * h);
432                 if( x > 0 )
433                         canvas->draw_line(x-1, y+y1, x, y+y2);
434                 y1 = y2;
435         }
436
437         canvas->set_line_width(1);
438 }
439
440
441 void HistogramWindow::update_canvas()
442 {
443         if(plugin->parade)
444         {
445                 draw_canvas_mode(HISTOGRAM_RED, RED, 0, canvas_h / 3);
446                 draw_canvas_mode(HISTOGRAM_GREEN, GREEN, canvas_h / 3, canvas_h / 3);
447                 draw_canvas_mode(HISTOGRAM_BLUE, BLUE, canvas_h * 2 / 3, canvas_h - canvas_h * 2 / 3);
448         }
449         else
450         {
451                 draw_canvas_mode(plugin->mode, MEGREY, 0, canvas_h);
452         }
453
454
455 // Draw 0 and 100% lines.
456         canvas->set_color(RED);
457         int x = (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE);
458         canvas->draw_line(x, 0, x, canvas_h);
459         x = (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE);
460         canvas->draw_line(x, 0, x, canvas_h);
461         canvas->flash();
462 }
463
464
465 HistogramParade::HistogramParade(HistogramMain *plugin, HistogramWindow *gui,
466                 int x, int y, int value)
467  : BC_Toggle(x, y,
468         value ? plugin->get_theme()->get_image_set("histogram_rgb_toggle") :
469                 plugin->get_theme()->get_image_set("histogram_toggle"),
470         0)
471 {
472         this->plugin = plugin;
473         this->gui = gui;
474         this->value = value;
475         if(value)
476                 set_tooltip(_("RGB Parade on"));
477         else
478                 set_tooltip(_("RGB Parade off"));
479 }
480
481 int HistogramParade::handle_event()
482 {
483         update(1);
484         plugin->parade = value;
485         gui->update(1, 0, 0, 1);
486         return 1;
487 }
488
489 HistogramCanvas::HistogramCanvas(HistogramMain *plugin, HistogramWindow *gui,
490                 int x, int y, int w, int h)
491  : BC_SubWindow(x, y, w, h, BLACK)
492 {
493         this->plugin = plugin;
494         this->gui = gui;
495 }
496
497 int HistogramCanvas::button_press_event()
498 {
499         int result = 0;
500         if(is_event_win() && cursor_inside())
501         {
502                 if(!plugin->dragging_point &&
503                         (!plugin->config.automatic || plugin->mode == HISTOGRAM_VALUE))
504                 {
505                         gui->deactivate();
506                 }
507         }
508         return result;
509 }
510
511 int HistogramCanvas::cursor_motion_event()
512 {
513         if(is_event_win() && cursor_inside())
514         {
515         }
516         return 0;
517 }
518
519 int HistogramCanvas::button_release_event()
520 {
521         return 0;
522 }
523
524
525 HistogramReset::HistogramReset(HistogramMain *plugin, int x, int y)
526  : BC_GenericButton(x, y, _("Reset"))
527 {
528         this->plugin = plugin;
529 }
530 int HistogramReset::handle_event()
531 {
532         plugin->config.reset(0);
533         ((HistogramWindow*)plugin->thread->window)->update(1, 1, 1, 1);
534         plugin->send_configure_change();
535         return 1;
536 }
537
538
539 HistogramLogSlider::HistogramLogSlider(HistogramMain *plugin, HistogramWindow *gui,
540                 int x, int y)
541 : BC_FSlider(x, y, 0, xS(100), xS(100), 0., 1., plugin->config.log_slider)
542
543 {
544         this->plugin = plugin;
545         this->gui = gui;
546 }
547
548 int HistogramLogSlider::handle_event()
549 {
550         plugin->config.log_slider = get_value();
551         plugin->send_configure_change();
552         return 1;
553 }
554
555 HistogramCarrot::HistogramCarrot(HistogramMain *plugin, HistogramWindow *gui, int x, int y)
556  : BC_Toggle(x, y, plugin->get_theme()->get_image_set("histogram_carrot"), 0)
557 {
558         this->plugin = plugin;
559         this->gui = gui;
560         drag_operation = 0;
561 }
562
563 HistogramCarrot::~HistogramCarrot()
564 {
565 }
566
567 float* HistogramCarrot::get_value()
568 {
569         if( this == gui->low_input_carrot )
570                 return &plugin->config.low_input[plugin->mode];
571         if( this == gui->high_input_carrot )
572                 return &plugin->config.high_input[plugin->mode];
573         if( this == gui->gamma_carrot )
574                 return &plugin->config.gamma[plugin->mode];
575         if( this == gui->low_output_carrot )
576                 return &plugin->config.low_output[plugin->mode];
577         if( this == gui->high_output_carrot )
578                 return &plugin->config.high_output[plugin->mode];
579         return 0;
580 }
581
582 void HistogramCarrot::update()
583 {
584         int new_x = 0;
585         float *value = get_value();
586
587         if(this != gui->gamma_carrot)
588         {
589                 new_x = (int)(gui->canvas->get_x() +
590                         (*value - HIST_MIN_INPUT) *
591                         gui->canvas->get_w() /
592                         (HIST_MAX_INPUT - HIST_MIN_INPUT) -
593                         get_w() / 2);
594         }
595         else
596         {
597                 float min = plugin->config.low_input[plugin->mode];
598                 float max = plugin->config.high_input[plugin->mode];
599                 float delta = (max - min) / 2.0;
600                 float mid = min + delta;
601                 float tmp = log10(1.0 / *value);
602                 tmp = mid + delta * tmp;
603
604 //printf("HistogramCarrot::update %d %f %f\n", __LINE__, *value, tmp);
605
606                         new_x = gui->canvas->get_x() -
607                                 get_w() / 2 +
608                                 (int)(gui->canvas->get_w() *
609                                 (tmp - HIST_MIN_INPUT) /
610                                 (HIST_MAX_INPUT - HIST_MIN_INPUT));
611         }
612
613         reposition_window(new_x, get_y());
614 }
615
616 int HistogramCarrot::button_press_event()
617 {
618         if(is_event_win() && get_buttonpress() == 1)
619         {
620                 //int w = get_w();
621                 gui->deactivate();
622                 set_status(BC_Toggle::TOGGLE_DOWN);
623
624                 BC_Toggle::update(0);
625                 gui->active_value = get_value();
626 // Disable the other toggles
627                 if(this != gui->low_input_carrot) gui->low_input_carrot->BC_Toggle::update(0);
628                 if(this != gui->high_input_carrot) gui->high_input_carrot->BC_Toggle::update(0);
629                 if(this != gui->gamma_carrot) gui->gamma_carrot->BC_Toggle::update(0);
630                 if(this != gui->low_output_carrot) gui->low_output_carrot->BC_Toggle::update(0);
631                 if(this != gui->high_output_carrot) gui->high_output_carrot->BC_Toggle::update(0);
632                 starting_x = get_x();
633                 offset_x = gui->get_relative_cursor_x();
634                 offset_y = gui->get_relative_cursor_y();
635 //printf("HistogramCarrot::button_press_event %d %d %d\n", __LINE__, starting_x, offset_x);
636                 drag_operation = 1;
637                 draw_face(1, 1);
638                 return 1;
639         }
640         return 0;
641 }
642
643 int HistogramCarrot::button_release_event()
644 {
645         int result = BC_Toggle::button_release_event();
646         handle_event();
647         drag_operation = 0;
648         return result;
649 }
650
651 int HistogramCarrot::cursor_motion_event()
652 {
653         int cursor_x = gui->get_relative_cursor_x();
654
655         if(drag_operation)
656         {
657 //printf("HistogramCarrot::cursor_motion_event %d %d\n", __LINE__, cursor_x);
658                 int new_x = starting_x + cursor_x - offset_x;
659
660 // Clamp x
661 // Get level from x
662                 float *value = get_value();
663                 if(this == gui->gamma_carrot)
664                 {
665                         float min = gui->low_input_carrot->get_x();
666                         float max = gui->high_input_carrot->get_x();
667                         float delta = (max - min) / 2.0;
668                         if(delta >= 0.5)
669                         {
670                                 float mid = min + delta;
671                                 float tmp = (float)(new_x - mid) /
672                                         delta;
673                                 tmp = 1.0 / pow(10, tmp);
674                                 CLAMP(tmp, MIN_GAMMA, MAX_GAMMA);
675                                 *value = tmp;
676 //printf("HistogramCarrot::update %d %f\n", __LINE__, tmp);
677                         }
678                 }
679                 else
680                 {
681                         int min_x = gui->canvas->get_x() - get_w() / 2;
682                         int max_x = gui->canvas->get_x() + gui->canvas->get_w() - get_w() / 2;
683                         CLAMP(new_x, min_x, max_x);
684                         *value = HIST_MIN_INPUT +
685                                 (HIST_MAX_INPUT - HIST_MIN_INPUT) *
686                                 (new_x - min_x) /
687                                 (max_x - min_x);
688                 }
689
690                 reposition_window(new_x, get_y());
691                 flush();
692
693                 gui->update(1,
694                         (this == gui->low_input_carrot || this == gui->high_input_carrot),
695                         1,
696                         0);
697                 plugin->send_configure_change();
698
699                 return 1;
700         }
701         return 0;
702 }
703
704
705
706 HistogramSlider::HistogramSlider(HistogramMain *plugin, HistogramWindow *gui,
707                 int x, int y, int w, int h, int is_input)
708  : BC_SubWindow(x, y, w, h)
709 {
710         this->plugin = plugin;
711         this->gui = gui;
712         this->is_input = is_input;
713         operation = NONE;
714 }
715
716 int HistogramSlider::input_to_pixel(float input)
717 {
718         return (int)((input - HIST_MIN_INPUT) / FLOAT_RANGE * get_w());
719 }
720
721 void HistogramSlider::update()
722 {
723         int w = get_w();
724         int h = get_h();
725         //int half_h = get_h() / 2;
726         //int quarter_h = get_h() / 4;
727         int mode = plugin->mode;
728         int r = 0xff;
729         int g = 0xff;
730         int b = 0xff;
731
732         clear_box(0, 0, w, h);
733
734         switch(mode) {
735         case HISTOGRAM_RED:
736                 g = b = 0x00;
737                 break;
738         case HISTOGRAM_GREEN:
739                 r = b = 0x00;
740                 break;
741         case HISTOGRAM_BLUE:
742                 r = g = 0x00;
743                 break;
744         }
745
746         for( int i = 0; i < w; i++ ) {
747                 int color = (int)(i * 0xff / w);
748                 set_color(((r * color / 0xff) << 16) |
749                         ((g * color / 0xff) << 8) |
750                         (b * color / 0xff));
751                 draw_line(i, 0, i, h);
752         }
753         flash();
754 }
755
756
757 HistogramAuto::HistogramAuto(HistogramMain *plugin, int x, int y)
758  : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
759 {
760         this->plugin = plugin;
761 }
762
763 int HistogramAuto::handle_event()
764 {
765         plugin->config.automatic = get_value();
766         plugin->send_configure_change();
767         return 1;
768 }
769
770
771 HistogramPlot::HistogramPlot(HistogramMain *plugin, int x, int y)
772  : BC_CheckBox(x, y, plugin->config.plot, _("Plot histogram"))
773 {
774         this->plugin = plugin;
775 }
776
777 int HistogramPlot::handle_event()
778 {
779         plugin->config.plot = get_value();
780         plugin->send_configure_change();
781         return 1;
782 }
783
784
785 HistogramSumFrames::HistogramSumFrames(HistogramMain *plugin, int x, int y)
786  : BC_CheckBox(x, y, plugin->config.sum_frames, _("Sum frames"))
787 {
788         this->plugin = plugin;
789 }
790
791 int HistogramSumFrames::handle_event()
792 {
793         plugin->config.sum_frames = get_value();
794         plugin->send_configure_change();
795         return 1;
796 }
797
798
799 HistogramSplit::HistogramSplit(HistogramMain *plugin, int x, int y)
800  : BC_CheckBox(x, y, plugin->config.split, _("Split output"))
801 {
802         this->plugin = plugin;
803 }
804
805 int HistogramSplit::handle_event()
806 {
807         plugin->config.split = get_value();
808         plugin->send_configure_change();
809         return 1;
810 }
811
812
813 HistogramMode::HistogramMode(HistogramMain *plugin,
814                 int x, int y, int value, char *text)
815  : BC_Radial(x, y, plugin->mode == value, text)
816 {
817         this->plugin = plugin;
818         this->value = value;
819 }
820 int HistogramMode::handle_event()
821 {
822         HistogramWindow *gui = (HistogramWindow*)plugin->thread->window;
823         plugin->mode = value;
824         plugin->current_point= -1;
825         gui->active_value = 0;
826         gui->low_input_carrot->BC_Toggle::update(0);
827         gui->gamma_carrot->BC_Toggle::update(0);
828         gui->high_input_carrot->BC_Toggle::update(0);
829         gui->low_output_carrot->BC_Toggle::update(0);
830         gui->high_output_carrot->BC_Toggle::update(0);
831         gui->update(1, 1, 1, 1);
832 //      plugin->send_configure_change();
833         return 1;
834 }
835
836
837 HistogramText::HistogramText(HistogramMain *plugin,
838         HistogramWindow *gui, int x, int y, float hist_min, float hist_max)
839  : BC_TumbleTextBox(gui, 0.0, hist_min, hist_max, x, y, xS(80))
840 {
841         this->plugin = plugin;
842         this->gui = gui;
843         set_precision(DIGITS);
844         set_increment(PRECISION);
845 }
846
847 float* HistogramText::get_value()
848 {
849         if( this == gui->low_input )
850                 return &plugin->config.low_input[plugin->mode];
851         if( this == gui->high_input )
852                 return &plugin->config.high_input[plugin->mode];
853         if( this == gui->gamma )
854                 return &plugin->config.gamma[plugin->mode];
855         if( this == gui->low_output )
856                 return &plugin->config.low_output[plugin->mode];
857         if( this == gui->high_output )
858                 return &plugin->config.high_output[plugin->mode];
859         if( this == gui->threshold )
860                 return &plugin->config.threshold;
861         return 0;
862 }
863
864 int HistogramText::handle_event()
865 {
866         float *output = get_value();
867         if( output )
868                 *output = atof(get_text());
869
870         gui->update(1, 1, 0, 0);
871         plugin->send_configure_change();
872         return 1;
873 }
874
875 void HistogramText::update()
876 {
877         float *output = get_value();
878         if( output )
879                 BC_TumbleTextBox::update(*output);
880 }
881