dynamic keyframes, textbox rework, andrea ffmpeg.opts, perpetual chkpt undo, lv2...
[goodguy/history.git] / cinelerra-5.1 / plugins / histogram_bezier / bistogramwindow.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 "bistogram.h"
25 #include "bistogramconfig.h"
26 #include "bistogramwindow.h"
27 #include "keys.h"
28 #include "language.h"
29
30
31 #include <unistd.h>
32 #include <string.h>
33
34 HistogramWindow::HistogramWindow(HistogramMain *plugin)
35  : PluginClientWindow(plugin, 440, 480, 440, 480, 0)
36 {
37         this->plugin = plugin;
38 }
39
40 HistogramWindow::~HistogramWindow()
41 {
42 }
43
44 #include "min_picon_png.h"
45 #include "mid_picon_png.h"
46 #include "max_picon_png.h"
47 static VFramePng max_picon_image(max_picon_png);
48 static VFramePng mid_picon_image(mid_picon_png);
49 static VFramePng min_picon_image(min_picon_png);
50
51 void HistogramWindow::create_objects()
52 {
53         int x = 10, y = 10, x1 = 10;
54         BC_Title *title = 0;
55
56         max_picon = create_pixmap(&max_picon_image);
57         mid_picon = create_pixmap(&mid_picon_image);
58         min_picon = create_pixmap(&min_picon_image);
59         add_subwindow(mode_v = new HistogramMode(plugin,
60                 x,
61                 y,
62                 HISTOGRAM_VALUE,
63                 _("Value")));
64         x += 70;
65         add_subwindow(mode_r = new HistogramMode(plugin,
66                 x,
67                 y,
68                 HISTOGRAM_RED,
69                 _("Red")));
70         x += 70;
71         add_subwindow(mode_g = new HistogramMode(plugin,
72                 x,
73                 y,
74                 HISTOGRAM_GREEN,
75                 _("Green")));
76         x += 70;
77         add_subwindow(mode_b = new HistogramMode(plugin,
78                 x,
79                 y,
80                 HISTOGRAM_BLUE,
81                 _("Blue")));
82 //      x += 70;
83 //      add_subwindow(mode_a = new HistogramMode(plugin,
84 //              x,
85 //              y,
86 //              HISTOGRAM_ALPHA,
87 //              _("Alpha")));
88
89         x = x1;
90         y += 30;
91         add_subwindow(title = new BC_Title(x, y, _("Input X:")));
92         x += title->get_w() + 10;
93         input_x = new HistogramInputText(plugin,
94                 this,
95                 x,
96                 y,
97                 1);
98         input_x->create_objects();
99
100         x += input_x->get_w() + 10;
101         add_subwindow(title = new BC_Title(x, y, _("Input Y:")));
102         x += title->get_w() + 10;
103         input_y = new HistogramInputText(plugin,
104                 this,
105                 x,
106                 y,
107                 0);
108         input_y->create_objects();
109
110         y += 30;
111         x = x1;
112
113         canvas_w = get_w() - x - x;
114         canvas_h = get_h() - y - 170;
115         title1_x = x;
116         title2_x = x + (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE);
117         title3_x = x + (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE);
118         title4_x = x + (int)(canvas_w);
119         add_subwindow(canvas = new HistogramCanvas(plugin,
120                 this,
121                 x,
122                 y,
123                 canvas_w,
124                 canvas_h));
125         draw_canvas_overlay();
126         canvas->flash();
127
128         y += canvas->get_h() + 1;
129         add_subwindow(new BC_Title(title1_x,
130                 y,
131                 "-10%"));
132         add_subwindow(new BC_Title(title2_x,
133                 y,
134                 "0%"));
135         add_subwindow(new BC_Title(title3_x - get_text_width(MEDIUMFONT, "100"),
136                 y,
137                 "100%"));
138         add_subwindow(new BC_Title(title4_x - get_text_width(MEDIUMFONT, "110"),
139                 y,
140                 "110%"));
141
142         y += 20;
143         add_subwindow(title = new BC_Title(x, y, _("Output min:")));
144         x += title->get_w() + 10;
145         output_min = new HistogramOutputText(plugin,
146                 this,
147                 x,
148                 y,
149                 &plugin->config.output_min[plugin->mode]);
150         output_min->create_objects();
151         x += output_min->get_w() + 10;
152         add_subwindow(new BC_Title(x, y, _("Output Max:")));
153         x += title->get_w() + 10;
154         output_max = new HistogramOutputText(plugin,
155                 this,
156                 x,
157                 y,
158                 &plugin->config.output_max[plugin->mode]);
159         output_max->create_objects();
160
161         x = x1;
162         y += 30;
163
164         add_subwindow(output = new HistogramSlider(plugin,
165                 this,
166                 x,
167                 y,
168                 get_w() - 20,
169                 30,
170                 0));
171         output->update();
172         y += 40;
173
174
175         add_subwindow(automatic = new HistogramAuto(plugin,
176                 x,
177                 y));
178
179         x += 120;
180         add_subwindow(new HistogramReset(plugin,
181                 x,
182                 y));
183         x += 100;
184         add_subwindow(new BC_Title(x, y, _("Threshold:")));
185         x += 100;
186         threshold = new HistogramOutputText(plugin,
187                 this,
188                 x,
189                 y,
190                 &plugin->config.threshold);
191         threshold->create_objects();
192         x = x1;
193         y += 40;
194         add_subwindow(split = new HistogramSplit(plugin, x, y));
195         y += 6;
196         x += 150;
197         add_subwindow(new BC_Title(x,y, _("Interpolation:")));
198         x += 120;
199         add_subwindow(smoothModeChoser = new HistogramSmoothMode(plugin, this, x, y));
200         smoothModeChoser->create_objects();
201
202         show_window();
203 }
204
205 int HistogramWindow::keypress_event()
206 {
207         int result = 0;
208         if(get_keypress() == BACKSPACE ||
209                 get_keypress() == DELETE)
210         {
211                 if(plugin->current_point >= 0)
212                 {
213                         HistogramPoint *current =
214                                 plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
215                         delete current;
216                         plugin->current_point = -1;
217                         update_input();
218                         update_canvas();
219                         plugin->send_configure_change();
220                         result = 1;
221                 }
222         }
223         return result;
224 }
225
226 void HistogramWindow::update(int do_input)
227 {
228         automatic->update(plugin->config.automatic);
229         threshold->update(plugin->config.threshold);
230         update_mode();
231
232         if(do_input) update_input();
233         update_output();
234 }
235
236 void HistogramWindow::update_input()
237 {
238         input_x->update();
239         input_y->update();
240 }
241
242 void HistogramWindow::update_output()
243 {
244         output->update();
245         output_min->update(plugin->config.output_min[plugin->mode]);
246         output_max->update(plugin->config.output_max[plugin->mode]);
247 }
248
249 void HistogramWindow::update_mode()
250 {
251         mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
252         mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
253         mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
254         mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
255         output_min->output = &plugin->config.output_min[plugin->mode];
256         output_max->output = &plugin->config.output_max[plugin->mode];
257 }
258
259 void HistogramWindow::draw_canvas_overlay()
260 {
261         canvas->set_color(0x00ff00);
262         int y1;
263
264 // Calculate output curve
265         plugin->tabulate_curve(plugin->mode, 0);
266
267 // Draw output line
268         for(int i = 0; i < canvas_w; i++)
269         {
270                 float input = (float)i /
271                                 canvas_w *
272                                 FLOAT_RANGE +
273                                 HIST_MIN_INPUT;
274                 float output = plugin->calculate_smooth(input, plugin->mode);
275
276                 int y2 = canvas_h - (int)(output * canvas_h);
277                 if(i > 0)
278                 {
279                         canvas->draw_line(i - 1, y1, i, y2);
280                 }
281                 y1 = y2;
282         }
283
284 // Draw output points
285         HistogramPoint *current = plugin->config.points[plugin->mode].first;
286         int number = 0;
287         while(current)
288         {
289                 int x = (int)((current->x - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE);
290                 int y = (int)(canvas_h - current->y * canvas_h);
291                 if(number == plugin->current_point)
292                         canvas->draw_box(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
293                 else
294                         canvas->draw_rectangle(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
295
296 //Draw gradients
297         if (plugin->config.smoothMode > HISTOGRAM_LINEAR)
298         {
299                 int x1,x2,y1,y2;
300                 canvas->set_color(0x0000ff);
301                 x2 = (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE);
302                 x1 = (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE);
303                 y2 = (int)(canvas_h - (current->y + current->xoffset_right * current->gradient) * canvas_h);
304                 y1 = (int)(canvas_h - (current->y + current->xoffset_left * current->gradient) * canvas_h);
305 /*              x2 = x + (title3_x - title2_x)/20;
306                 x1 = x - (title3_x - title2_x)/20;
307                 y1 = y + (int)(current->gradient * (float)(canvas_h)/20.0);
308                 y2 = y - (int)(current->gradient * (float)(canvas_h)/20.0);
309 //              int y2 = (int)(canvas_h - canvas_h * (current->y + current->gradient /10));*/
310                 canvas->draw_line(x1,y1,x2,y2);
311
312                 canvas->draw_circle(x1 - BOX_SIZE / 4, y1 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2);
313                 canvas->draw_circle(x2 - BOX_SIZE / 4, y2 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2);
314                 canvas->set_color(0x00ff00);
315         }
316
317                 current = NEXT;
318                 number++;
319         }
320
321
322 // Draw 0 and 100% lines.
323         canvas->set_color(0xff0000);
324         canvas->draw_line(title2_x - canvas->get_x(),
325                 0,
326                 title2_x - canvas->get_x(),
327                 canvas_h);
328         canvas->draw_line(title3_x - canvas->get_x(),
329                 0,
330                 title3_x - canvas->get_x(),
331                 canvas_h);
332 }
333
334 void HistogramWindow::update_canvas()
335 {
336         int *accum = plugin->accum[plugin->mode];
337         int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1;
338         float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w;
339         int normalize = 0;
340         int max = 0;
341
342         for(int i = 0; i < HISTOGRAM_SLOTS; i++)
343         {
344                 if(accum && accum[i] > normalize) normalize = accum[i];
345         }
346
347
348         if(normalize)
349         {
350                 for(int i = 0; i < canvas_w; i++)
351                 {
352                         int accum_start = (int)(accum_per_canvas_f * i);
353                         int accum_end = accum_start + accum_per_canvas_i;
354                         max = 0;
355                         for(int j = accum_start; j < accum_end; j++)
356                         {
357                                 max = MAX(accum[j], max);
358                         }
359
360 //                      max = max * canvas_h / normalize;
361                         max = (int)(log(max) / log(normalize) * canvas_h);
362
363                         canvas->set_color(0xffffff);
364                         canvas->draw_line(i, 0, i, canvas_h - max);
365                         canvas->set_color(0x000000);
366                         canvas->draw_line(i, canvas_h - max, i, canvas_h);
367                 }
368         }
369         else
370         {
371                 canvas->set_color(0xffffff);
372                 canvas->draw_box(0, 0, canvas_w, canvas_h);
373         }
374
375
376         draw_canvas_overlay();
377         canvas->flash();
378 }
379
380
381
382
383
384
385
386
387 HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
388         HistogramWindow *gui,
389         int x,
390         int y,
391         int w,
392         int h)
393  : BC_SubWindow(x,
394         y,
395         w,
396         h,
397         0xffffff)
398 {
399         this->plugin = plugin;
400         this->gui = gui;
401 }
402
403 int HistogramCanvas::button_press_event()
404 {
405         int result = 0;
406         if(is_event_win() && cursor_inside())
407         {
408                 if(!plugin->dragging_point)
409                 {
410                         HistogramPoint *new_point = 0;
411                         gui->deactivate();
412 // Search for existing point under cursor
413                         HistogramPoint *current = plugin->config.points[plugin->mode].first;
414                         plugin->current_point = -1;
415                         int dragID = 0;
416                         while(current)
417                         {
418                                 int x = (int)((current->x - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
419                                 int y = (int)(gui->canvas_h - current->y * gui->canvas_h);
420
421 /* Check for click on main point */
422                                 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
423                                         get_cursor_y() >= y - BOX_SIZE / 2 &&
424                                         get_cursor_x() < x + BOX_SIZE / 2 &&
425                                         get_cursor_y() < y + BOX_SIZE / 2)
426                                 {
427                                         plugin->current_point =
428                                                 plugin->config.points[plugin->mode].number_of(current);
429                                         plugin->point_x_offset = get_cursor_x() - x;
430                                         plugin->point_y_offset = get_cursor_y() - y;
431                                         dragID = 1;
432                                         break;
433                                 }
434 //                              if (plugin->config.smoothMode == HISTOGRAM_LINEAR)
435 //                                break;
436
437                                 int xright =
438                                   (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
439                                 int yright =
440                                   (int)(gui->canvas_h - (current->y + current->xoffset_right * current->gradient) *
441                                   gui->canvas_h);
442
443 /* Check for click on right handle */
444                                 if(get_cursor_x() >= xright - BOX_SIZE / 2 &&
445                                    get_cursor_y() >= yright - BOX_SIZE / 2 &&
446                                    get_cursor_x() <  xright + BOX_SIZE / 2 &&
447                                    get_cursor_y() <  yright + BOX_SIZE / 2)
448                                 {
449                                         plugin->current_point =
450                                                 plugin->config.points[plugin->mode].number_of(current);
451                                         plugin->point_x_offset = get_cursor_x() - xright;
452                                         plugin->point_y_offset = get_cursor_y() - yright;
453                                         dragID = 2;
454                                         break;
455                                 }
456
457 /* Check for click on left handle */
458                                 int xleft =
459                                   (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
460                                 int yleft =
461                                   (int)(gui->canvas_h - (current->y + current->xoffset_left * current->gradient) *
462                                   gui->canvas_h);
463                                 if(get_cursor_x() >= xleft - BOX_SIZE / 2 &&
464                                    get_cursor_y() >= yleft - BOX_SIZE / 2 &&
465                                    get_cursor_x() <  xleft + BOX_SIZE / 2 &&
466                                    get_cursor_y() <  yleft + BOX_SIZE / 2)
467                                 {
468                                         plugin->current_point =
469                                                 plugin->config.points[plugin->mode].number_of(current);
470                                         plugin->point_x_offset = get_cursor_x() - xleft;
471                                         plugin->point_y_offset = get_cursor_y() - yleft;
472                                         dragID = 3;
473                                         break;
474                                 }
475
476
477                                 current = NEXT;
478                         }
479
480                         if(plugin->current_point < 0)
481                         {
482 // Create new point under cursor
483                                 float current_x = (float)get_cursor_x() *
484                                         FLOAT_RANGE /
485                                         get_w() +
486                                         HIST_MIN_INPUT;
487                                 float current_y = 1.0 -
488                                         (float)get_cursor_y() /
489                                         get_h();
490                                 new_point =
491                                         plugin->config.points[plugin->mode].insert(current_x, current_y);
492                                 plugin->current_point =
493                                         plugin->config.points[plugin->mode].number_of(new_point);
494                                 plugin->point_x_offset = 0;
495                                 plugin->point_y_offset = 0;
496
497 // Default gradient
498 // Get 2 points surrounding current position
499                                 float x1 = 0, x2 = 1, y1 = 0, y2 = 1;
500
501                                 HistogramPoint *current = plugin->config.points[plugin->mode].first;
502                                 int done = 0;
503                                 while(current && !done)
504                                 {
505                                         if(current->x > current_x)
506                                         {
507                                                 x2 = current->x;
508                                                 y2 = current->y;
509                                                 done = 1;
510                                         }
511                                         else
512                                                 current = NEXT;
513                                 }
514
515                                 current = plugin->config.points[plugin->mode].last;
516                                 done = 0;
517                                 while(current && !done)
518                                 {
519                                         if(current->x <= current_x)
520                                         {
521                                                 x1 = current->x;
522                                                 y1 = current->y;
523                                                 done = 1;
524                                         }
525                                         else
526                                                 current = PREVIOUS;
527                                 }
528                                 new_point->gradient = (y2 - y1) / (x2 - x1);
529                                 dragID = 1;
530
531                         }
532
533
534                         plugin->dragging_point = dragID;
535                         result = 1;
536
537                         plugin->config.boundaries();
538                         gui->update_input();
539                         gui->update_canvas();
540                         if(new_point)
541                         {
542                                 plugin->send_configure_change();
543                         }
544                 }
545         }
546         return result;
547 }
548
549 int HistogramCanvas::cursor_motion_event()
550 {
551         if(plugin->dragging_point)
552         {
553                 HistogramPoint * current_point = plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
554
555                 float current_x =
556                         (float)(get_cursor_x() - plugin->point_x_offset) *
557                         FLOAT_RANGE /
558                         get_w() +
559                         HIST_MIN_INPUT;
560                 float current_y = 1.0 -
561                         (float)(get_cursor_y() - plugin->point_y_offset) /
562                         get_h();
563
564                 switch(plugin->dragging_point)
565                 {
566                   case 1: /* Main point dragged */
567                         current_point->x = current_x;
568                         current_point->y = current_y;
569                         break;
570                   case 2: /* Right control point dragged */
571                         if (current_x - current_point->x > 0)
572                         {
573                           current_point->xoffset_right = current_x - current_point->x;
574                           current_point->gradient = (current_y - current_point->y) / (current_x - current_point->x);
575                         }
576                         break;
577                   case 3: /* Left control point dragged */
578                         if (current_x - current_point->x < 0)
579                         {
580                           current_point->xoffset_left = current_x - current_point->x;
581                           current_point->gradient = (current_point->y - current_y) / (current_point->x - current_x);
582                         }
583                         break;
584                 }
585
586                 plugin->config.boundaries();
587                 gui->update_input();
588                 gui->update_canvas();
589                 plugin->send_configure_change();
590                 return 1;
591         }
592         return 0;
593 }
594
595 int HistogramCanvas::button_release_event()
596 {
597         if(plugin->dragging_point)
598         {
599 // Test for out of order points to delete.
600                 HistogramPoint *current =
601                         plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
602                 HistogramPoint *prev = PREVIOUS;
603                 HistogramPoint *next = NEXT;
604
605                 if((prev && prev->x >= current->x) ||
606                         (next && next->x <= current->x))
607                 {
608                         delete current;
609                         plugin->current_point = -1;
610                         plugin->config.boundaries();
611                         gui->update_input();
612                         gui->update_canvas();
613                         plugin->send_configure_change();
614                 }
615
616                 plugin->dragging_point = 0;
617         }
618         return 0;
619 }
620
621
622
623
624
625
626
627 HistogramReset::HistogramReset(HistogramMain *plugin,
628         int x,
629         int y)
630  : BC_GenericButton(x, y, _("Reset"))
631 {
632         this->plugin = plugin;
633 }
634 int HistogramReset::handle_event()
635 {
636         plugin->config.reset(0);
637         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
638         window->update(1);
639         window->update_canvas();
640         plugin->send_configure_change();
641         return 1;
642 }
643
644
645
646
647
648
649
650
651
652 HistogramSlider::HistogramSlider(HistogramMain *plugin,
653         HistogramWindow *gui,
654         int x,
655         int y,
656         int w,
657         int h,
658         int is_input)
659  : BC_SubWindow(x, y, w, h)
660 {
661         this->plugin = plugin;
662         this->gui = gui;
663         this->is_input = is_input;
664         operation = NONE;
665 }
666
667 int HistogramSlider::input_to_pixel(float input)
668 {
669         return (int)((input - HIST_MIN_INPUT) / FLOAT_RANGE * get_w());
670 }
671
672 int HistogramSlider::button_press_event()
673 {
674         if(is_event_win() && cursor_inside())
675         {
676 //              int w = get_w();
677                 int h = get_h();
678                 int half_h = get_h() / 2;
679
680                 gui->deactivate();
681
682                 if(operation == NONE)
683                 {
684                         int x1 = input_to_pixel(plugin->config.output_min[plugin->mode]) -
685                                 gui->mid_picon->get_w() / 2;
686                         int x2 = x1 + gui->mid_picon->get_w();
687                         if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
688                                 get_cursor_y() >= half_h && get_cursor_y() < h)
689                         {
690                                 operation = DRAG_MIN_OUTPUT;
691                         }
692                 }
693
694                 if(operation == NONE)
695                 {
696                         int x1 = input_to_pixel(plugin->config.output_max[plugin->mode]) -
697                                 gui->mid_picon->get_w() / 2;
698                         int x2 = x1 + gui->mid_picon->get_w();
699                         if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
700                                 get_cursor_y() >= half_h && get_cursor_y() < h)
701                         {
702                                 operation = DRAG_MAX_OUTPUT;
703                         }
704                 }
705                 return 1;
706         }
707         return 0;
708 }
709
710 int HistogramSlider::button_release_event()
711 {
712         if(operation != NONE)
713         {
714                 operation = NONE;
715                 return 1;
716         }
717         return 0;
718 }
719
720 int HistogramSlider::cursor_motion_event()
721 {
722         if(operation != NONE)
723         {
724                 float value = (float)get_cursor_x() / get_w() * FLOAT_RANGE + HIST_MIN_INPUT;
725                 CLAMP(value, HIST_MIN_INPUT, HIST_MAX_INPUT);
726
727                 switch(operation)
728                 {
729                         case DRAG_MIN_OUTPUT:
730                                 value = MIN(plugin->config.output_max[plugin->mode], value);
731                                 plugin->config.output_min[plugin->mode] = value;
732                                 break;
733                         case DRAG_MAX_OUTPUT:
734                                 value = MAX(plugin->config.output_min[plugin->mode], value);
735                                 plugin->config.output_max[plugin->mode] = value;
736                                 break;
737                 }
738
739                 plugin->config.boundaries();
740                 gui->update_output();
741
742                 plugin->send_configure_change();
743                 return 1;
744         }
745         return 0;
746 }
747
748 void HistogramSlider::update()
749 {
750         int w = get_w();
751         int h = get_h();
752         int half_h = get_h() / 2;
753 //      int quarter_h = get_h() / 4;
754         int mode = plugin->mode;
755         int r = 0xff;
756         int g = 0xff;
757         int b = 0xff;
758
759         clear_box(0, 0, w, h);
760
761         switch(mode)
762         {
763                 case HISTOGRAM_RED:
764                         g = b = 0x00;
765                         break;
766                 case HISTOGRAM_GREEN:
767                         r = b = 0x00;
768                         break;
769                 case HISTOGRAM_BLUE:
770                         r = g = 0x00;
771                         break;
772         }
773
774         for(int i = 0; i < w; i++)
775         {
776                 int color = (int)(i * 0xff / w);
777                 set_color(((r * color / 0xff) << 16) |
778                         ((g * color / 0xff) << 8) |
779                         (b * color / 0xff));
780
781                 draw_line(i, 0, i, half_h);
782         }
783
784         float min;
785         float max;
786         min = plugin->config.output_min[plugin->mode];
787         max = plugin->config.output_max[plugin->mode];
788
789         draw_pixmap(gui->min_picon,
790                 input_to_pixel(min) - gui->min_picon->get_w() / 2,
791                 half_h + 1);
792         draw_pixmap(gui->max_picon,
793                 input_to_pixel(max) - gui->max_picon->get_w() / 2,
794                 half_h + 1);
795
796         flash();
797         flush();
798 }
799
800
801
802
803
804
805
806
807
808 HistogramAuto::HistogramAuto(HistogramMain *plugin,
809         int x,
810         int y)
811  : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
812 {
813         this->plugin = plugin;
814 }
815
816 int HistogramAuto::handle_event()
817 {
818         plugin->config.automatic = get_value();
819         plugin->send_configure_change();
820         return 1;
821 }
822
823
824
825
826 HistogramSplit::HistogramSplit(HistogramMain *plugin,
827         int x,
828         int y)
829  : BC_CheckBox(x, y, plugin->config.split, _("Split picture"))
830 {
831         this->plugin = plugin;
832 }
833
834 int HistogramSplit::handle_event()
835 {
836         plugin->config.split = get_value();
837         plugin->send_configure_change();
838         return 1;
839 }
840
841
842
843
844 HistogramMode::HistogramMode(HistogramMain *plugin,
845         int x,
846         int y,
847         int value,
848         char *text)
849  : BC_Radial(x, y, plugin->mode == value, text)
850 {
851         this->plugin = plugin;
852         this->value = value;
853 }
854 int HistogramMode::handle_event()
855 {
856         plugin->mode = value;
857         plugin->current_point= -1;
858         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
859         window->update_canvas();
860         window->update_mode();
861         window->update_input();
862         window->update_canvas();
863         window->update_output();
864         window->output->update();
865 //      plugin->send_configure_change();
866         return 1;
867 }
868
869
870
871
872
873
874
875
876
877 HistogramOutputText::HistogramOutputText(HistogramMain *plugin,
878         HistogramWindow *gui,
879         int x,
880         int y,
881         float *output)
882  : BC_TumbleTextBox(gui,
883                 output ? (float)*output : 0.0,
884                 (float)HIST_MIN_INPUT,
885                 (float)HIST_MAX_INPUT,
886                 x,
887                 y,
888                 60)
889 {
890         this->plugin = plugin;
891         this->output = output;
892         set_precision(DIGITS);
893         set_increment(PRECISION);
894 }
895
896
897 int HistogramOutputText::handle_event()
898 {
899         if(output)
900         {
901                 *output = atof(get_text());
902         }
903
904         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
905         window->output->update();
906         plugin->send_configure_change();
907         return 1;
908 }
909
910
911
912
913
914
915
916
917 HistogramInputText::HistogramInputText(HistogramMain *plugin,
918         HistogramWindow *gui,
919         int x,
920         int y,
921         int do_x)
922  : BC_TumbleTextBox(gui,
923                 0.0,
924                 (float)HIST_MIN_INPUT,
925                 (float)HIST_MAX_INPUT,
926                 x,
927                 y,
928                 60)
929 {
930         this->do_x = do_x;
931         this->plugin = plugin;
932         this->gui = gui;
933         set_precision(DIGITS);
934         set_increment(PRECISION);
935 }
936
937
938 int HistogramInputText::handle_event()
939 {
940         if(plugin->current_point >= 0 &&
941                 plugin->current_point < plugin->config.points[plugin->mode].total())
942         {
943                 HistogramPoint *point =
944                         plugin->config.points[plugin->mode].get_item_number(
945                                 plugin->current_point);
946
947                 if(point)
948                 {
949                         if(do_x)
950                                 point->x = atof(get_text());
951                         else
952                                 point->y = atof(get_text());
953
954                         plugin->config.boundaries();
955                         gui->update_canvas();
956
957                         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
958                         window->output->update();
959                         plugin->send_configure_change();
960                 }
961         }
962         return 1;
963 }
964
965 void HistogramInputText::update()
966 {
967         if(plugin->current_point >= 0 &&
968                 plugin->current_point < plugin->config.points[plugin->mode].total())
969         {
970                 HistogramPoint *point =
971
972                         plugin->config.points[plugin->mode].get_item_number(
973                                 plugin->current_point);
974
975                 if(point)
976                 {
977                         if(do_x)
978                                 BC_TumbleTextBox::update(point->x);
979                         else
980                                 BC_TumbleTextBox::update(point->y);
981                 }
982                 else
983                 {
984                         BC_TumbleTextBox::update((float)0.0);
985                 }
986         }
987         else
988         {
989                 BC_TumbleTextBox::update((float)0.0);
990         }
991
992 }
993
994
995 HistogramSmoothMode::HistogramSmoothMode(HistogramMain*plugin,
996         HistogramWindow *gui,
997         int x,
998         int y)
999  : BC_PopupMenu(x, y, 120, to_text(plugin->config.smoothMode), 1)
1000 {
1001         this->plugin = plugin;
1002         this->gui = gui;
1003 }
1004 void HistogramSmoothMode::create_objects()
1005 {
1006         add_item(new BC_MenuItem(to_text(HISTOGRAM_LINEAR)));
1007         add_item(new BC_MenuItem(to_text(HISTOGRAM_POLYNOMINAL)));
1008         add_item(new BC_MenuItem(to_text(HISTOGRAM_BEZIER)));
1009 }
1010
1011 char* HistogramSmoothMode::to_text(int mode)
1012 {
1013         switch(mode)
1014         {
1015                 case HISTOGRAM_LINEAR:
1016                         return _("Linear");
1017                 case HISTOGRAM_POLYNOMINAL:
1018                         return _("Polynominal");
1019                 case HISTOGRAM_BEZIER:
1020                         return _("Bezier");
1021         }
1022         return _("None");
1023 }
1024
1025 int HistogramSmoothMode::from_text(char *text)
1026 {
1027         if(!strcmp(text, to_text(HISTOGRAM_LINEAR)))
1028                 return HISTOGRAM_LINEAR;
1029         if(!strcmp(text, to_text(HISTOGRAM_POLYNOMINAL)))
1030                 return HISTOGRAM_POLYNOMINAL;
1031         if(!strcmp(text, to_text(HISTOGRAM_BEZIER)))
1032                 return HISTOGRAM_BEZIER;
1033         return HISTOGRAM_LINEAR;
1034 }
1035
1036 int HistogramSmoothMode::handle_event()
1037 {
1038         plugin->config.smoothMode = from_text(get_text());
1039         gui->update_canvas();
1040         plugin->send_configure_change();
1041         return 1;
1042 }
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056