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