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