fix histogram bez keyframe interp, update plugins/fonts/fonts.scale, edl copy clip...
[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         int y1;
262
263 // Calculate output curve
264         plugin->tabulate_curve(plugin->mode, 0);
265
266 // Draw output line
267         canvas->set_color(0xffff00);
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         int x0 = 0, y0 = 0;
285 // Draw output points
286         HistogramPoint *current = plugin->config.points[plugin->mode].first;
287         int number = 0;
288         while(current)
289         {
290                 canvas->set_color(0x00ff00);
291                 int x = (int)((current->x - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE);
292                 int y = (int)(canvas_h - current->y * canvas_h);
293                 if(number == plugin->current_point)
294                         canvas->draw_box(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
295                 else
296                         canvas->draw_rectangle(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
297
298                 if( number > 0 )
299                         canvas->draw_line(x0, y0, x, y);
300                 x0 = x;  y0 = y;
301 //Draw gradients
302                 if (plugin->config.smoothMode > HISTOGRAM_LINEAR) {
303                         int x1,x2,y1,y2;
304                         canvas->set_color(0x0000ff);
305                         x2 = (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE);
306                         x1 = (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * canvas_w / FLOAT_RANGE);
307                         y2 = (int)(canvas_h - (current->y + current->xoffset_right * current->gradient) * canvas_h);
308                         y1 = (int)(canvas_h - (current->y + current->xoffset_left * current->gradient) * canvas_h);
309 /*                      x2 = x + (title3_x - title2_x)/20;
310                         x1 = x - (title3_x - title2_x)/20;
311                         y1 = y + (int)(current->gradient * (float)(canvas_h)/20.0);
312                         y2 = y - (int)(current->gradient * (float)(canvas_h)/20.0);
313 //                      int y2 = (int)(canvas_h - canvas_h * (current->y + current->gradient /10));*/
314                         canvas->draw_line(x1,y1,x2,y2);
315
316                         canvas->draw_circle(x1 - BOX_SIZE / 4, y1 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2);
317                         canvas->draw_circle(x2 - BOX_SIZE / 4, y2 - BOX_SIZE / 4, BOX_SIZE/2, BOX_SIZE/2);
318                 }
319
320                 current = NEXT;
321                 number++;
322         }
323
324
325 // Draw 0 and 100% lines.
326         canvas->set_color(0xff0000);
327         canvas->draw_line(title2_x - canvas->get_x(),
328                 0,
329                 title2_x - canvas->get_x(),
330                 canvas_h);
331         canvas->draw_line(title3_x - canvas->get_x(),
332                 0,
333                 title3_x - canvas->get_x(),
334                 canvas_h);
335 }
336
337 void HistogramWindow::update_canvas()
338 {
339         int *accum = plugin->accum[plugin->mode];
340         int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1;
341         float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w;
342         int normalize = 0;
343         int max = 0;
344
345         for(int i = 0; i < HISTOGRAM_SLOTS; i++)
346         {
347                 if(accum && accum[i] > normalize) normalize = accum[i];
348         }
349
350
351         if(normalize)
352         {
353                 for(int i = 0; i < canvas_w; i++)
354                 {
355                         int accum_start = (int)(accum_per_canvas_f * i);
356                         int accum_end = accum_start + accum_per_canvas_i;
357                         max = 0;
358                         for(int j = accum_start; j < accum_end; j++)
359                         {
360                                 max = MAX(accum[j], max);
361                         }
362
363 //                      max = max * canvas_h / normalize;
364                         max = (int)(log(max) / log(normalize) * canvas_h);
365
366                         canvas->set_color(0xffffff);
367                         canvas->draw_line(i, 0, i, canvas_h - max);
368                         canvas->set_color(0x000000);
369                         canvas->draw_line(i, canvas_h - max, i, canvas_h);
370                 }
371         }
372         else
373         {
374                 canvas->set_color(0xffffff);
375                 canvas->draw_box(0, 0, canvas_w, canvas_h);
376         }
377
378
379         draw_canvas_overlay();
380         canvas->flash();
381 }
382
383
384
385
386
387
388
389
390 HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
391         HistogramWindow *gui,
392         int x,
393         int y,
394         int w,
395         int h)
396  : BC_SubWindow(x,
397         y,
398         w,
399         h,
400         0xffffff)
401 {
402         this->plugin = plugin;
403         this->gui = gui;
404 }
405
406 int HistogramCanvas::button_press_event()
407 {
408         int result = 0;
409         if(is_event_win() && cursor_inside())
410         {
411                 if(!plugin->dragging_point)
412                 {
413                         HistogramPoint *new_point = 0;
414                         gui->deactivate();
415 // Search for existing point under cursor
416                         HistogramPoint *current = plugin->config.points[plugin->mode].first;
417                         plugin->current_point = -1;
418                         int dragID = 0;
419                         while(current)
420                         {
421                                 int x = (int)((current->x - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
422                                 int y = (int)(gui->canvas_h - current->y * gui->canvas_h);
423
424 /* Check for click on main point */
425                                 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
426                                         get_cursor_y() >= y - BOX_SIZE / 2 &&
427                                         get_cursor_x() < x + BOX_SIZE / 2 &&
428                                         get_cursor_y() < y + BOX_SIZE / 2)
429                                 {
430                                         plugin->current_point =
431                                                 plugin->config.points[plugin->mode].number_of(current);
432                                         plugin->point_x_offset = get_cursor_x() - x;
433                                         plugin->point_y_offset = get_cursor_y() - y;
434                                         dragID = 1;
435                                         break;
436                                 }
437 //                              if (plugin->config.smoothMode == HISTOGRAM_LINEAR)
438 //                                break;
439
440                                 int xright =
441                                   (int)((current->x + current->xoffset_right - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
442                                 int yright =
443                                   (int)(gui->canvas_h - (current->y + current->xoffset_right * current->gradient) *
444                                   gui->canvas_h);
445
446 /* Check for click on right handle */
447                                 if(get_cursor_x() >= xright - BOX_SIZE / 2 &&
448                                    get_cursor_y() >= yright - BOX_SIZE / 2 &&
449                                    get_cursor_x() <  xright + BOX_SIZE / 2 &&
450                                    get_cursor_y() <  yright + BOX_SIZE / 2)
451                                 {
452                                         plugin->current_point =
453                                                 plugin->config.points[plugin->mode].number_of(current);
454                                         plugin->point_x_offset = get_cursor_x() - xright;
455                                         plugin->point_y_offset = get_cursor_y() - yright;
456                                         dragID = 2;
457                                         break;
458                                 }
459
460 /* Check for click on left handle */
461                                 int xleft =
462                                   (int)((current->x + current->xoffset_left - HIST_MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
463                                 int yleft =
464                                   (int)(gui->canvas_h - (current->y + current->xoffset_left * current->gradient) *
465                                   gui->canvas_h);
466                                 if(get_cursor_x() >= xleft - BOX_SIZE / 2 &&
467                                    get_cursor_y() >= yleft - BOX_SIZE / 2 &&
468                                    get_cursor_x() <  xleft + BOX_SIZE / 2 &&
469                                    get_cursor_y() <  yleft + BOX_SIZE / 2)
470                                 {
471                                         plugin->current_point =
472                                                 plugin->config.points[plugin->mode].number_of(current);
473                                         plugin->point_x_offset = get_cursor_x() - xleft;
474                                         plugin->point_y_offset = get_cursor_y() - yleft;
475                                         dragID = 3;
476                                         break;
477                                 }
478
479
480                                 current = NEXT;
481                         }
482
483                         if(plugin->current_point < 0)
484                         {
485 // Create new point under cursor
486                                 float current_x = (float)get_cursor_x() *
487                                         FLOAT_RANGE /
488                                         get_w() +
489                                         HIST_MIN_INPUT;
490                                 float current_y = 1.0 -
491                                         (float)get_cursor_y() /
492                                         get_h();
493                                 new_point =
494                                         plugin->config.points[plugin->mode].insert(current_x, current_y);
495                                 plugin->current_point =
496                                         plugin->config.points[plugin->mode].number_of(new_point);
497                                 plugin->point_x_offset = 0;
498                                 plugin->point_y_offset = 0;
499
500 // Default gradient
501 // Get 2 points surrounding current position
502                                 float x1 = 0, x2 = 1, y1 = 0, y2 = 1;
503
504                                 HistogramPoint *current = plugin->config.points[plugin->mode].first;
505                                 int done = 0;
506                                 while(current && !done)
507                                 {
508                                         if(current->x > current_x)
509                                         {
510                                                 x2 = current->x;
511                                                 y2 = current->y;
512                                                 done = 1;
513                                         }
514                                         else
515                                                 current = NEXT;
516                                 }
517
518                                 current = plugin->config.points[plugin->mode].last;
519                                 done = 0;
520                                 while(current && !done)
521                                 {
522                                         if(current->x <= current_x)
523                                         {
524                                                 x1 = current->x;
525                                                 y1 = current->y;
526                                                 done = 1;
527                                         }
528                                         else
529                                                 current = PREVIOUS;
530                                 }
531                                 new_point->gradient = (y2 - y1) / (x2 - x1);
532                                 dragID = 1;
533
534                         }
535
536
537                         plugin->dragging_point = dragID;
538                         result = 1;
539
540                         plugin->config.boundaries();
541                         gui->update_input();
542                         gui->update_canvas();
543                         if(new_point)
544                         {
545                                 plugin->send_configure_change();
546                         }
547                 }
548         }
549         return result;
550 }
551
552 int HistogramCanvas::cursor_motion_event()
553 {
554         if(plugin->dragging_point)
555         {
556                 HistogramPoint * current_point = plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
557
558                 float current_x =
559                         (float)(get_cursor_x() - plugin->point_x_offset) *
560                         FLOAT_RANGE /
561                         get_w() +
562                         HIST_MIN_INPUT;
563                 float current_y = 1.0 -
564                         (float)(get_cursor_y() - plugin->point_y_offset) /
565                         get_h();
566
567                 switch(plugin->dragging_point)
568                 {
569                   case 1: /* Main point dragged */
570                         current_point->x = current_x;
571                         current_point->y = current_y;
572                         break;
573                   case 2: /* Right control point dragged */
574                         if (current_x - current_point->x > 0)
575                         {
576                           current_point->xoffset_right = current_x - current_point->x;
577                           current_point->gradient = (current_y - current_point->y) / (current_x - current_point->x);
578                         }
579                         break;
580                   case 3: /* Left control point dragged */
581                         if (current_x - current_point->x < 0)
582                         {
583                           current_point->xoffset_left = current_x - current_point->x;
584                           current_point->gradient = (current_point->y - current_y) / (current_point->x - current_x);
585                         }
586                         break;
587                 }
588
589                 plugin->config.boundaries();
590                 gui->update_input();
591                 gui->update_canvas();
592                 plugin->send_configure_change();
593                 return 1;
594         }
595         return 0;
596 }
597
598 int HistogramCanvas::button_release_event()
599 {
600         if(plugin->dragging_point)
601         {
602 // Test for out of order points to delete.
603                 HistogramPoint *current =
604                         plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
605                 HistogramPoint *prev = PREVIOUS;
606                 HistogramPoint *next = NEXT;
607
608                 if((prev && prev->x >= current->x) ||
609                         (next && next->x <= current->x))
610                 {
611                         delete current;
612                         plugin->current_point = -1;
613                         plugin->config.boundaries();
614                         gui->update_input();
615                         gui->update_canvas();
616                         plugin->send_configure_change();
617                 }
618
619                 plugin->dragging_point = 0;
620         }
621         return 0;
622 }
623
624
625
626
627
628
629
630 HistogramReset::HistogramReset(HistogramMain *plugin,
631         int x,
632         int y)
633  : BC_GenericButton(x, y, _("Reset"))
634 {
635         this->plugin = plugin;
636 }
637 int HistogramReset::handle_event()
638 {
639         plugin->config.reset(0);
640         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
641         window->update(1);
642         window->update_canvas();
643         plugin->send_configure_change();
644         return 1;
645 }
646
647
648
649
650
651
652
653
654
655 HistogramSlider::HistogramSlider(HistogramMain *plugin,
656         HistogramWindow *gui,
657         int x,
658         int y,
659         int w,
660         int h,
661         int is_input)
662  : BC_SubWindow(x, y, w, h)
663 {
664         this->plugin = plugin;
665         this->gui = gui;
666         this->is_input = is_input;
667         operation = NONE;
668 }
669
670 int HistogramSlider::input_to_pixel(float input)
671 {
672         return (int)((input - HIST_MIN_INPUT) / FLOAT_RANGE * get_w());
673 }
674
675 int HistogramSlider::button_press_event()
676 {
677         if(is_event_win() && cursor_inside())
678         {
679 //              int w = get_w();
680                 int h = get_h();
681                 int half_h = get_h() / 2;
682
683                 gui->deactivate();
684
685                 if(operation == NONE)
686                 {
687                         int x1 = input_to_pixel(plugin->config.output_min[plugin->mode]) -
688                                 gui->mid_picon->get_w() / 2;
689                         int x2 = x1 + gui->mid_picon->get_w();
690                         if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
691                                 get_cursor_y() >= half_h && get_cursor_y() < h)
692                         {
693                                 operation = DRAG_MIN_OUTPUT;
694                         }
695                 }
696
697                 if(operation == NONE)
698                 {
699                         int x1 = input_to_pixel(plugin->config.output_max[plugin->mode]) -
700                                 gui->mid_picon->get_w() / 2;
701                         int x2 = x1 + gui->mid_picon->get_w();
702                         if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
703                                 get_cursor_y() >= half_h && get_cursor_y() < h)
704                         {
705                                 operation = DRAG_MAX_OUTPUT;
706                         }
707                 }
708                 return 1;
709         }
710         return 0;
711 }
712
713 int HistogramSlider::button_release_event()
714 {
715         if(operation != NONE)
716         {
717                 operation = NONE;
718                 return 1;
719         }
720         return 0;
721 }
722
723 int HistogramSlider::cursor_motion_event()
724 {
725         if(operation != NONE)
726         {
727                 float value = (float)get_cursor_x() / get_w() * FLOAT_RANGE + HIST_MIN_INPUT;
728                 CLAMP(value, HIST_MIN_INPUT, HIST_MAX_INPUT);
729
730                 switch(operation)
731                 {
732                         case DRAG_MIN_OUTPUT:
733                                 value = MIN(plugin->config.output_max[plugin->mode], value);
734                                 plugin->config.output_min[plugin->mode] = value;
735                                 break;
736                         case DRAG_MAX_OUTPUT:
737                                 value = MAX(plugin->config.output_min[plugin->mode], value);
738                                 plugin->config.output_max[plugin->mode] = value;
739                                 break;
740                 }
741
742                 plugin->config.boundaries();
743                 gui->update_output();
744
745                 plugin->send_configure_change();
746                 return 1;
747         }
748         return 0;
749 }
750
751 void HistogramSlider::update()
752 {
753         int w = get_w();
754         int h = get_h();
755         int half_h = get_h() / 2;
756 //      int quarter_h = get_h() / 4;
757         int mode = plugin->mode;
758         int r = 0xff;
759         int g = 0xff;
760         int b = 0xff;
761
762         clear_box(0, 0, w, h);
763
764         switch(mode)
765         {
766                 case HISTOGRAM_RED:
767                         g = b = 0x00;
768                         break;
769                 case HISTOGRAM_GREEN:
770                         r = b = 0x00;
771                         break;
772                 case HISTOGRAM_BLUE:
773                         r = g = 0x00;
774                         break;
775         }
776
777         for(int i = 0; i < w; i++)
778         {
779                 int color = (int)(i * 0xff / w);
780                 set_color(((r * color / 0xff) << 16) |
781                         ((g * color / 0xff) << 8) |
782                         (b * color / 0xff));
783
784                 draw_line(i, 0, i, half_h);
785         }
786
787         float min;
788         float max;
789         min = plugin->config.output_min[plugin->mode];
790         max = plugin->config.output_max[plugin->mode];
791
792         draw_pixmap(gui->min_picon,
793                 input_to_pixel(min) - gui->min_picon->get_w() / 2,
794                 half_h + 1);
795         draw_pixmap(gui->max_picon,
796                 input_to_pixel(max) - gui->max_picon->get_w() / 2,
797                 half_h + 1);
798
799         flash();
800         flush();
801 }
802
803
804
805
806
807
808
809
810
811 HistogramAuto::HistogramAuto(HistogramMain *plugin,
812         int x,
813         int y)
814  : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
815 {
816         this->plugin = plugin;
817 }
818
819 int HistogramAuto::handle_event()
820 {
821         plugin->config.automatic = get_value();
822         plugin->send_configure_change();
823         return 1;
824 }
825
826
827
828
829 HistogramSplit::HistogramSplit(HistogramMain *plugin,
830         int x,
831         int y)
832  : BC_CheckBox(x, y, plugin->config.split, _("Split picture"))
833 {
834         this->plugin = plugin;
835 }
836
837 int HistogramSplit::handle_event()
838 {
839         plugin->config.split = get_value();
840         plugin->send_configure_change();
841         return 1;
842 }
843
844
845
846
847 HistogramMode::HistogramMode(HistogramMain *plugin,
848         int x,
849         int y,
850         int value,
851         char *text)
852  : BC_Radial(x, y, plugin->mode == value, text)
853 {
854         this->plugin = plugin;
855         this->value = value;
856 }
857 int HistogramMode::handle_event()
858 {
859         plugin->mode = value;
860         plugin->current_point= -1;
861         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
862         window->update_canvas();
863         window->update_mode();
864         window->update_input();
865         window->update_canvas();
866         window->update_output();
867         window->output->update();
868 //      plugin->send_configure_change();
869         return 1;
870 }
871
872
873
874
875
876
877
878
879
880 HistogramOutputText::HistogramOutputText(HistogramMain *plugin,
881         HistogramWindow *gui,
882         int x,
883         int y,
884         float *output)
885  : BC_TumbleTextBox(gui,
886                 output ? (float)*output : 0.0,
887                 (float)HIST_MIN_INPUT,
888                 (float)HIST_MAX_INPUT,
889                 x,
890                 y,
891                 60)
892 {
893         this->plugin = plugin;
894         this->output = output;
895         set_precision(DIGITS);
896         set_increment(PRECISION);
897 }
898
899
900 int HistogramOutputText::handle_event()
901 {
902         if(output)
903         {
904                 *output = atof(get_text());
905         }
906
907         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
908         window->output->update();
909         plugin->send_configure_change();
910         return 1;
911 }
912
913
914
915
916
917
918
919
920 HistogramInputText::HistogramInputText(HistogramMain *plugin,
921         HistogramWindow *gui,
922         int x,
923         int y,
924         int do_x)
925  : BC_TumbleTextBox(gui,
926                 0.0,
927                 (float)HIST_MIN_INPUT,
928                 (float)HIST_MAX_INPUT,
929                 x,
930                 y,
931                 60)
932 {
933         this->do_x = do_x;
934         this->plugin = plugin;
935         this->gui = gui;
936         set_precision(DIGITS);
937         set_increment(PRECISION);
938 }
939
940
941 int HistogramInputText::handle_event()
942 {
943         if(plugin->current_point >= 0 &&
944                 plugin->current_point < plugin->config.points[plugin->mode].total())
945         {
946                 HistogramPoint *point =
947                         plugin->config.points[plugin->mode].get_item_number(
948                                 plugin->current_point);
949
950                 if(point)
951                 {
952                         if(do_x)
953                                 point->x = atof(get_text());
954                         else
955                                 point->y = atof(get_text());
956
957                         plugin->config.boundaries();
958                         gui->update_canvas();
959
960                         HistogramWindow *window = (HistogramWindow *)plugin->thread->window;
961                         window->output->update();
962                         plugin->send_configure_change();
963                 }
964         }
965         return 1;
966 }
967
968 void HistogramInputText::update()
969 {
970         if(plugin->current_point >= 0 &&
971                 plugin->current_point < plugin->config.points[plugin->mode].total())
972         {
973                 HistogramPoint *point =
974
975                         plugin->config.points[plugin->mode].get_item_number(
976                                 plugin->current_point);
977
978                 if(point)
979                 {
980                         if(do_x)
981                                 BC_TumbleTextBox::update(point->x);
982                         else
983                                 BC_TumbleTextBox::update(point->y);
984                 }
985                 else
986                 {
987                         BC_TumbleTextBox::update((float)0.0);
988                 }
989         }
990         else
991         {
992                 BC_TumbleTextBox::update((float)0.0);
993         }
994
995 }
996
997
998 HistogramSmoothMode::HistogramSmoothMode(HistogramMain*plugin,
999         HistogramWindow *gui,
1000         int x,
1001         int y)
1002  : BC_PopupMenu(x, y, 120, to_text(plugin->config.smoothMode), 1)
1003 {
1004         this->plugin = plugin;
1005         this->gui = gui;
1006 }
1007 void HistogramSmoothMode::create_objects()
1008 {
1009         add_item(new BC_MenuItem(to_text(HISTOGRAM_LINEAR)));
1010         add_item(new BC_MenuItem(to_text(HISTOGRAM_POLYNOMINAL)));
1011         add_item(new BC_MenuItem(to_text(HISTOGRAM_BEZIER)));
1012 }
1013
1014 char* HistogramSmoothMode::to_text(int mode)
1015 {
1016         switch(mode)
1017         {
1018                 case HISTOGRAM_LINEAR:
1019                         return _("Linear");
1020                 case HISTOGRAM_POLYNOMINAL:
1021                         return _("Polynominal");
1022                 case HISTOGRAM_BEZIER:
1023                         return _("Bezier");
1024         }
1025         return _("None");
1026 }
1027
1028 int HistogramSmoothMode::from_text(char *text)
1029 {
1030         if(!strcmp(text, to_text(HISTOGRAM_LINEAR)))
1031                 return HISTOGRAM_LINEAR;
1032         if(!strcmp(text, to_text(HISTOGRAM_POLYNOMINAL)))
1033                 return HISTOGRAM_POLYNOMINAL;
1034         if(!strcmp(text, to_text(HISTOGRAM_BEZIER)))
1035                 return HISTOGRAM_BEZIER;
1036         return HISTOGRAM_LINEAR;
1037 }
1038
1039 int HistogramSmoothMode::handle_event()
1040 {
1041         plugin->config.smoothMode = from_text(get_text());
1042         gui->update_canvas();
1043         plugin->send_configure_change();
1044         return 1;
1045 }
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059