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