504957e9a72c4d0a784d450a289412ac3c589c75
[goodguy/history.git] / cinelerra-5.1 / plugins / bluebanana / bluebananawindow.C
1 /*
2  * Cinelerra :: Blue Banana - color modification plugin for Cinelerra-CV
3  * Copyright (C) 2012 Monty <monty@xiph.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20
21 #include <unistd.h>
22 #include <math.h>
23 #include "bcdisplayinfo.h"
24 #include "bcsignals.h"
25 #include "cursors.h"
26 #include "bluebanana.h"
27 #include "bluebananaconfig.h"
28 #include "bluebananaslider.h"
29 #include "bluebananawindow.h"
30 #include "keys.h"
31 #include "language.h"
32 #include "plugin.h"
33 #include "brender.h"
34
35 #include "bluebananacolor.c"
36
37
38 class BluebananaHActive : public BC_CheckBox {
39 public:
40   BluebananaHActive(BluebananaMain *plugin, BluebananaWindow *gui);
41   virtual int handle_event();
42   void update();
43   BluebananaMain *plugin;
44   BluebananaWindow *gui;
45 };
46
47 class BluebananaSActive : public BC_CheckBox {
48 public:
49   BluebananaSActive(BluebananaMain *plugin, BluebananaWindow *gui);
50   virtual int handle_event();
51   void update();
52   BluebananaMain *plugin;
53   BluebananaWindow *gui;
54 };
55
56 class BluebananaVActive : public BC_CheckBox {
57 public:
58   BluebananaVActive(BluebananaMain *plugin, BluebananaWindow *gui);
59   virtual int handle_event();
60   void update();
61   BluebananaMain *plugin;
62   BluebananaWindow *gui;
63 };
64
65
66 // -------------------------------------------------------------------------------
67 // The below code is because the stock TextTumbler trips too many bugs
68 // in guicast to be useful. If this plugin is to be shipped standalone
69 // and work, we need an independent version that avoids the bugs here.
70
71 BB_Tumble::BB_Tumble(BluebananaMain *plugin,
72                      BluebananaWindow *gui,
73                      float min,
74                      float mid,
75                      float max,
76                      int precision,
77                      float increment,
78                      int text_w)
79   : BC_TextBox(-1,-1,text_w,1,mid,1,MEDIUMFONT,precision){
80
81   // We must pass in the precision for initialization to get the
82   // geometry right.  But then bctextbox.C immediately clobbers it, so
83   // set it again
84   set_precision(precision);
85
86   this->gui = gui;
87   this->plugin = plugin;
88   this->x = -1;
89   this->y = -1;
90   this->min = min;
91   this->mid = mid;
92   this->max = max;
93   this->text_w = text_w;
94   this->precision = precision;
95   this->increment = increment;
96   this->active = 0;
97   this->suppress_events = 0;
98 }
99
100 float BB_Tumble::get_value(){
101   const char *text = get_text();
102   if(!text || text[0]==0) return 0;
103   return atof(text);
104 }
105
106 int BB_Tumble::handle_event(){
107   if(!suppress_events) value_event();
108   return 1;
109 }
110
111 int BB_Tumble::activate(){
112   // we want to restore the previous value on ESC
113   prev = get_value();
114   // the textbox active member is private, make our own
115   active = 1;
116   return BC_TextBox::activate();
117 }
118
119 int BB_Tumble::deactivate(){
120   if(active){
121     // only fire an event if the value changed; this makes 0/360
122     // behavior in the hue selection readout stick with what the user
123     // actually sets (as opposed to sanity checking flipping the value
124     // if an event fires)
125     if(get_value()!=prev)
126       value_event();
127     active = 0;
128     suppress_events=0;
129   }
130   return BC_TextBox::deactivate();
131 }
132
133 int BB_Tumble::button_press_event(){
134   if(is_event_win()){
135     if(get_buttonpress() < 4) return BC_TextBox::button_press_event();
136     if(get_buttonpress() == 4){
137       float v = get_value()+increment;
138       if(v>max)v=max;
139       update(v);
140       value_event();
141     }else if(get_buttonpress() == 5){
142       float v = get_value()-increment;
143       if(v<min)v=min;
144       update(v);
145       value_event();
146     }
147     return 1;
148   }
149   return 0;
150 }
151
152 int BB_Tumble::keypress_event(){
153   if(active && get_keypress()==ESC)
154     update(prev);
155
156   // don't fire update events from every keypress when editing; that
157   // will trigger slider updates, which will then sanity-check/clamp
158   // values, and then update/clobber the readout text while we're
159   // editing it.
160   suppress_events=1;
161   int ret = BC_TextBox::keypress_event();
162   suppress_events=0;
163   return ret;
164 }
165
166 // --------------------------------------------------------------------------------
167 //  initialization:
168 //    1) create_objects() constructs sliders and readouts with
169 //       limits but no values
170 //    2) create_objects() then calls slider update()
171 //       update computes and sets slider vals from config
172 //       update computes and sets readout vals from config
173 //
174 //  slider drag event:
175 //    1) slider calls handle_event(). This updates config.
176 //    2) slider calls update()
177 //       update computes and [re]sets slider vals from config;
178 //          this is where the snap-to-value behavior comes from
179 //       update computes and sets readout vals from config
180 //
181 //  readout event:
182 //    1) readout calls handle_event(). This updates config.
183 //    2) readout calls slider update() directly
184 //       slider update computes and sets slider vals from config
185 //       slider update computes and [re]sets readout vals from config;
186 //           this does not result in a further handle_event() call, so
187 //           no infinite recursion.
188 //
189 //  importantly, readout and slider values are set from the config
190 //  (and vice-versa) in only one place each.
191
192 // ---------------------------- hue adjustment slider -------------------------------
193
194 class BluebananaHAReadout : public BB_Tumble {
195  public:
196   BluebananaHAReadout(BluebananaMain *plugin, BluebananaWindow *gui, int w)
197     : BB_Tumble(plugin,gui,rint(-180),0,rint(180), 0,1,w){}
198   int value_event();
199 };
200
201 class BluebananaHASlider : public BluebananaSliderSingle {
202 public:
203   BluebananaHASlider(BluebananaMain *plugin, BluebananaWindow *gui,
204                      int x, int y, int w, int h)
205     : BluebananaSliderSingle(plugin,gui,x,y,w,h,-180,180){
206   }
207   virtual int handle_event() {
208     plugin->config.Hadj_val = val;
209     return 1;
210   }
211   void reset(){
212     plugin->config.Hadj_val=0;
213     update();
214   }
215   void update(){
216     val=plugin->config.Hadj_val;
217     highlight = plugin->config.active && plugin->config.Hadj_active;
218     gui->Hadj_readout->update(plugin->config.Hadj_val);
219     gui->slider_labels[7]->set_color(highlight && plugin->config.Hadj_val ?
220                                      get_resources()->default_text_color : dimtextcolor);
221     gui->enter_config_change();
222     gui->commit_config_change();
223   }
224   void trough_color(float hdel, float vdel, float &r, float &g, float &b, float &a){
225     float Hshift = plugin->config.Hsel_active ? (plugin->config.Hsel_lo + plugin->config.Hsel_hi)/720.f-.5f : 0.f;
226     float deg = hdel+Hshift;
227     if(deg<0)deg+=1;
228     if(deg>1)deg-=1;
229     HSpV_to_RGB(deg*6.f,1.,.2,r,g,b);
230     a=1.;
231   }
232 };
233
234 int BluebananaHAReadout::value_event(){
235   float val = get_value();
236   if(val<-180)val=-180;
237   if(val>180)val=180;
238   plugin->config.Hadj_val = val;
239   gui->Hadj_slider->update();
240   return 1;
241 }
242
243 // ------------------------------ Filter selection slider --------------------------------
244 class BluebananaFSReadout0 : public BB_Tumble {
245  public:
246   BluebananaFSReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
247     : BB_Tumble(plugin,gui,-FSrange,0,FSrange, 0,1,w){}
248   int value_event();
249 };
250 class BluebananaFSReadout1 : public BB_Tumble {
251  public:
252   BluebananaFSReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
253     : BB_Tumble(plugin,gui,-FSrange,0,FSrange, 0,1,w){}
254   int value_event();
255 };
256 class BluebananaFSReadout2 : public BB_Tumble {
257  public:
258   BluebananaFSReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
259     : BB_Tumble(plugin,gui,-FSrange,0,FSrange, 0,1,w){}
260   int value_event();
261 };
262 class BluebananaFSReadout3 : public BB_Tumble {
263  public:
264   BluebananaFSReadout3(BluebananaMain *plugin, BluebananaWindow *gui, int w)
265     : BB_Tumble(plugin,gui,0.,0,FSovermax, 0,1,w){}
266   int value_event();
267 };
268
269 static void paint_dot(float *array,int w, int h, float cx, float cy, float r, int inv){
270   int x,y;
271   int x0 = floor(cx-r);
272   int x1 = ceil(cx+r)+1;
273   int y0 = floor(cy-r);
274   int y1 = ceil(cy+r)+1;
275
276   if(x0<0)x0=0;
277   if(x1<0)x1=0;
278   if(y0<0)y0=0;
279   if(y1<0)y1=0;
280
281   if(x0>w)x0=w;
282   if(x1>w)x1=w;
283   if(y0>h)y0=h;
284   if(y1>h)y1=h;
285
286   for(y=y0;y<y1;y++){
287     float *row = array+y*w;
288     for(x=x0;x<x1;x++){
289       float rr = hypotf(x-cx,y-cy);
290       /* not correct, but this is merely cosmetic anyway */
291       float v = (r-rr+.5);
292       if(v>0){
293         if(inv){
294           row[x] -= v;
295           if(row[x]>1.)row[x]=0.;
296         }else{
297           row[x] += v;
298           if(row[x]>1.)row[x]=1.;
299         }
300       }
301     }
302   }
303 }
304
305 class BluebananaFSSlider : public BluebananaSliderFill {
306 public:
307   BluebananaFSSlider(BluebananaMain *plugin, BluebananaWindow *gui,
308                      int x, int y, int w, int h)
309     : BluebananaSliderFill(plugin,gui,x,y,w,h,-FSrange,FSrange,FSovermax) {
310     trough_alpha=0;
311     recompute_trough_alpha = 1;
312     erode=-1;
313   }
314   ~BluebananaFSSlider(){
315     if(trough_alpha)delete[] trough_alpha;
316   }
317   virtual int handle_event() {
318     plugin->config.Fsel_lo = (int)rint(loval);
319     plugin->config.Fsel_mid = (int)rint(midval);
320     plugin->config.Fsel_hi = (int)rint(hival);
321     plugin->config.Fsel_over = (int)rint(overval);
322     recompute_trough_alpha = 1;
323     return 1;
324   }
325   void update(){
326     if(plugin->config.Fsel_lo>0)plugin->config.Fsel_lo=0;
327     if(plugin->config.Fsel_hi<0)plugin->config.Fsel_hi=0;
328
329     if(highlight!=plugin->config.Fsel_active ||
330        erode!=plugin->config.Fsel_erode ||
331        loval!=plugin->config.Fsel_lo ||
332        midval!=plugin->config.Fsel_mid ||
333        hival!=plugin->config.Fsel_hi ||
334        overval!=plugin->config.Fsel_over){
335       recompute_trough_alpha = 1;
336     }
337     erode = plugin->config.Fsel_erode;
338     loval = plugin->config.Fsel_lo;
339     midval = plugin->config.Fsel_mid;
340     hival = plugin->config.Fsel_hi;
341     overval = plugin->config.Fsel_over;
342     highlight = plugin->config.Fsel_active;
343     gui->Fsel_readout0->update(plugin->config.Fsel_lo);
344     gui->Fsel_readout1->update(plugin->config.Fsel_mid);
345     gui->Fsel_readout2->update(plugin->config.Fsel_hi);
346     gui->Fsel_readout3->update(plugin->config.Fsel_over);
347     gui->slider_labels[3]->set_color
348       (highlight &&
349        (plugin->config.Hsel_active || plugin->config.Ssel_active || plugin->config.Vsel_active) &&
350        (plugin->config.Fsel_lo  != 0 ||
351         plugin->config.Fsel_mid != 0 ||
352         plugin->config.Fsel_hi  != 0 ||
353         plugin->config.Fsel_over!= 0 ) ?
354        get_resources()->default_text_color : dimtextcolor);
355
356     gui->erode_label->set_color
357       (highlight && plugin->config.Fsel_lo && plugin->config.Fsel_hi &&
358        (plugin->config.Hsel_active || plugin->config.Ssel_active || plugin->config.Vsel_active)?
359        get_resources()->default_text_color : dimtextcolor);
360
361     gui->enter_config_change();
362     gui->commit_config_change();
363   }
364   void trough_color(float hdel, float vdel, float &r, float &g, float &b, float &a){
365     int x = rint(hdel*troughcols-.5);
366     int y = rint(vdel*troughlines-.5);
367     float deg = plugin->config.Hsel_active ?
368       vdel*(plugin->config.Hsel_hi-plugin->config.Hsel_lo)+plugin->config.Hsel_lo :
369       vdel*360.f;
370     float sat = plugin->config.Ssel_active ?
371       (plugin->config.Ssel_hi+plugin->config.Ssel_lo)/200.:
372       .5;
373     float val = plugin->config.Vsel_active ?
374       (plugin->config.Vsel_hi*3+plugin->config.Vsel_lo)/400:
375       .75;
376
377     if(deg>=360)deg-=360.f;
378     HSpV_to_RGB(deg/60.,sat,val,r,g,b);
379     a = trough_alpha[troughcols*y+x];
380   }
381   void render(){
382
383     if(!trough_alpha)
384       trough_alpha = new float[troughcols*troughlines];
385
386     if(recompute_trough_alpha){
387       int trough_border = FSrange;
388       int tw = troughcols*3+trough_border*2;
389       int th = troughlines*3+trough_border*2;
390
391       float work1[tw*th];
392       float work2[tw*th];
393
394       memset(work1,0,sizeof(work1));
395
396       float loval=1;
397       float hival=FSrange*2-1;
398       float y0 = (th-1)/2.;
399       float y1 = (th-1)/2.;
400
401       int spacing=rint(FSrange)*2;
402       int rowflag=0;
403       int x,y;
404
405       while((y0+spacing*.5)>0){
406         for(x=(rowflag?spacing/2.:0.);x-spacing*.5<tw;x+=spacing){
407           float r = (((float)x/tw)*(hival-loval)+loval)*.5;
408           if(y0==y1){
409             paint_dot(work1,tw,th,x,y0,r,0);
410           }else{
411             paint_dot(work1,tw,th,x,y0,r,0);
412             paint_dot(work1,tw,th,x,y1,r,0);
413           }
414         }
415         y0-=spacing/2.;
416         y1+=spacing/2.;
417         rowflag = (rowflag+1)&1;
418       }
419
420       float *final = work1;
421       if(plugin->config.Fsel_active &&
422          (plugin->config.Fsel_lo || plugin->config.Fsel_hi || plugin->config.Fsel_over))
423         final=plugin->fill_selection(work1,work2,tw,th,NULL);
424
425       /* subsample into trough */
426       float *in = final + (tw+1)*trough_border;
427       for(y=0;y<troughlines;y++){
428         float *out = trough_alpha + troughcols*y;
429         for(x=0;x<troughcols;x++)
430           out[x] = (in[x*3]+in[x*3+1]+in[x*3+2]+
431                     in[tw+x*3]+in[tw+x*3+1]+in[x*3+2]+
432                     in[tw*2+x*3]+in[tw*2+x*3+1]+in[tw*2+x*3+2])*.1111;
433         in += tw*3;
434       }
435
436     }
437     recompute_trough_alpha=0;
438     BluebananaSliderFill::update();
439   }
440
441   float *trough_alpha;
442   int trough_border;
443   int recompute_trough_alpha;
444   int erode;
445 };
446
447 int BluebananaFSReadout0::value_event(){
448   float val = rint(get_value());
449   if(val<-FSrange)val=-FSrange;
450   if(val>0)val=0;
451   if(val>plugin->config.Fsel_mid) val = plugin->config.Fsel_mid;
452   plugin->config.Fsel_lo = val;
453   gui->Fsel_slider->update();
454   return 1;
455 }
456
457 int BluebananaFSReadout1::value_event(){
458   float val = rint(get_value());
459   if(val<-FSrange)val=-FSrange;
460   if(val>FSrange)val=FSrange;
461   if(val<plugin->config.Fsel_lo) plugin->config.Fsel_lo=val;
462   if(val>plugin->config.Fsel_hi) plugin->config.Fsel_hi=val;
463   plugin->config.Fsel_mid = val;
464   gui->Fsel_slider->update();
465   return 1;
466 }
467
468 int BluebananaFSReadout2::value_event(){
469   float val = rint(get_value());
470   if(val<0)val=0;
471   if(val>FSrange)val=FSrange;
472   if(val<plugin->config.Fsel_mid) val = plugin->config.Fsel_mid;
473   plugin->config.Fsel_hi = val;
474   gui->Fsel_slider->update();
475   return 1;
476 }
477
478 int BluebananaFSReadout3::value_event(){
479   float val = rint(get_value());
480   if(val<0)val=0;
481   if(val>FSovermax)val=FSovermax;
482   plugin->config.Fsel_over = val;
483   gui->Fsel_slider->update();
484   return 1;
485 }
486
487 // ------------------------------ value selection slider --------------------------------
488 class BluebananaVSReadout0 : public BB_Tumble {
489  public:
490   BluebananaVSReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
491     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
492   int value_event();
493 };
494 class BluebananaVSReadout1 : public BB_Tumble {
495  public:
496   BluebananaVSReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
497     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
498   int value_event();
499 };
500 class BluebananaVSReadout2 : public BB_Tumble {
501  public:
502   BluebananaVSReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
503     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
504   int value_event();
505 };
506
507 class BluebananaVSSlider : public BluebananaSliderBracket {
508 public:
509   BluebananaVSSlider(BluebananaMain *plugin, BluebananaWindow *gui,
510                      int x, int y, int w, int h)
511     : BluebananaSliderBracket(plugin,gui,x,y,w,h,0,100) { }
512   virtual int handle_event() {
513     plugin->config.Vsel_lo = rint(loval);
514     plugin->config.Vsel_hi = rint(hival);
515     plugin->config.Vsel_over = rint(overval);
516     return 1;
517   }
518   void pick(){
519     int delta = plugin->config.Vsel_hi - plugin->config.Vsel_lo;
520     float r = plugin->get_red();
521     float g = plugin->get_green();
522     float b = plugin->get_blue();
523     float h,s,v;
524     RGB_to_HSpV(r,g,b,h,s,v);
525     h*=60.f;
526     v=rint(v*100.f);
527     if(v<0)v=0;
528     if(v>100)v=100;
529     if(delta>25)delta=25;
530     int lo = v - delta/2;
531     int hi = lo + delta;
532     /* shrink the brackets if necessary */
533     if(lo<0){
534       lo=0;
535       if(hi-lo<10)hi=10;
536     }
537     if(hi>100){
538       hi=100;
539       if(hi-lo<10)lo=90;
540     }
541     plugin->config.Vsel_lo=lo;
542     plugin->config.Vsel_hi=hi;
543     plugin->config.Vsel_active=1;
544     gui->Vsel_active->update(); // this will also call the slider update
545   }
546   void update(){
547     loval = plugin->config.Vsel_lo;
548     hival = plugin->config.Vsel_hi;
549     midval = (loval+hival)/2.f;
550     overval = plugin->config.Vsel_over;
551     highlight = plugin->config.Vsel_active;
552
553     gui->Vsel_readout0->update(plugin->config.Vsel_lo);
554     gui->Vsel_readout1->update(plugin->config.Vsel_hi);
555     gui->Vsel_readout2->update(plugin->config.Vsel_over);
556     gui->slider_labels[2]->set_color
557       (highlight && (plugin->config.Vsel_lo != 0 || plugin->config.Vsel_hi != 100) ?
558        get_resources()->default_text_color : dimtextcolor);
559
560     gui->enter_config_change();
561     if(gui->Fsel_slider)gui->Fsel_slider->update();
562     gui->commit_config_change();
563   }
564   void trough_color(float hdel, float vdel, float &r, float &g, float &b, float &a){
565     float deg = plugin->config.Hsel_active ?
566       vdel*(plugin->config.Hsel_hi-plugin->config.Hsel_lo)+plugin->config.Hsel_lo :
567       vdel*360.f;
568     float sat = plugin->config.Ssel_active ?
569       (plugin->config.Ssel_hi*3+plugin->config.Ssel_lo)/400.:
570       .5;
571
572     if(deg>=360)deg-=360.f;
573     HSpV_to_RGB(deg/60.,sat,hdel,r,g,b);
574     a= plugin->val_select_alpha(hdel);
575   }
576 };
577
578 int BluebananaVSReadout0::value_event(){
579   float val = get_value();
580   if(val<0)val=0;
581   if(val>100)val=100;
582   if(val>plugin->config.Vsel_hi) val = plugin->config.Vsel_hi;
583   plugin->config.Vsel_lo = val;
584   gui->Vsel_slider->update();
585   return 1;
586 }
587
588 int BluebananaVSReadout1::value_event(){
589   float val = get_value();
590   if(val<0)val=0;
591   if(val>100)val=100;
592   if(val<plugin->config.Vsel_lo) val = plugin->config.Vsel_lo;
593   plugin->config.Vsel_hi = val;
594   gui->Vsel_slider->update();
595   return 1;
596 }
597
598 int BluebananaVSReadout2::value_event(){
599   float val = get_value();
600   if(val<0)val=0;
601   if(val>100)val=100;
602   plugin->config.Vsel_over = val;
603   gui->Vsel_slider->update();
604   return 1;
605 }
606
607 // ----------------------------- saturation selection slider -----------------------------
608 class BluebananaSSReadout0 : public BB_Tumble {
609  public:
610   BluebananaSSReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
611     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
612   int value_event();
613 };
614 class BluebananaSSReadout1 : public BB_Tumble {
615  public:
616   BluebananaSSReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
617     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
618   int value_event();
619 };
620 class BluebananaSSReadout2 : public BB_Tumble {
621  public:
622   BluebananaSSReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
623     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
624   int value_event();
625 };
626
627 class BluebananaSSSlider : public BluebananaSliderBracket {
628 public:
629   BluebananaSSSlider(BluebananaMain *plugin, BluebananaWindow *gui,
630                      int x, int y, int w, int h)
631     : BluebananaSliderBracket(plugin,gui,x,y,w,h,0,100) { }
632   int handle_event() {
633     plugin->config.Ssel_lo = rint(loval);
634     plugin->config.Ssel_hi = rint(hival);
635     plugin->config.Ssel_over = rint(overval);
636     return 1;
637   }
638   void pick(){
639     int delta = plugin->config.Ssel_hi - plugin->config.Ssel_lo;
640     float r = plugin->get_red();
641     float g = plugin->get_green();
642     float b = plugin->get_blue();
643     float h,s,v;
644     RGB_to_HSpV(r,g,b,h,s,v);
645     h*=60.f;
646     s=rint(s*100.f);
647     if(s<0)s=0;
648     if(s>100)s=100;
649     if(delta>25)delta=25;
650     int lo = s - delta/2;
651     int hi = lo + delta;
652     /* shrink the brackets if necessary */
653     if(lo<0){
654       lo=0;
655       if(hi-lo<10)hi=10;
656     }
657     if(hi>100){
658       hi=100;
659       if(hi-lo<10)lo=90;
660     }
661     plugin->config.Ssel_lo=lo;
662     plugin->config.Ssel_hi=hi;
663     plugin->config.Ssel_active=1;
664     gui->Ssel_active->update(); // this will also call the slider update
665   }
666   void update(){
667     loval = plugin->config.Ssel_lo;
668     hival = plugin->config.Ssel_hi;
669     midval = (loval+hival)/2.f;
670     overval = plugin->config.Ssel_over;
671     highlight = plugin->config.Ssel_active;
672
673     gui->Ssel_readout0->update(plugin->config.Ssel_lo);
674     gui->Ssel_readout1->update(plugin->config.Ssel_hi);
675     gui->Ssel_readout2->update(plugin->config.Ssel_over);
676     gui->slider_labels[1]->set_color(highlight  &&
677                                      (plugin->config.Ssel_lo != 0 || plugin->config.Ssel_hi != 100) ?
678                                      get_resources()->default_text_color : dimtextcolor);
679
680     gui->enter_config_change();
681     if(gui->Fsel_slider)gui->Fsel_slider->update();
682     gui->commit_config_change();
683   }
684   void trough_color(float hdel, float vdel, float &r, float &g, float &b, float &a){
685     float deg = plugin->config.Hsel_active ?
686       vdel*(plugin->config.Hsel_hi-plugin->config.Hsel_lo)+plugin->config.Hsel_lo :
687       vdel*360.;
688     if(deg>=360)deg-=360.f;
689     HSpV_to_RGB(deg/60.f,hdel,.7+.3*hdel,r,g,b);
690     a = plugin->sat_select_alpha(hdel);
691   }
692 };
693
694 int BluebananaSSReadout0::value_event(){
695   float val = get_value();
696   if(val<0)val=0;
697   if(val>100)val=100;
698   if(val>plugin->config.Ssel_hi) val = plugin->config.Ssel_hi;
699   plugin->config.Ssel_lo = val;
700   gui->Ssel_slider->update();
701   return 1;
702 }
703
704 int BluebananaSSReadout1::value_event(){
705   float val = get_value();
706   if(val<0)val=0;
707   if(val>100)val=100;
708   if(val<plugin->config.Ssel_lo) val = plugin->config.Ssel_lo;
709   plugin->config.Ssel_hi = val;
710   gui->Ssel_slider->update();
711   return 1;
712 }
713
714 int BluebananaSSReadout2::value_event(){
715   float val = get_value();
716   if(val<0)val=0;
717   if(val>100)val=100;
718   plugin->config.Ssel_over = val;
719   gui->Ssel_slider->update();
720   return 1;
721 }
722
723 // ----------------------------- hue selection slider ---------------------------------
724 class BluebananaHSReadout0 : public BB_Tumble {
725  public:
726   BluebananaHSReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
727     : BB_Tumble(plugin,gui,0.,0,360., 0,1,w){}
728   int value_event();
729 };
730 class BluebananaHSReadout1 : public BB_Tumble {
731  public:
732   BluebananaHSReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
733     : BB_Tumble(plugin,gui,0.,0,360., 0,1,w){}
734   int value_event();
735 };
736 class BluebananaHSReadout2 : public BB_Tumble {
737  public:
738   BluebananaHSReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
739     : BB_Tumble(plugin,gui,0.,360.,360., 0,1,w){}
740   int value_event();
741 };
742
743 class BluebananaHSSlider : public BluebananaSliderCircular {
744 public:
745   BluebananaHSSlider(BluebananaMain *plugin, BluebananaWindow *gui,
746                      int x, int y, int w, int h)
747     : BluebananaSliderCircular(plugin,gui,x,y,w,h,0,360) {
748   }
749   int handle_event() {
750     plugin->config.Hsel_lo = rint(loval);
751     plugin->config.Hsel_hi = plugin->config.Hsel_lo +
752       (midval<loval ? rint(midval*2-loval*2+720) : rint(midval*2-loval*2));
753     plugin->config.Hsel_over = rint(overval);
754     return 1;
755   }
756   void pick(){
757     int delta = plugin->config.Hsel_hi - plugin->config.Hsel_lo;
758     float r = plugin->get_red();
759     float g = plugin->get_green();
760     float b = plugin->get_blue();
761     float h,s,v;
762     RGB_to_HSpV(r,g,b,h,s,v);
763     h=rint(h*60.f);
764     if(h<0)h=0;
765     if(h>360)h=360;
766     if(delta>30)delta=30;
767     int lo = h - delta/2;
768     int hi = lo + delta;
769     if(lo<0){
770       lo+=360;
771       hi+=360;
772     }
773     plugin->config.Hsel_lo=lo;
774     plugin->config.Hsel_hi=hi;
775     plugin->config.Hsel_active=1;
776     gui->Hsel_active->update(); // this will also call the slider update
777   }
778   void update(){
779     // Significantly more complex than the other sliders due to the
780     // circular scale.
781     //float delta = (plugin->config.Hsel_hi - plugin->config.Hsel_lo);
782     loval = plugin->config.Hsel_lo;
783     overval = plugin->config.Hsel_over;
784     float newhival = plugin->config.Hsel_hi;
785     float newmidval = (loval+newhival)/2.;
786     if(loval<0)loval+=360.;
787     if(loval>360.)loval-=360.;
788     if(newmidval<0)newmidval+=360.;
789     if(newmidval>360.)newmidval-=360.;
790     if(newhival<0)newhival+=360.;
791     if(newhival>360.)newhival-=360.;
792     highlight = plugin->config.Hsel_active;
793
794     float checkhi = plugin->config.Hsel_hi;
795     if(checkhi>360)checkhi-=360;
796
797     // one last weirdness; 0 and 360 are technically the same value on
798     // the circular scale, but the user can set either.  This isn't a
799     // problem with lo as it doesn't wrap, but mid/hi is computed for
800     // the slider and could end up at 0 or 360, and then clobber the
801     // slider/readout.  To avoid annoying the user, don't override an
802     // existing readout/slider setting with its equivalent.
803     if(newhival==0 && hival==360.){
804       newhival=360.;
805       checkhi=360;
806     }else if(newhival==360 && hival==0.){
807       newhival=0.;
808       checkhi=0;
809     }else if(checkhi==0 && gui->Hsel_readout2->get_value()==360){
810       newhival=360.;
811       checkhi=360;
812     }else if(checkhi==360 && gui->Hsel_readout2->get_value()==0){
813       newhival=0.;
814       checkhi=0;
815     }
816
817     if(newmidval<1 && midval>359){
818       newmidval=360.;
819     }else if(newmidval>359.f && midval<1.){
820       newmidval=0.;
821     }
822     midval=newmidval;
823     hival=newhival;
824
825     gui->Hsel_readout0->update(plugin->config.Hsel_lo);
826     gui->Hsel_readout1->update(checkhi);
827     gui->Hsel_readout2->update(plugin->config.Hsel_over);
828     gui->slider_labels[0]->set_color(highlight &&
829                                      (plugin->config.Hsel_hi - plugin->config.Hsel_lo != 360) ?
830                                      get_resources()->default_text_color : dimtextcolor);
831
832     gui->enter_config_change();
833     if(gui->Fsel_slider)gui->Fsel_slider->update();
834     gui->commit_config_change();
835   }
836   void trough_color(float hdel, float vdel, float &r, float &g, float &b, float &a){
837     float deg = hdel*360.f;
838     if(deg>=360)deg-=360.f;
839
840     HSpV_to_RGB(deg/60.f,1.f,1.f,r,g,b);
841     a = plugin->hue_select_alpha(hdel*360.f);
842   }
843   friend class BluebananaHSReadout1;
844   friend class BluebananaHSReadout2;
845 };
846
847 int BluebananaHSReadout0::value_event(){
848   plugin->config.Hsel_lo = get_value();
849   if(plugin->config.Hsel_lo<0)plugin->config.Hsel_lo=0;
850   if(plugin->config.Hsel_lo>360)plugin->config.Hsel_lo=360;
851   if(plugin->config.Hsel_hi - plugin->config.Hsel_lo > 360)
852     plugin->config.Hsel_hi-=360;
853   if(plugin->config.Hsel_lo > plugin->config.Hsel_hi)
854     plugin->config.Hsel_hi+=360;
855   gui->Hsel_slider->update();
856   return 1;
857 }
858
859 int BluebananaHSReadout1::value_event(){
860   plugin->config.Hsel_hi = get_value();
861   if(plugin->config.Hsel_hi<0)plugin->config.Hsel_hi=0;
862   if(plugin->config.Hsel_hi>360)plugin->config.Hsel_hi=360;
863   if(plugin->config.Hsel_lo > plugin->config.Hsel_hi)
864     plugin->config.Hsel_hi+=360;
865   gui->Hsel_slider->hival=-1; /* force update to hival, not the hi readout */
866   gui->Hsel_slider->update();
867   return 1;
868 }
869
870 int BluebananaHSReadout2::value_event(){
871   float val = get_value();
872   if(val<0)val=0;
873   if(val>360)val=360;
874   plugin->config.Hsel_over=val;
875   gui->Hsel_slider->update();
876   return 1;
877 }
878
879 // ---------------------------- saturation adjustment slider ----------------------------
880 class BluebananaSAReadout0 : public BB_Tumble {
881  public:
882   BluebananaSAReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
883     : BB_Tumble(plugin,gui,-100,0,100., 0,1,w){}
884   int value_event();
885 };
886 class BluebananaSAReadout1 : public BB_Tumble {
887  public:
888   BluebananaSAReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
889     : BB_Tumble(plugin,gui,0.,0,200., 0,1,w){}
890   int value_event();
891 };
892 class BluebananaSAReadout2 : public BB_Tumble {
893  public:
894   BluebananaSAReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
895     : BB_Tumble(plugin,gui,MIN_GAMMA,0,MAX_GAMMA,2,.01,w){}
896   int value_event();
897 };
898
899 class BluebananaSASlider : public BluebananaSliderChannel {
900 public:
901   BluebananaSASlider(BluebananaMain *plugin, BluebananaWindow *gui,
902                      int x, int y, int w, int h)
903     : BluebananaSliderChannel(plugin,gui,x,y,w,h) { }
904   virtual int handle_event() {
905     plugin->config.Sadj_lo = loval;
906     plugin->config.Sadj_hi = hival;
907     plugin->config.Sadj_gamma = gamma;
908     return 1;
909   }
910   void reset(){
911     plugin->config.Sadj_lo=0.;
912     plugin->config.Sadj_hi=100.;
913     plugin->config.Sadj_gamma=1.;
914     update();
915   }
916   void update(){
917     loval = plugin->config.Sadj_lo;
918     hival = plugin->config.Sadj_hi;
919     gamma = plugin->config.Sadj_gamma;
920
921     highlight = plugin->config.active && plugin->config.Sadj_active;
922
923     gui->Sadj_readout0->update(plugin->config.Sadj_lo);
924     gui->Sadj_readout1->update(plugin->config.Sadj_hi);
925     gui->Sadj_readout2->update(plugin->config.Sadj_gamma);
926     gui->slider_labels[8]->set_color(highlight &&
927                                      (plugin->config.Sadj_lo != 0 ||
928                                       plugin->config.Sadj_hi != 100 ||
929                                       plugin->config.Sadj_gamma != 1.) ?
930                                      get_resources()->default_text_color : dimtextcolor);
931
932     gui->enter_config_change();
933     gui->commit_config_change();
934   }
935   void trough_color(float hdel, float &r, float &g, float &b){
936     r=g=b=0;
937   }
938 };
939
940 #define BBCLAMP(x,y,z) ((x)<(y) ? (y) : (x)>(z) ? (z) : (x))
941
942 int BluebananaSAReadout0::value_event(){
943   plugin->config.Sadj_lo = BBCLAMP(get_value(),-100,plugin->config.Sadj_hi);
944   plugin->config.Sadj_lo = BBCLAMP(get_value(),-100,100);
945   gui->Sadj_slider->update();
946   return 1;
947 }
948 int BluebananaSAReadout1::value_event(){
949   plugin->config.Sadj_hi = BBCLAMP(get_value(),plugin->config.Sadj_lo,200);
950   plugin->config.Sadj_hi = BBCLAMP(get_value(),0,200);
951   gui->Sadj_slider->update();
952   return 1;
953 }
954 int BluebananaSAReadout2::value_event(){
955   plugin->config.Sadj_gamma = BBCLAMP(get_value(),MIN_GAMMA,MAX_GAMMA);
956   gui->Sadj_slider->update();
957   return 1;
958 }
959
960 // ------------------------------- value adjustment slider -------------------------------
961 class BluebananaVAReadout0 : public BB_Tumble {
962  public:
963   BluebananaVAReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
964     : BB_Tumble(plugin,gui,-100.,0,100., 0,1,w){}
965   int value_event();
966 };
967 class BluebananaVAReadout1 : public BB_Tumble {
968  public:
969   BluebananaVAReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
970     : BB_Tumble(plugin,gui,0.,0,200., 0,1,w){}
971   int value_event();
972 };
973 class BluebananaVAReadout2 : public BB_Tumble {
974  public:
975   BluebananaVAReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
976     : BB_Tumble(plugin,gui,MIN_GAMMA,0,MAX_GAMMA,2,.01,w){}
977   int value_event();
978 };
979
980 class BluebananaVASlider : public BluebananaSliderChannel {
981 public:
982   BluebananaVASlider(BluebananaMain *plugin, BluebananaWindow *gui,
983                      int x, int y, int w, int h)
984     : BluebananaSliderChannel(plugin,gui,x,y,w,h) { }
985   virtual int handle_event() {
986     plugin->config.Vadj_lo = loval;
987     plugin->config.Vadj_hi = hival;
988     plugin->config.Vadj_gamma = gamma;
989     return 1;
990   }
991   void reset(){
992     plugin->config.Vadj_lo=0;
993     plugin->config.Vadj_hi=100;
994     plugin->config.Vadj_gamma=1;
995     update();
996   }
997   void update(){
998     loval = plugin->config.Vadj_lo;
999     hival = plugin->config.Vadj_hi;
1000     gamma = plugin->config.Vadj_gamma;
1001
1002     highlight = plugin->config.active && plugin->config.Vadj_active;
1003
1004     gui->Vadj_readout0->update(plugin->config.Vadj_lo);
1005     gui->Vadj_readout1->update(plugin->config.Vadj_hi);
1006     gui->Vadj_readout2->update(plugin->config.Vadj_gamma);
1007     gui->slider_labels[9]->set_color(highlight  &&
1008                                      (plugin->config.Vadj_lo != 0.f ||
1009                                       plugin->config.Vadj_hi != 100.f ||
1010                                       plugin->config.Vadj_gamma != 1.f) ?
1011                                      get_resources()->default_text_color : dimtextcolor);
1012
1013     gui->enter_config_change();
1014     gui->commit_config_change();
1015   }
1016   void trough_color(float hdel, float &r, float &g, float &b){
1017     r=g=b=0;
1018   }
1019 };
1020
1021 int BluebananaVAReadout0::value_event(){
1022   plugin->config.Vadj_lo = BBCLAMP(get_value(),-100,plugin->config.Vadj_hi);
1023   plugin->config.Vadj_lo = BBCLAMP(get_value(),-100,100);
1024   gui->Vadj_slider->update();
1025   return 1;
1026 }
1027 int BluebananaVAReadout1::value_event(){
1028   plugin->config.Vadj_hi = BBCLAMP(get_value(),plugin->config.Vadj_lo,200);
1029   plugin->config.Vadj_hi = BBCLAMP(get_value(),0,200);
1030   gui->Vadj_slider->update();
1031   return 1;
1032 }
1033 int BluebananaVAReadout2::value_event(){
1034   plugin->config.Vadj_gamma = BBCLAMP(get_value(),MIN_GAMMA,MAX_GAMMA);
1035   gui->Vadj_slider->update();
1036   return 1;
1037 }
1038
1039 // -------------------------------- red adjustment slider --------------------------------
1040 class BluebananaRAReadout0 : public BB_Tumble {
1041  public:
1042   BluebananaRAReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1043     : BB_Tumble(plugin,gui,-100.,0,100., 0,1,w){}
1044   int value_event();
1045 };
1046 class BluebananaRAReadout1 : public BB_Tumble {
1047  public:
1048   BluebananaRAReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1049     : BB_Tumble(plugin,gui,0.,0,200., 0,1,w){}
1050   int value_event();
1051 };
1052 class BluebananaRAReadout2 : public BB_Tumble {
1053  public:
1054   BluebananaRAReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1055     : BB_Tumble(plugin,gui,MIN_GAMMA,0,MAX_GAMMA,2,.01,w){}
1056   int value_event();
1057 };
1058
1059 class BluebananaRASlider : public BluebananaSliderChannel {
1060 public:
1061   BluebananaRASlider(BluebananaMain *plugin, BluebananaWindow *gui,
1062                      int x, int y, int w, int h)
1063     : BluebananaSliderChannel(plugin,gui,x,y,w,h) { }
1064   virtual int handle_event() {
1065     plugin->config.Radj_lo = loval;
1066     plugin->config.Radj_hi = hival;
1067     plugin->config.Radj_gamma = gamma;
1068     return 1;
1069   }
1070   void reset(){
1071     plugin->config.Radj_lo=0;
1072     plugin->config.Radj_hi=100;
1073     plugin->config.Radj_gamma=1;
1074     update();
1075   }
1076   void update(){
1077     loval = plugin->config.Radj_lo;
1078     hival = plugin->config.Radj_hi;
1079     gamma = plugin->config.Radj_gamma;
1080
1081     highlight = plugin->config.active && plugin->config.Radj_active;
1082
1083     gui->Radj_readout0->update(plugin->config.Radj_lo);
1084     gui->Radj_readout1->update(plugin->config.Radj_hi);
1085     gui->Radj_readout2->update(plugin->config.Radj_gamma);
1086     gui->slider_labels[4]->set_color(highlight  &&
1087                                      (plugin->config.Radj_lo != 0 ||
1088                                       plugin->config.Radj_hi != 100 ||
1089                                       plugin->config.Radj_gamma != 1) ?
1090                                      get_resources()->default_text_color : dimtextcolor);
1091
1092     gui->enter_config_change();
1093     gui->commit_config_change();
1094   }
1095   void trough_color(float hdel, float &r, float &g, float &b){
1096     if(hdel<0){
1097       r=g=b=0.;
1098     }else if(hdel<=1.f){
1099       r=hdel;
1100       g=b=0.;
1101     }else{
1102       r=1.;
1103       g=b=0.;
1104     }
1105   }
1106 };
1107
1108 int BluebananaRAReadout0::value_event(){
1109   plugin->config.Radj_lo = BBCLAMP(get_value(),-100,plugin->config.Radj_hi);
1110   plugin->config.Radj_lo = BBCLAMP(get_value(),-100,100);
1111   gui->Radj_slider->update();
1112   return 1;
1113 }
1114 int BluebananaRAReadout1::value_event(){
1115   plugin->config.Radj_hi = BBCLAMP(get_value(),plugin->config.Radj_lo,200);
1116   plugin->config.Radj_hi = BBCLAMP(get_value(),0,200);
1117   gui->Radj_slider->update();
1118   return 1;
1119 }
1120 int BluebananaRAReadout2::value_event(){
1121   plugin->config.Radj_gamma = BBCLAMP(get_value(),MIN_GAMMA,MAX_GAMMA);
1122   gui->Radj_slider->update();
1123   return 1;
1124 }
1125
1126 // ---------------------------- green adjustment slider ----------------------------
1127 class BluebananaGAReadout0 : public BB_Tumble {
1128  public:
1129   BluebananaGAReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1130     : BB_Tumble(plugin,gui,-100.,0,100., 0,1,w){}
1131   int value_event();
1132 };
1133 class BluebananaGAReadout1 : public BB_Tumble {
1134  public:
1135   BluebananaGAReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1136     : BB_Tumble(plugin,gui,0.,0,200., 0,1,w){}
1137   int value_event();
1138 };
1139 class BluebananaGAReadout2 : public BB_Tumble {
1140  public:
1141   BluebananaGAReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1142     : BB_Tumble(plugin,gui,MIN_GAMMA,0,MAX_GAMMA,2,.01,w){}
1143   int value_event();
1144 };
1145
1146 class BluebananaGASlider : public BluebananaSliderChannel {
1147 public:
1148   BluebananaGASlider(BluebananaMain *plugin, BluebananaWindow *gui,
1149                      int x, int y, int w, int h)
1150     : BluebananaSliderChannel(plugin,gui,x,y,w,h) { }
1151   virtual int handle_event() {
1152     plugin->config.Gadj_lo = loval;
1153     plugin->config.Gadj_hi = hival;
1154     plugin->config.Gadj_gamma = gamma;
1155     return 1;
1156   }
1157   void reset(){
1158     plugin->config.Gadj_lo=0;
1159     plugin->config.Gadj_hi=100;
1160     plugin->config.Gadj_gamma=1;
1161     update();
1162   }
1163   void update(){
1164     loval = plugin->config.Gadj_lo;
1165     hival = plugin->config.Gadj_hi;
1166     gamma = plugin->config.Gadj_gamma;
1167
1168     highlight = plugin->config.active && plugin->config.Gadj_active;
1169
1170     gui->Gadj_readout0->update(plugin->config.Gadj_lo);
1171     gui->Gadj_readout1->update(plugin->config.Gadj_hi);
1172     gui->Gadj_readout2->update(plugin->config.Gadj_gamma);
1173     gui->slider_labels[5]->set_color(highlight  &&
1174                                      (plugin->config.Gadj_lo != 0 ||
1175                                       plugin->config.Gadj_hi != 100 ||
1176                                       plugin->config.Gadj_gamma != 1) ?
1177                                      get_resources()->default_text_color : dimtextcolor);
1178
1179     gui->enter_config_change();
1180     gui->commit_config_change();
1181   }
1182   void trough_color(float hdel, float &r, float &g, float &b){
1183     if(hdel<0){
1184       r=g=b=0.;
1185     }else if(hdel<=1.f){
1186       g=hdel;
1187       r=b=0.;
1188     }else{
1189       g=1.;
1190       r=b=0.;
1191     }
1192   }
1193 };
1194
1195 int BluebananaGAReadout0::value_event(){
1196   plugin->config.Gadj_lo = BBCLAMP(get_value(),-100,plugin->config.Gadj_hi);
1197   plugin->config.Gadj_lo = BBCLAMP(get_value(),-100,100);
1198   gui->Gadj_slider->update();
1199   return 1;
1200 }
1201 int BluebananaGAReadout1::value_event(){
1202   plugin->config.Gadj_hi = BBCLAMP(get_value(),plugin->config.Gadj_lo,200);
1203   plugin->config.Gadj_hi = BBCLAMP(get_value(),0,200);
1204   gui->Gadj_slider->update();
1205   return 1;
1206 }
1207 int BluebananaGAReadout2::value_event(){
1208   plugin->config.Gadj_gamma = BBCLAMP(get_value(),MIN_GAMMA,MAX_GAMMA);
1209   gui->Gadj_slider->update();
1210   return 1;
1211 }
1212
1213 // ------------------------------- blue adjustment slider -------------------------------
1214 class BluebananaBAReadout0 : public BB_Tumble {
1215  public:
1216   BluebananaBAReadout0(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1217     : BB_Tumble(plugin,gui,-100.,0,100., 0,1,w){}
1218   int value_event();
1219 };
1220 class BluebananaBAReadout1 : public BB_Tumble {
1221  public:
1222   BluebananaBAReadout1(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1223     : BB_Tumble(plugin,gui,0.,0,200., 0,1,w){}
1224   int value_event();
1225 };
1226 class BluebananaBAReadout2 : public BB_Tumble {
1227  public:
1228   BluebananaBAReadout2(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1229     : BB_Tumble(plugin,gui,MIN_GAMMA,0,MAX_GAMMA,2,.01,w){}
1230   int value_event();
1231 };
1232
1233 class BluebananaBASlider : public BluebananaSliderChannel {
1234 public:
1235   BluebananaBASlider(BluebananaMain *plugin, BluebananaWindow *gui,
1236                      int x, int y, int w, int h)
1237     : BluebananaSliderChannel(plugin,gui,x,y,w,h) { }
1238   virtual int handle_event() {
1239     plugin->config.Badj_lo = loval;
1240     plugin->config.Badj_hi = hival;
1241     plugin->config.Badj_gamma = gamma;
1242     return 1;
1243   }
1244   void reset(){
1245     plugin->config.Badj_lo=0;
1246     plugin->config.Badj_hi=100;
1247     plugin->config.Badj_gamma=1;
1248     update();
1249   }
1250   void update(){
1251     loval = plugin->config.Badj_lo;
1252     hival = plugin->config.Badj_hi;
1253     gamma = plugin->config.Badj_gamma;
1254
1255     highlight = plugin->config.active && plugin->config.Badj_active;
1256
1257     gui->Badj_readout0->update(plugin->config.Badj_lo);
1258     gui->Badj_readout1->update(plugin->config.Badj_hi);
1259     gui->Badj_readout2->update(plugin->config.Badj_gamma);
1260     gui->slider_labels[6]->set_color(highlight  &&
1261                                      (plugin->config.Badj_lo != 0 ||
1262                                       plugin->config.Badj_hi != 100 ||
1263                                       plugin->config.Badj_gamma != 1) ?
1264                                      get_resources()->default_text_color : dimtextcolor);
1265
1266     gui->enter_config_change();
1267     gui->commit_config_change();
1268   }
1269   void trough_color(float hdel, float &r, float &g, float &b){
1270     if(hdel<0){
1271       r=g=b=0.;
1272     }else if(hdel<=1.f){
1273       b=hdel;
1274       g=r=0.;
1275     }else{
1276       b=1.;
1277       g=r=0.;
1278     }
1279   }
1280 };
1281
1282 int BluebananaBAReadout0::value_event(){
1283   plugin->config.Badj_lo = BBCLAMP(get_value(),-100,plugin->config.Badj_hi);
1284   plugin->config.Badj_lo = BBCLAMP(get_value(),-100,100);
1285   gui->Badj_slider->update();
1286   return 1;
1287 }
1288 int BluebananaBAReadout1::value_event(){
1289   plugin->config.Badj_hi = BBCLAMP(get_value(),plugin->config.Badj_lo,200);
1290   plugin->config.Badj_hi = BBCLAMP(get_value(),0,200);
1291   gui->Badj_slider->update();
1292   return 1;
1293 }
1294 int BluebananaBAReadout2::value_event(){
1295   plugin->config.Badj_gamma = BBCLAMP(get_value(),MIN_GAMMA,MAX_GAMMA);
1296   gui->Badj_slider->update();
1297   return 1;
1298 }
1299
1300 // ---------------------------------- opacity slider ---------------------------------
1301 class BluebananaOAReadout : public BB_Tumble {
1302  public:
1303   BluebananaOAReadout(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1304     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
1305   int value_event();
1306 };
1307
1308 class BluebananaOASlider : public BluebananaSliderSingle {
1309 public:
1310   BluebananaOASlider(BluebananaMain *plugin, BluebananaWindow *gui,
1311                      int x, int y, int w, int h)
1312     : BluebananaSliderSingle(plugin,gui,x,y,w,h,0,100) { }
1313   virtual int handle_event() {
1314     plugin->config.Oadj_val = val;
1315     return 1;
1316   }
1317   void reset(){
1318     plugin->config.Oadj_val=100;
1319     update();
1320   }
1321   void update(){
1322     val = plugin->config.Oadj_val;
1323     highlight = plugin->config.active && plugin->config.Oadj_active;
1324     gui->Oadj_readout->update(plugin->config.Oadj_val);
1325     gui->slider_labels[10]->set_color(highlight  &&
1326                                       plugin->config.Oadj_val != 100 ?
1327                                       get_resources()->default_text_color : dimtextcolor);
1328     gui->enter_config_change();
1329     gui->commit_config_change();
1330   }
1331   void trough_color(float hdel, float vdel, float &r, float &g, float &b, float &a){
1332     r=g=b=.8;
1333     a=1-cos(hdel*M_PI*.5);
1334   }
1335 };
1336
1337 int BluebananaOAReadout::value_event(){
1338   float val = get_value();
1339   plugin->config.Oadj_val = val;
1340   gui->Oadj_slider->update();
1341   return 1;
1342 }
1343
1344 // ---------------------------------- alpha slider ---------------------------------
1345 class BluebananaAAReadout : public BB_Tumble {
1346  public:
1347   BluebananaAAReadout(BluebananaMain *plugin, BluebananaWindow *gui, int w)
1348     : BB_Tumble(plugin,gui,0.,0,100., 0,1,w){}
1349   int value_event();
1350 };
1351
1352 class BluebananaAASlider : public BluebananaSliderSingle {
1353 public:
1354   BluebananaAASlider(BluebananaMain *plugin, BluebananaWindow *gui,
1355                      int x, int y, int w, int h)
1356     : BluebananaSliderSingle(plugin,gui,x,y,w,h,0,100) {}
1357   virtual int handle_event() {
1358     plugin->config.Aadj_val = val;
1359     return 1;
1360   }
1361   void reset(){
1362     plugin->config.Aadj_val=100;
1363     update();
1364   }
1365   void update(){
1366     val = plugin->config.Aadj_val;
1367     if( BC_CModels::has_alpha(plugin->colormodel) ) {
1368       if( is_hidden() ) show_window();
1369     }else{
1370       if( !is_hidden() ) hide_window();
1371     }
1372     if( is_hidden() ) return;
1373     highlight = plugin->config.active && plugin->config.Aadj_active;
1374     gui->Aadj_readout->update(plugin->config.Aadj_val);
1375     gui->slider_labels[11]->set_color(highlight  && plugin->config.Aadj_val != 100 ?
1376          get_resources()->default_text_color : dimtextcolor);
1377     gui->enter_config_change();
1378     gui->commit_config_change();
1379   }
1380   void trough_color(float hdel, float vdel, float &r, float &g, float &b, float &a){
1381     r=g=b=.8;
1382     a=1-cos(hdel*M_PI*.5);
1383   }
1384 };
1385
1386 int BluebananaAAReadout::value_event(){
1387   float val = get_value();
1388   plugin->config.Aadj_val = val;
1389   gui->Aadj_slider->update();
1390   return 1;
1391 }
1392
1393 // ------------------------------------- picker buttons -----------------------------------------
1394 class BluebananaHPicker : public BC_GenericButton{
1395  public:
1396   BluebananaHPicker(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Pick")){
1397     this->gui = gui;
1398   }
1399   int handle_event() { gui->Hsel_slider->pick(); return 1; }
1400   BluebananaWindow *gui;
1401 };
1402 class BluebananaSPicker : public BC_GenericButton{
1403  public:
1404   BluebananaSPicker(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Pick")){
1405     this->gui = gui;
1406   }
1407   int handle_event() { gui->Ssel_slider->pick(); return 1; }
1408   BluebananaWindow *gui;
1409 };
1410 class BluebananaVPicker : public BC_GenericButton{
1411  public:
1412   BluebananaVPicker(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Pick")){
1413     this->gui = gui;
1414   }
1415   int handle_event() { gui->Vsel_slider->pick(); return 1; }
1416   BluebananaWindow *gui;
1417 };
1418
1419 // -------------------------------------- reset buttons -----------------------------------------
1420
1421 class BluebananaHAReset : public BC_GenericButton{
1422  public:
1423   BluebananaHAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1424     this->gui = gui;
1425   }
1426   int handle_event() { gui->Hadj_slider->reset(); return 1;}
1427   BluebananaWindow *gui;
1428 };
1429 class BluebananaSAReset : public BC_GenericButton{
1430  public:
1431   BluebananaSAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1432     this->gui = gui;
1433   }
1434   int handle_event() { gui->Sadj_slider->reset(); return 1;}
1435   BluebananaWindow *gui;
1436 };
1437 class BluebananaVAReset : public BC_GenericButton{
1438  public:
1439   BluebananaVAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1440     this->gui = gui;
1441   }
1442   int handle_event() { gui->Vadj_slider->reset(); return 1;}
1443   BluebananaWindow *gui;
1444 };
1445 class BluebananaRAReset : public BC_GenericButton{
1446  public:
1447   BluebananaRAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1448     this->gui = gui;
1449   }
1450   int handle_event() { gui->Radj_slider->reset(); return 1;}
1451   BluebananaWindow *gui;
1452 };
1453 class BluebananaGAReset : public BC_GenericButton{
1454  public:
1455   BluebananaGAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1456     this->gui = gui;
1457   }
1458   int handle_event() { gui->Gadj_slider->reset(); return 1;}
1459   BluebananaWindow *gui;
1460 };
1461 class BluebananaBAReset : public BC_GenericButton{
1462  public:
1463   BluebananaBAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1464     this->gui = gui;
1465   }
1466   int handle_event() { gui->Badj_slider->reset(); return 1;}
1467   BluebananaWindow *gui;
1468 };
1469 class BluebananaOAReset : public BC_GenericButton{
1470  public:
1471   BluebananaOAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1472     this->gui = gui;
1473   }
1474   int handle_event() { gui->Oadj_slider->reset(); return 1;}
1475   BluebananaWindow *gui;
1476 };
1477 class BluebananaAAReset : public BC_GenericButton{
1478  public:
1479   BluebananaAAReset(BluebananaWindow *gui, int w) : BC_GenericButton(-1, -1, w, _("Reset")){
1480     this->gui = gui;
1481   }
1482   int handle_event() { gui->Aadj_slider->reset(); return 1;}
1483   BluebananaWindow *gui;
1484 };
1485
1486 // ----------------------------------- slider active buttons ------------------------------------
1487
1488 BluebananaHActive::BluebananaHActive(BluebananaMain *plugin, BluebananaWindow *gui)
1489   : BC_CheckBox(-1, -1, &plugin->config.Hsel_active, ""){
1490   this->plugin = plugin;
1491   this->gui = gui;
1492 }
1493 int BluebananaHActive::handle_event(){
1494   plugin->config.Hsel_active = get_value();
1495   update();
1496   return 1;
1497 }
1498 void BluebananaHActive::update(){
1499   this->BC_CheckBox::update(plugin->config.Hsel_active,1);
1500   gui->Hsel_slider->update();
1501 }
1502
1503 BluebananaSActive::BluebananaSActive(BluebananaMain *plugin, BluebananaWindow *gui)
1504   : BC_CheckBox(-1, -1, &plugin->config.Ssel_active, ""){
1505   this->plugin = plugin;
1506   this->gui = gui;
1507 }
1508 int BluebananaSActive::handle_event(){
1509   plugin->config.Ssel_active = get_value();
1510   update();
1511   return 1;
1512 }
1513 void BluebananaSActive::update(){
1514   this->BC_CheckBox::update(plugin->config.Ssel_active,1);
1515   gui->Ssel_slider->update();
1516 }
1517
1518 BluebananaVActive::BluebananaVActive(BluebananaMain *plugin, BluebananaWindow *gui)
1519   : BC_CheckBox(-1, -1, &plugin->config.Vsel_active, ""){
1520   this->plugin = plugin;
1521   this->gui = gui;
1522 }
1523 int BluebananaVActive::handle_event(){
1524   plugin->config.Vsel_active = get_value();
1525   update();
1526   return 1;
1527 }
1528 void BluebananaVActive::update(){
1529   this->BC_CheckBox::update(plugin->config.Vsel_active,1);
1530   gui->Vsel_slider->update();
1531 }
1532
1533 class BluebananaFActive : public BC_CheckBox {
1534 public:
1535   BluebananaFActive(BluebananaMain *plugin, BluebananaWindow *gui)
1536   : BC_CheckBox(-1, -1, &plugin->config.Fsel_active, ""){
1537     this->plugin = plugin;
1538     this->gui = gui;
1539   }
1540   virtual int handle_event(){
1541     plugin->config.Fsel_active = get_value();
1542     update();
1543     return 1;
1544   }
1545   void update(){
1546     this->BC_CheckBox::update(plugin->config.Fsel_active,1);
1547     gui->Fsel_slider->update();
1548   }
1549   BluebananaMain *plugin;
1550   BluebananaWindow *gui;
1551 };
1552
1553 class BluebananaHAActive : public BC_CheckBox {
1554 public:
1555   BluebananaHAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1556   : BC_CheckBox(-1, -1, &plugin->config.Hadj_active, ""){
1557     this->plugin = plugin;
1558     this->gui = gui;
1559   }
1560   virtual int handle_event(){
1561     plugin->config.Hadj_active = get_value();
1562     update();
1563     return 1;
1564   }
1565   void update(){
1566     this->BC_CheckBox::update(plugin->config.Hadj_active,1);
1567     gui->Hadj_slider->update();
1568   }
1569   BluebananaMain *plugin;
1570   BluebananaWindow *gui;
1571 };
1572
1573 class BluebananaSAActive : public BC_CheckBox {
1574 public:
1575   BluebananaSAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1576   : BC_CheckBox(-1, -1, &plugin->config.Sadj_active, ""){
1577     this->plugin = plugin;
1578     this->gui = gui;
1579   }
1580   virtual int handle_event(){
1581     plugin->config.Sadj_active = get_value();
1582     update();
1583     return 1;
1584   }
1585   void update(){
1586     this->BC_CheckBox::update(plugin->config.Sadj_active,1);
1587     gui->Sadj_slider->update();
1588   }
1589   BluebananaMain *plugin;
1590   BluebananaWindow *gui;
1591 };
1592
1593 class BluebananaVAActive : public BC_CheckBox {
1594 public:
1595   BluebananaVAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1596   : BC_CheckBox(-1, -1, &plugin->config.Vadj_active, ""){
1597     this->plugin = plugin;
1598     this->gui = gui;
1599   }
1600   virtual int handle_event(){
1601     plugin->config.Vadj_active = get_value();
1602     update();
1603     return 1;
1604   }
1605   void update(){
1606     this->BC_CheckBox::update(plugin->config.Vadj_active,1);
1607     gui->Vadj_slider->update();
1608   }
1609   BluebananaMain *plugin;
1610   BluebananaWindow *gui;
1611 };
1612
1613 class BluebananaRAActive : public BC_CheckBox {
1614 public:
1615   BluebananaRAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1616   : BC_CheckBox(-1, -1, &plugin->config.Radj_active, ""){
1617     this->plugin = plugin;
1618     this->gui = gui;
1619   }
1620   virtual int handle_event(){
1621     plugin->config.Radj_active = get_value();
1622     update();
1623     return 1;
1624   }
1625   void update(){
1626     this->BC_CheckBox::update(plugin->config.Radj_active,1);
1627     gui->Radj_slider->update();
1628   }
1629   BluebananaMain *plugin;
1630   BluebananaWindow *gui;
1631 };
1632
1633 class BluebananaGAActive : public BC_CheckBox {
1634 public:
1635   BluebananaGAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1636   : BC_CheckBox(-1, -1, &plugin->config.Gadj_active, ""){
1637     this->plugin = plugin;
1638     this->gui = gui;
1639   }
1640   virtual int handle_event(){
1641     plugin->config.Gadj_active = get_value();
1642     update();
1643     return 1;
1644   }
1645   void update(){
1646     this->BC_CheckBox::update(plugin->config.Gadj_active,1);
1647     gui->Gadj_slider->update();
1648   }
1649   BluebananaMain *plugin;
1650   BluebananaWindow *gui;
1651 };
1652
1653 class BluebananaBAActive : public BC_CheckBox {
1654 public:
1655   BluebananaBAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1656   : BC_CheckBox(-1, -1, &plugin->config.Badj_active, ""){
1657     this->plugin = plugin;
1658     this->gui = gui;
1659   }
1660   virtual int handle_event(){
1661     plugin->config.Badj_active = get_value();
1662     update();
1663     return 1;
1664   }
1665   void update(){
1666     this->BC_CheckBox::update(plugin->config.Badj_active,1);
1667     gui->Badj_slider->update();
1668   }
1669   BluebananaMain *plugin;
1670   BluebananaWindow *gui;
1671 };
1672
1673 class BluebananaOAActive : public BC_CheckBox {
1674 public:
1675   BluebananaOAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1676   : BC_CheckBox(-1, -1, &plugin->config.Oadj_active, ""){
1677     this->plugin = plugin;
1678     this->gui = gui;
1679   }
1680   virtual int handle_event(){
1681     plugin->config.Oadj_active = get_value();
1682     update();
1683     return 1;
1684   }
1685   void update(){
1686     this->BC_CheckBox::update(plugin->config.Oadj_active,1);
1687     gui->Oadj_slider->update();
1688   }
1689   BluebananaMain *plugin;
1690   BluebananaWindow *gui;
1691 };
1692
1693 class BluebananaAAActive : public BC_CheckBox {
1694 public:
1695
1696   BluebananaAAActive(BluebananaMain *plugin, BluebananaWindow *gui)
1697   : BC_CheckBox(-1, -1, &plugin->config.Aadj_active, ""){
1698     this->plugin = plugin;
1699     this->gui = gui;
1700   }
1701   virtual int handle_event(){
1702     plugin->config.Aadj_active =
1703       !BC_CModels::has_alpha(plugin->colormodel) ? 0 : get_value();
1704     update();
1705     return 1;
1706   }
1707   void update(){
1708     this->BC_CheckBox::update(plugin->config.Aadj_active,1);
1709     if( BC_CModels::has_alpha(plugin->colormodel) ) {
1710       if( is_hidden() ) show_window();
1711     }else{
1712       if( !is_hidden() ) hide_window();
1713     }
1714     if( is_hidden() ) return;
1715     gui->Aadj_slider->update();
1716   }
1717   BluebananaMain *plugin;
1718   BluebananaWindow *gui;
1719 };
1720
1721 // -------------------------------------------- Erode --------------------------------------------
1722 class BluebananaErode : public BC_CheckBox {
1723 public:
1724   BluebananaErode(BluebananaMain *plugin, BluebananaWindow *gui)
1725   : BC_CheckBox(-1, -1, &plugin->config.Fsel_erode, ""){
1726     this->plugin = plugin;
1727     this->gui = gui;
1728   }
1729   virtual int handle_event(){
1730     plugin->config.Fsel_erode = get_value();
1731     update();
1732     return 1;
1733   }
1734   void update(){
1735     this->BC_CheckBox::update(plugin->config.Fsel_erode,1);
1736     gui->Fsel_slider->update();
1737   }
1738   BluebananaMain *plugin;
1739   BluebananaWindow *gui;
1740 };
1741
1742
1743 // -------------------------------------- Invert Selection ---------------------------------------
1744 class BluebananaIS : public BC_CheckBox {
1745 public:
1746   BluebananaIS(BluebananaMain *plugin, BluebananaWindow *gui)
1747   : BC_CheckBox(-1, -1, &plugin->config.invert_selection, ""){
1748     this->plugin = plugin;
1749     this->gui = gui;
1750   }
1751   virtual int handle_event(){
1752     plugin->config.invert_selection = get_value();
1753     update();
1754     return 1;
1755   }
1756   void update(){
1757     this->BC_CheckBox::update(plugin->config.invert_selection,1);
1758     gui->enter_config_change();
1759     gui->commit_config_change();
1760   }
1761   BluebananaMain *plugin;
1762   BluebananaWindow *gui;
1763 };
1764
1765
1766 // -------------------------------------------- Op --------------------------------------------
1767 class BluebananaOp : public BC_CheckBox {
1768 public:
1769   BluebananaOp(BluebananaMain *plugin, BluebananaWindow *gui)
1770     : BC_CheckBox(-1, -1, &plugin->config.op, ""){
1771     this->plugin = plugin;
1772     this->gui = gui;
1773   }
1774   virtual int handle_event() {
1775     if(plugin->config.op != get_value()){
1776       plugin->config.op = get_value();
1777       gui->enter_config_change();
1778       gui->commit_config_change();
1779     }
1780     return 1;
1781   }
1782   void update (){
1783     if(plugin->config.op != get_value()){
1784       this->BC_CheckBox::update(plugin->config.op,1);
1785     }
1786   };
1787   BluebananaMain *plugin;
1788   BluebananaWindow *gui;
1789 };
1790
1791 // -------------------------------------------- Mark --------------------------------------------
1792 class BluebananaMark : public BC_CheckBox {
1793 public:
1794   BluebananaMark(BluebananaMain *plugin, BluebananaWindow *gui)
1795     : BC_CheckBox(-1, -1, 0, ""){
1796     this->plugin = plugin;
1797     this->gui = gui;
1798   }
1799   virtual int handle_event() {
1800     if(plugin->config.mark != get_value()){
1801       plugin->config.mark = get_value();
1802       plugin->save_nonauto();
1803       if(plugin->config.mark){
1804         gui->set_repeat(207);
1805       }else{
1806         gui->unset_repeat(207);
1807       }
1808       plugin->server->mwindow->sync_parameters();
1809     }
1810     return 1;
1811   }
1812   void update (){
1813     if(plugin->config.mark != get_value()){
1814       this->BC_CheckBox::update(plugin->config.mark,1);
1815       if(plugin->config.mark){
1816         gui->set_repeat(207);
1817       }else{
1818         gui->unset_repeat(207);
1819       }
1820     }
1821   };
1822   BluebananaMain *plugin;
1823   BluebananaWindow *gui;
1824 };
1825
1826 // ------------------------------------------- Active -------------------------------------------
1827 class BluebananaActive : public BC_CheckBox {
1828 public:
1829   BluebananaActive(BluebananaMain *plugin, BluebananaWindow *gui)
1830     : BC_CheckBox(-1, -1, &plugin->config.active, ""){
1831     this->plugin = plugin;
1832     this->gui = gui;
1833     active=-1;
1834   }
1835   virtual int handle_event(){
1836     active = get_value();
1837     update();
1838     return 1;
1839   }
1840   void update(){
1841     if(active != plugin->config.active){
1842       plugin->config.active = active;
1843       this->BC_CheckBox::update(plugin->config.active,1);
1844       gui->enter_config_change();
1845       gui->Hadj_slider->update();
1846       gui->Sadj_slider->update();
1847       gui->Vadj_slider->update();
1848       gui->Radj_slider->update();
1849       gui->Gadj_slider->update();
1850       gui->Badj_slider->update();
1851       gui->Oadj_slider->update();
1852       gui->Aadj_slider->update();
1853       gui->commit_config_change();
1854     }
1855   }
1856   BluebananaMain *plugin;
1857   BluebananaWindow *gui;
1858   int active;
1859 };
1860
1861 // ---------------------------------------- Capture mask ---------------------------------------
1862 class BluebananaUnmask : public BC_CheckBox {
1863 public:
1864   BluebananaUnmask(BluebananaMain *plugin, BluebananaWindow *gui,int padx)
1865     : BC_CheckBox(-1, -1, &plugin->config.capture_mask, ""){
1866     this->plugin = plugin;
1867     this->gui = gui;
1868     this->padx = padx;
1869     this->label = new BC_Title(-1,-1,_(" End Mask"));
1870     this->x=-1;
1871     this->y=-1;
1872     gui->add_subwindow(this->label);
1873     gui->add_subwindow(this);
1874   }
1875   virtual int handle_event(){
1876     plugin->config.capture_mask=get_value();
1877     plugin->save_nonauto();
1878     update();
1879     gui->enter_config_change();
1880     gui->commit_config_change();
1881     return 1;
1882   }
1883   int get_h(){
1884     return label->get_h();
1885   }
1886   int get_w(){
1887     return BC_CheckBox::get_w()+label->get_w()+padx*4;
1888   }
1889   void reposition_window(int x, int y){
1890     int h = label->get_h();
1891     this->x = x;
1892     this->y = y;
1893     label->reposition_window(x+padx,y);
1894     BC_CheckBox::reposition_window(x+padx*2+label->get_w(),y+(h-BC_CheckBox::get_h())/2);
1895     update();
1896   }
1897   void update(){
1898     int w = get_w();
1899     int h = get_h();
1900     int f=0;
1901     int hideme = !plugin->config.use_mask;
1902     switch(plugin->colormodel){
1903     case BC_RGB888:
1904     case BC_RGB_FLOAT:
1905     case BC_YUV888:
1906     case BC_RGB161616:
1907     case BC_YUV161616:
1908       hideme=1;
1909       break;
1910     }
1911
1912     if(hideme && !is_hidden()){
1913       hide_window();
1914       label->hide_window();
1915       gui->set_color(get_resources()->get_bg_color());
1916       gui->draw_box(x,y,w,h);
1917       gui->set_color(get_resources()->default_text_color);
1918       gui->draw_line(x,y+h/2,x+w,y+h/2);
1919       f=1;
1920     }
1921
1922     if(!hideme && is_hidden()){
1923       gui->set_color(get_resources()->get_bg_color());
1924       gui->draw_box(x,y,w,h);
1925       show_window();
1926       label->show_window();
1927       f=1;
1928     }
1929
1930     if(plugin->config.capture_mask != get_value())
1931       this->BC_CheckBox::update(plugin->config.capture_mask,1);
1932     if(f)
1933       gui->flash(x,y,w,h);
1934   }
1935   BluebananaMain *plugin;
1936   BluebananaWindow *gui;
1937   BC_Title *label;
1938   int x,y,padx;
1939 };
1940
1941 // ------------------------------------------ Use mask ----------------------------------------
1942 class BluebananaA2Sel : public BC_CheckBox {
1943 public:
1944   BluebananaA2Sel(BluebananaMain *plugin, BluebananaWindow *gui,int padx)
1945     : BC_CheckBox(-1, -1, &plugin->config.use_mask, ""){
1946     this->plugin = plugin;
1947     this->gui = gui;
1948     this->padx = padx;
1949     this->label = new BC_Title(-1,-1,_(" Mask Selection"));
1950     this->x=-1;
1951     this->y=-1;
1952     gui->add_subwindow(this->label);
1953     gui->add_subwindow(this);
1954   }
1955   virtual int handle_event(){
1956     plugin->config.use_mask=get_value();
1957     plugin->save_nonauto();
1958     update();
1959     gui->enter_config_change();
1960     gui->commit_config_change();
1961     return 1;
1962   }
1963   int get_h(){
1964     return label->get_h();
1965   }
1966   int get_w(){
1967     return BC_CheckBox::get_w()+label->get_w()+padx*4;
1968   }
1969   void reposition_window(int x, int y){
1970     int h = label->get_h();
1971     this->x = x;
1972     this->y = y;
1973     label->reposition_window(x+padx,y);
1974     BC_CheckBox::reposition_window(x+padx*2+label->get_w(),y+(h-BC_CheckBox::get_h())/2);
1975     update();
1976   }
1977   void update(){
1978     int w = get_w();
1979     int h = get_h();
1980     int f=0;
1981
1982     if(gui->capture_mask)
1983       gui->capture_mask->update();
1984
1985     switch(plugin->colormodel){
1986     case BC_RGB888:
1987     case BC_RGB_FLOAT:
1988     case BC_YUV888:
1989     case BC_RGB161616:
1990     case BC_YUV161616:
1991       if(!is_hidden()){
1992         hide_window();
1993         label->hide_window();
1994         gui->set_color(get_resources()->get_bg_color());
1995         gui->draw_box(x,y,w,h);
1996         gui->set_color(get_resources()->default_text_color);
1997         gui->draw_line(x,y+h/2,x+w,y+h/2);
1998         f=1;
1999       }
2000       break;
2001     case BC_RGBA8888:
2002     case BC_RGBA_FLOAT:
2003     case BC_YUVA8888:
2004     case BC_RGBA16161616:
2005     case BC_YUVA16161616:
2006       if(is_hidden()){
2007         gui->set_color(get_resources()->get_bg_color());
2008         gui->draw_box(x,y,w,h);
2009         show_window();
2010         label->show_window();
2011         f=1;
2012       }
2013       break;
2014     case -1:
2015       // not initialized yet
2016       return;
2017     default:
2018       fprintf(stderr,_("Unknown colormodel in BluebananaA2Sel:update()\n"));
2019       break;
2020     }
2021     if(plugin->config.use_mask != get_value())
2022       this->BC_CheckBox::update(plugin->config.use_mask,1);
2023     if(f)
2024       gui->flash(x,y,w,h);
2025   }
2026   BluebananaMain *plugin;
2027   BluebananaWindow *gui;
2028   BC_Title *label;
2029   int x,y,padx;
2030 };
2031
2032 // --------------------------------------- Main GUI window --------------------------------------
2033 BluebananaWindow::BluebananaWindow(BluebananaMain *plugin)
2034  : PluginClientWindow(plugin,1000,1000,0,1,1)
2035 {
2036   do_render=0;
2037   windowx = get_x();
2038   windowy = get_y();
2039   this->plugin = plugin;
2040   config_refcount=1; // suppress pushing config during startup
2041   config_change=0;
2042   config_produce=0;
2043   config_consume=0;
2044   config_pending=0;
2045
2046   Hsel_slider=NULL;
2047   Ssel_slider=NULL;
2048   Vsel_slider=NULL;
2049   Fsel_slider=NULL;
2050   Hadj_slider=NULL;
2051   Sadj_slider=NULL;
2052   Vadj_slider=NULL;
2053   Radj_slider=NULL;
2054   Gadj_slider=NULL;
2055   Badj_slider=NULL;
2056   Oadj_slider=NULL;
2057   Aadj_slider=NULL;
2058
2059   use_mask=0;
2060   capture_mask=0;
2061 }
2062
2063 BluebananaWindow::~BluebananaWindow()
2064 {
2065 }
2066
2067 void BluebananaWindow::create_objects()
2068 {
2069   int xmargin = 20, ymargin = 10;
2070   float row_padding = .1;
2071   float column_padding = .3;
2072   int padx=0;
2073
2074   int i;
2075   int row_h=0, row_adv=0;
2076   int label_x=0;
2077   int label_w=0;
2078   int slider_w=0;
2079   int picker_w=0;
2080   int reset_w=0;
2081   int tumbler_w=0,tumbler_ww=0,tumbler_h=0;
2082   int tumbler_col1_x=0,tumbler_col2_x=0,tumbler_col2_w=0;
2083   int y = ymargin;
2084
2085   //BluebananaHAReset *hareset=NULL;
2086
2087   config_refcount=0;
2088   enter_config_change();
2089
2090   /* window headline */
2091   {
2092     BC_Title *l = new BC_Title(xmargin,y,_("Combine Selection"));
2093     BC_Title *l2 = new BC_Title(-1,-1,_(" Mark Selected Areas"));
2094     add_subwindow(mark = new BluebananaMark(plugin,this));
2095     add_subwindow(l);
2096     add_subwindow(l2);
2097     padx = l->get_h()*column_padding;
2098     add_subwindow(op = new BluebananaOp(plugin,this));
2099     int x0 = xmargin + l->get_w() + padx;
2100     op->reposition_window(x0,y-(op->get_h()-l->get_h())/2);
2101     x0 += op->get_w() + padx;
2102     int x1 = get_w()-xmargin-mark->get_w();
2103     mark->reposition_window(x1,y-(mark->get_h()-l->get_h())/2);
2104     x1 -= padx+l2->get_w();
2105     l2->reposition_window(x1,y);
2106     x1-=padx;
2107
2108     set_color(get_resources()->default_text_color);
2109     int y0 = y+l->get_h()*.5;
2110     draw_line(x0,y0, x1,y0);
2111
2112     y += l->get_h()*(row_padding+1.);
2113   }
2114
2115   label_x = xmargin + 100 + padx;
2116   const char *labels[12]={_("hue"),_("saturation"),_("value"),_("fill"),_("red"),_("green"),_("blue"),_("hue"),_("saturation"),_("value"),_("fade"),_("alpha")};
2117   for(i=0;i<12;i++){
2118     add_subwindow(slider_labels[i] = new BC_Title(-1,-1,labels[i]));
2119     if(slider_labels[i]->get_w()>label_w)label_w=slider_labels[i]->get_w();
2120   }
2121
2122   int tumbler_text_ww = MAX(get_text_width(MEDIUMFONT,"-000"),get_text_width(MEDIUMFONT,"5.00"))+8;
2123   int tumbler_text_w = get_text_width(MEDIUMFONT,"50")+8;
2124   if(tumbler_text_w*3<tumbler_text_ww*2){
2125     tumbler_text_ww = (tumbler_text_ww*2+2)/3*3/2;
2126     tumbler_text_w=tumbler_text_ww*2/3;
2127   }
2128
2129   erode_label = new BC_Title(xmargin,y,_("pre-erode"));
2130   BluebananaErode *erode = new BluebananaErode(plugin,this);
2131   add_subwindow(erode_label);
2132   add_subwindow(erode);
2133
2134   for(i=0;i<12;i++){
2135     BC_GenericButton *p=NULL;
2136     BluebananaSlider *s=NULL;
2137     BB_Tumble *t0 = NULL, *t1=NULL, *t2=NULL;
2138     BC_Toggle *a = NULL;
2139     BC_Title *l = slider_labels[i];
2140
2141     switch(i){
2142     case 0:
2143
2144       add_subwindow(t0 = Hsel_readout0 = new BluebananaHSReadout0(plugin,this,tumbler_text_ww));
2145       add_subwindow(t1 = Hsel_readout1 = new BluebananaHSReadout1(plugin,this,tumbler_text_ww));
2146       add_subwindow(t2 = Hsel_readout2 = new BluebananaHSReadout2(plugin,this,tumbler_text_ww));
2147       add_subwindow(a = Hsel_active = new BluebananaHActive(plugin,this));
2148
2149       /* need a narrow and a wide wide tumbler */
2150       add_subwindow(Fsel_readout0 = new BluebananaFSReadout0(plugin,this,tumbler_text_w));
2151       add_subwindow(Fsel_readout1 = new BluebananaFSReadout1(plugin,this,tumbler_text_w));
2152       add_subwindow(Fsel_readout2 = new BluebananaFSReadout2(plugin,this,tumbler_text_w));
2153       add_subwindow(Fsel_readout3 = new BluebananaFSReadout3(plugin,this,tumbler_text_ww));
2154       tumbler_w = Fsel_readout0->get_w();
2155       tumbler_ww = t0->get_w();
2156       tumbler_h = t0->get_h();
2157
2158       /* need a reset button's width */
2159       reset_w = BC_GenericButton::calculate_w(this, _("Reset"));
2160       picker_w = BC_GenericButton::calculate_w(this, _("Pick"));
2161
2162       /* determine row spacing */
2163       row_h = 30; /* minimum widget height allowance for the row
2164                      (really, min height for the slider) */
2165       if(row_h<a->get_h())row_h=a->get_h();
2166       if(row_h<l->get_h())row_h=l->get_h();
2167       if(row_h<BC_GenericButton::calculate_h())row_h=BC_GenericButton::calculate_h();
2168       if(row_h<t2->get_h())row_h=t2->get_h();
2169       row_adv = row_h*(1.+row_padding);
2170
2171       /* determine horizontal element positioning; two main setups */
2172       /* setup 1: three tumblers + button */
2173       tumbler_col2_w = MAX(reset_w,picker_w);
2174
2175       /* setup 2: four tumblers + erode */
2176       {
2177         int threew = tumbler_ww*3 + padx*4 + tumbler_col2_w;
2178         int fourw = tumbler_w*3 + tumbler_ww + padx*5 + erode->get_w() + erode_label->get_w();
2179         if(fourw>threew) tumbler_col2_w += fourw-threew;
2180       }
2181
2182       tumbler_col2_x = get_w()-xmargin-tumbler_col2_w;
2183       tumbler_col1_x = tumbler_col2_x - tumbler_ww*3 - padx*5;
2184       slider_x = label_x+padx;
2185       slider_w = (tumbler_col1_x - slider_x - padx*3);
2186
2187       /* make sure the label x doesn't cause any labels to go off the
2188          left of the pane */
2189       {
2190         int lx = label_x - padx - a->get_w();
2191         if (lx-label_w < xmargin){
2192           slider_x += ((xmargin+label_w)-lx);
2193           label_x += ((xmargin+label_w)-lx);
2194           slider_w -= ((xmargin+label_w)-lx);
2195         }
2196       }
2197
2198       y += row_adv/3; /* extra half row spacing under headline */
2199       s = Hsel_slider = new BluebananaHSSlider(plugin,this,slider_x,y,slider_w,row_h);
2200       add_subwindow(p = new BluebananaHPicker(this,tumbler_col2_w));
2201
2202       /* Move the upper alpha <->selection config buttons into place */
2203       {
2204         int x0 = slider_x+slider_w+padx*2;
2205         invert_selection = new BluebananaIS(plugin,this);
2206         BC_Title *l = new BC_Title(xmargin,y,_(" Invert Selection"));
2207         add_subwindow(l);
2208         add_subwindow(invert_selection);
2209         int w0 = padx+l->get_w()+padx+invert_selection->get_w()+padx*2;
2210         set_color(get_resources()->get_bg_color());
2211         draw_box(x0-w0,ymargin,w0,ymargin+l->get_h());
2212         x0-=padx*2;
2213         x0-=invert_selection->get_w();
2214         invert_selection->reposition_window(x0,ymargin+(l->get_h()-invert_selection->get_h())/2);
2215         x0-=padx;
2216         x0-=l->get_w();
2217         l->reposition_window(x0,ymargin);
2218         x0-=padx;
2219         x0-=padx*5;
2220
2221         use_mask = new BluebananaA2Sel(plugin,this,padx);
2222         x0-=use_mask->get_w();
2223         use_mask->reposition_window(x0, ymargin);
2224         capture_mask = new BluebananaUnmask(plugin,this,padx);
2225         x0-=padx*5 + capture_mask->get_w();
2226         capture_mask->reposition_window(x0, ymargin);
2227       }
2228
2229       break;
2230
2231     case 1:
2232
2233       add_subwindow(t0 = Ssel_readout0 = new BluebananaSSReadout0(plugin,this,tumbler_text_ww));
2234       add_subwindow(t1 = Ssel_readout1 = new BluebananaSSReadout1(plugin,this,tumbler_text_ww));
2235       add_subwindow(t2 = Ssel_readout2 = new BluebananaSSReadout2(plugin,this,tumbler_text_ww));
2236       add_subwindow(a = Ssel_active = new BluebananaSActive(plugin,this));
2237       add_subwindow(p = new BluebananaSPicker(this,tumbler_col2_w));
2238       s = Ssel_slider = new BluebananaSSSlider(plugin,this,slider_x,y,slider_w,row_h);
2239       break;
2240
2241     case 2:
2242
2243       add_subwindow(t0 = Vsel_readout0 = new BluebananaVSReadout0(plugin,this,tumbler_text_ww));
2244       add_subwindow(t1 = Vsel_readout1 = new BluebananaVSReadout1(plugin,this,tumbler_text_ww));
2245       add_subwindow(t2 = Vsel_readout2 = new BluebananaVSReadout2(plugin,this,tumbler_text_ww));
2246       add_subwindow(a = Vsel_active = new BluebananaVActive(plugin,this));
2247       add_subwindow(p = new BluebananaVPicker(this,tumbler_col2_w));
2248       s = Vsel_slider = new BluebananaVSSlider(plugin,this,slider_x,y,slider_w,row_h);
2249       break;
2250
2251     case 3:
2252
2253       add_subwindow(a = Fsel_active = new BluebananaFActive(plugin,this));
2254       s = Fsel_slider = new BluebananaFSSlider(plugin,this,slider_x,y,slider_w,row_h);
2255
2256       Fsel_readout0->reposition_window(tumbler_col1_x, y + (row_h-tumbler_h)/2 + 1);
2257       Fsel_readout1->reposition_window(tumbler_col1_x+tumbler_w, y + (row_h-tumbler_h)/2 + 1);
2258       Fsel_readout2->reposition_window(tumbler_col1_x+tumbler_w*2, y + (row_h-tumbler_h)/2 + 1);
2259       Fsel_readout3->reposition_window(tumbler_col1_x+tumbler_w*3+padx*2,
2260                                        y + (row_h-tumbler_h)/2 + 1);
2261
2262       {
2263         int x = get_w() - xmargin - erode->get_w();
2264         erode->reposition_window(x,y+(row_h-erode->get_h())/2);
2265         erode_label->reposition_window(x-erode_label->get_w()-padx,y+(row_h-erode_label->get_h())/2);
2266       }
2267
2268       break;
2269
2270     case 4:
2271
2272       add_subwindow(t0 = Radj_readout0 = new BluebananaRAReadout0(plugin,this,tumbler_text_ww));
2273       add_subwindow(t1 = Radj_readout1 = new BluebananaRAReadout1(plugin,this,tumbler_text_ww));
2274       add_subwindow(t2 = Radj_readout2 = new BluebananaRAReadout2(plugin,this,tumbler_text_ww));
2275       add_subwindow(a = Radj_active = new BluebananaRAActive(plugin,this));
2276       add_subwindow(p = new BluebananaRAReset(this,tumbler_col2_w));
2277       s = Radj_slider = new BluebananaRASlider(plugin,this,slider_x,y,slider_w,row_h);
2278       break;
2279
2280     case 5:
2281
2282       add_subwindow(t0 = Gadj_readout0 = new BluebananaGAReadout0(plugin,this,tumbler_text_ww));
2283       add_subwindow(t1 = Gadj_readout1 = new BluebananaGAReadout1(plugin,this,tumbler_text_ww));
2284       add_subwindow(t2 = Gadj_readout2 = new BluebananaGAReadout2(plugin,this,tumbler_text_ww));
2285       add_subwindow(a = Gadj_active = new BluebananaGAActive(plugin,this));
2286       add_subwindow(p = new BluebananaGAReset(this,tumbler_col2_w));
2287       s = Gadj_slider = new BluebananaGASlider(plugin,this,slider_x,y,slider_w,row_h);
2288       break;
2289
2290     case 6:
2291
2292       add_subwindow(t0 = Badj_readout0 = new BluebananaBAReadout0(plugin,this,tumbler_text_ww));
2293       add_subwindow(t1 = Badj_readout1 = new BluebananaBAReadout1(plugin,this,tumbler_text_ww));
2294       add_subwindow(t2 = Badj_readout2 = new BluebananaBAReadout2(plugin,this,tumbler_text_ww));
2295       add_subwindow(a = Badj_active = new BluebananaBAActive(plugin,this));
2296       add_subwindow(p = new BluebananaBAReset(this,tumbler_col2_w));
2297       s = Badj_slider = new BluebananaBASlider(plugin,this,slider_x,y,slider_w,row_h);
2298       break;
2299
2300     case 7:
2301
2302       add_subwindow(t0 = Hadj_readout = new BluebananaHAReadout(plugin,this,tumbler_text_ww));
2303       add_subwindow(a = Hadj_active = new BluebananaHAActive(plugin,this));
2304       add_subwindow(p = new BluebananaHAReset(this,tumbler_col2_w));
2305       s = Hadj_slider = new BluebananaHASlider(plugin,this,slider_x,y,slider_w,row_h);
2306       break;
2307
2308     case 8:
2309
2310       add_subwindow(t0 = Sadj_readout0 = new BluebananaSAReadout0(plugin,this,tumbler_text_ww));
2311       add_subwindow(t1 = Sadj_readout1 = new BluebananaSAReadout1(plugin,this,tumbler_text_ww));
2312       add_subwindow(t2 = Sadj_readout2 = new BluebananaSAReadout2(plugin,this,tumbler_text_ww));
2313
2314       add_subwindow(a = Sadj_active = new BluebananaSAActive(plugin,this));
2315       add_subwindow(p = new BluebananaSAReset(this,tumbler_col2_w));
2316       s = Sadj_slider = new BluebananaSASlider(plugin,this,slider_x,y,slider_w,row_h);
2317       break;
2318
2319     case 9:
2320
2321       add_subwindow(t0 = Vadj_readout0 = new BluebananaVAReadout0(plugin,this,tumbler_text_ww));
2322       add_subwindow(t1 = Vadj_readout1 = new BluebananaVAReadout1(plugin,this,tumbler_text_ww));
2323       add_subwindow(t2 = Vadj_readout2 = new BluebananaVAReadout2(plugin,this,tumbler_text_ww));
2324       add_subwindow(a = Vadj_active = new BluebananaVAActive(plugin,this));
2325       add_subwindow(p = new BluebananaVAReset(this,tumbler_col2_w));
2326       s = Vadj_slider = new BluebananaVASlider(plugin,this,slider_x,y,slider_w,row_h);
2327       break;
2328
2329     case 10:
2330
2331       add_subwindow(t0 = Oadj_readout = new BluebananaOAReadout(plugin,this,tumbler_text_ww));
2332       add_subwindow(a = Oadj_active = new BluebananaOAActive(plugin,this));
2333       add_subwindow(p = new BluebananaOAReset(this,tumbler_col2_w));
2334       s = Oadj_slider = new BluebananaOASlider(plugin,this,slider_x,y,slider_w,row_h);
2335       break;
2336
2337     case 11:
2338
2339       add_subwindow(t0 = Aadj_readout = new BluebananaAAReadout(plugin,this,tumbler_text_ww));
2340       add_subwindow(a = Aadj_active = new BluebananaAAActive(plugin,this));
2341       add_subwindow(p = new BluebananaAAReset(this,tumbler_col2_w));
2342       s = Aadj_slider = new BluebananaAASlider(plugin,this,slider_x,y,slider_w,row_h);
2343       break;
2344
2345     }
2346     add_subwindow(s);
2347
2348     if(a)a->reposition_window(label_x - padx - a->get_w(), y + (row_h-a->get_h())/2 + 1);
2349     if(l)l->reposition(label_x - l->get_w() - padx*2 - a->get_w(), y + (row_h-l->get_h())/2 + 1);
2350
2351     if(p){
2352       p->BC_SubWindow::reposition_window(tumbler_col2_x, y + (row_h-p->get_h())/2 + 1,
2353                                          MAX(tumbler_col2_w,picker_w),p->get_h());
2354
2355       // work around bug; the reposition step does not fully redraw the button
2356       p->draw_face();
2357     }
2358
2359     if(t0)t0->reposition_window(tumbler_col1_x,
2360                                 y + (row_h-tumbler_h)/2 + 1);
2361
2362     if(t1)t1->reposition_window(tumbler_col1_x+tumbler_ww,
2363                                 y + (row_h-tumbler_h)/2 + 1);
2364
2365     if(t2)t2->reposition_window(tumbler_col1_x+tumbler_ww*2+padx*2+(tumbler_ww-t2->get_w())/2,
2366                                 y + (row_h-tumbler_h)/2 + 1);
2367
2368
2369     s->update();
2370
2371     y+=row_adv;
2372     if(i==3){
2373       y+=row_adv/3;
2374
2375       BC_Title *l = new BC_Title(xmargin,y,_("Color Adjustment"));
2376       BC_Title *l2 = new BC_Title(-1,-1,_(" Filter Active"));
2377       add_subwindow(l);
2378       add_subwindow(l2);
2379       add_subwindow(active = new BluebananaActive(plugin,this));
2380
2381       int x0 = get_w()-xmargin-mark->get_w();
2382       active->reposition_window(x0,y-(active->get_h()-l->get_h())/2);
2383       x0 -= padx+l2->get_w();
2384       l2->reposition_window(x0,y);
2385       x0 -= padx*2;
2386       set_color(get_resources()->default_text_color);
2387       draw_line(xmargin+l->get_w()+padx, y+l->get_h()*.5, x0, y+l->get_h()*.5);
2388
2389       y += l->get_h()*(row_padding+1.);
2390       y += row_adv/3;
2391     }
2392
2393
2394     if(i==6 || i==9){
2395       y+=row_adv/4;
2396
2397       set_color((s->dimtextcolor + get_resources()->default_text_color)/2);
2398       draw_line(slider_x+20, y+l->get_h()*.5, tumbler_col2_x-30, y+l->get_h()*.5);
2399
2400       y += l->get_h()*(row_padding+1.);
2401       y += row_adv/4;
2402     }
2403
2404
2405   }
2406   y += row_adv/2-4;
2407
2408   plugin->update_lookups(0);
2409   do_render=1;
2410
2411   resize_window(get_w(),y);
2412   show_window();
2413   reposition_window(windowx,windowy,get_w(),y);
2414   leave_config_change(); // also forces render
2415   plugin->server->mwindow->sync_parameters();
2416 }
2417
2418 int BluebananaWindow::close_event(){
2419   set_done(1);
2420   return 1;
2421 }
2422
2423 // adds one to config push refcount
2424 // updates any internal state immediately
2425 void BluebananaWindow::enter_config_change(){
2426   config_refcount++;
2427   if(!config_change && !plugin->update_cache.equivalent(plugin->config)){
2428     config_change=1;
2429   }
2430   plugin->update_lookups(0);
2431 }
2432
2433 // decrements one from config push refcount.  If refcount drops to
2434 // zero, pushes new config up to application
2435
2436 // also compresses events; waits 184ms for new events before pushing
2437 // configuration changes
2438 void BluebananaWindow::commit_config_change(){
2439   if(--config_refcount==0){
2440     if(config_change){
2441       config_change=0;
2442       config_produce++;
2443       config_pending=1;
2444       set_repeat(97);
2445     }
2446     render();
2447   }
2448 }
2449
2450 // decrements one from config push refcount.  Does not push config up
2451 // to application when refcount drops to zero (used to wrap update
2452 // requests coming from the application, not user-initiated state
2453 // changes)
2454 void BluebananaWindow::leave_config_change(){
2455   config_change=0;
2456   plugin->update_cache.copy_from(plugin->config);
2457   if(--config_refcount==0){
2458     render();
2459   }
2460 }
2461
2462 int BluebananaWindow::flush_config_change(){
2463   unset_repeat(97);
2464   if(config_pending){
2465     config_pending=0;
2466     plugin->update_cache.copy_from(plugin->config);
2467     plugin->send_configure_change();
2468   }
2469   config_consume=config_produce;
2470   return 0;
2471 }
2472
2473 int BluebananaWindow::repeat_event(int64_t d){
2474   if(d==97){
2475     if(config_consume!=config_produce)
2476       flush_config_change();
2477   }
2478   if(!plugin->server->plugin->on) return 0;
2479   if(d==207){
2480
2481     /* if background render is active and we're showing the zebra, mark
2482        the current frame uncached so that we can push zebra changes */
2483     if(plugin->config.mark && plugin->server->mwindow->brender)
2484       plugin->server->mwindow->brender->set_video_map(plugin->source_position, BRender::SCANNED);
2485
2486     /* push update request without an EDL update */
2487     plugin->server->mwindow->sync_parameters();
2488   }
2489   return 0;
2490 }
2491
2492 /* engine -> gui update; don't allow any EDL pushes */
2493 void BluebananaWindow::update(){
2494
2495   // called to suppress configuration pushes
2496   enter_config_change();
2497
2498   // full configuration recompute and redraw
2499   Hsel_slider->update();
2500   Ssel_slider->update();
2501   Vsel_slider->update();
2502   Fsel_slider->update();
2503   Hadj_slider->update();
2504   Sadj_slider->update();
2505   Vadj_slider->update();
2506   Radj_slider->update();
2507   Gadj_slider->update();
2508   Badj_slider->update();
2509   Oadj_slider->update();
2510   Aadj_slider->update();
2511
2512   active->update();
2513   mark->update();
2514   use_mask->update();
2515   capture_mask->update();
2516   invert_selection->update();
2517
2518   Hsel_active->update();
2519   Ssel_active->update();
2520   Vsel_active->update();
2521   Fsel_active->update();
2522
2523   Hadj_active->update();
2524   Sadj_active->update();
2525   Vadj_active->update();
2526   Radj_active->update();
2527   Gadj_active->update();
2528   Badj_active->update();
2529   Oadj_active->update();
2530   Aadj_active->update();
2531
2532   // called to release configuration without pushing
2533   leave_config_change();
2534 }
2535
2536 void BluebananaWindow::render(){
2537   if(do_render){
2538     Hsel_slider->render();
2539     Ssel_slider->render();
2540     Vsel_slider->render();
2541     Fsel_slider->render();
2542     Hadj_slider->render();
2543     Sadj_slider->render();
2544     Vadj_slider->render();
2545     Radj_slider->render();
2546     Gadj_slider->render();
2547     Badj_slider->render();
2548     Oadj_slider->render();
2549     Aadj_slider->render();
2550   }
2551 }
2552
2553 void BluebananaWindow::update_histograms(BluebananaMain *plugin){
2554   int w = plugin->frame->get_w();
2555   int h = plugin->frame->get_h();
2556
2557   if(Radj_slider)Radj_slider->update_histogram(plugin->red_histogram,0,0,0,w*h);
2558   if(Gadj_slider)Gadj_slider->update_histogram(plugin->green_histogram,0,0,0,w*h);
2559   if(Badj_slider)Badj_slider->update_histogram(plugin->blue_histogram,0,0,0,w*h);
2560
2561   if(Hadj_slider)
2562     Hadj_slider->update_histogram(plugin->hue_histogram,
2563                                   plugin->hue_histogram_red,
2564                                   plugin->hue_histogram_green,
2565                                   plugin->hue_histogram_blue,w*h);
2566
2567   if(Sadj_slider)
2568     Sadj_slider->update_histogram(plugin->sat_histogram,
2569                                   plugin->sat_histogram_red,
2570                                   plugin->sat_histogram_green,
2571                                   plugin->sat_histogram_blue,w*h);
2572
2573   if(Vadj_slider)
2574     Vadj_slider->update_histogram(plugin->value_histogram,
2575                                   plugin->value_histogram_red,
2576                                   plugin->value_histogram_green,
2577                                   plugin->value_histogram_blue,w*h);
2578
2579 }