grab stable branch
[synfig.git] / synfig-studio / tags / stable / src / gtkmm / dialog_setup.cpp
1 /* === S I N F G =========================================================== */
2 /*!     \file dialog_setup.cpp
3 **      \brief Template File
4 **
5 **      $Id: dialog_setup.cpp,v 1.1.1.1 2005/01/07 03:34:36 darco Exp $
6 **
7 **      \legal
8 **      Copyright (c) 2002 Robert B. Quattlebaum Jr.
9 **
10 **      This software and associated documentation
11 **      are CONFIDENTIAL and PROPRIETARY property of
12 **      the above-mentioned copyright holder.
13 **
14 **      You may not copy, print, publish, or in any
15 **      other way distribute this software without
16 **      a prior written agreement with
17 **      the copyright holder.
18 **      \endlegal
19 */
20 /* ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #ifdef USING_PCH
25 #       include "pch.h"
26 #else
27 #ifdef HAVE_CONFIG_H
28 #       include <config.h>
29 #endif
30
31 #include "dialog_setup.h"
32 #include "app.h"
33 #include <gtkmm/scale.h>
34 #include <gtkmm/table.h>
35 #include <gtkmm/frame.h>
36 #include <gtkmm/notebook.h>
37 #include <gtkmm/spinbutton.h>
38 #include "widget_enum.h"
39
40 #include <ETL/stringf>
41 #include <ETL/misc>
42 #endif
43
44 /* === U S I N G =========================================================== */
45
46 using namespace std;
47 using namespace etl;
48 using namespace sinfg;
49 using namespace studio;
50
51 /* === M A C R O S ========================================================= */
52
53 /* === G L O B A L S ======================================================= */
54
55 /* === P R O C E D U R E S ================================================= */
56
57 /* === M E T H O D S ======================================================= */
58
59 Dialog_Setup::Dialog_Setup():
60         Dialog(_("SINFG Studio Setup"),false,true),
61         adj_gamma_r(2.2,0.1,3.0,0.025,0.025,0.025),
62         adj_gamma_g(2.2,0.1,3.0,0.025,0.025,0.025),
63         adj_gamma_b(2.2,0.1,3.0,0.025,0.025,0.025),
64         adj_recent_files(15,1,50,1,1,1),
65         adj_undo_depth(100,10,5000,1,1,1),
66         toggle_use_colorspace_gamma(_("Visually Linear Color Selection"))
67 {
68         // Setup the buttons
69
70         Gtk::Button *ok_button(manage(new class Gtk::Button(Gtk::StockID("gtk-ok"))));
71         ok_button->show();
72         add_action_widget(*ok_button,2);
73         ok_button->signal_clicked().connect(sigc::mem_fun(*this, &Dialog_Setup::on_ok_pressed));
74
75         Gtk::Button *apply_button(manage(new class Gtk::Button(Gtk::StockID("gtk-apply"))));
76         apply_button->show();
77         add_action_widget(*apply_button,1);
78         apply_button->signal_clicked().connect(sigc::mem_fun(*this, &Dialog_Setup::on_apply_pressed));
79
80         Gtk::Button *cancel_button(manage(new class Gtk::Button(Gtk::StockID("gtk-close"))));
81         cancel_button->show();
82         add_action_widget(*cancel_button,0);
83         cancel_button->signal_clicked().connect(sigc::mem_fun(*this, &Dialog_Setup::hide));
84
85
86         // Notebook
87         Gtk::Notebook *notebook=manage(new class Gtk::Notebook());
88         get_vbox()->pack_start(*notebook);
89
90
91         // Gamma
92         Gtk::Table *gamma_table=manage(new Gtk::Table(2,2,false));
93         notebook->append_page(*gamma_table,_("Gamma"));
94         //gamma_frame->add(*gamma_table);
95         
96         gamma_table->attach(gamma_pattern, 0, 2, 0, 1, Gtk::EXPAND, Gtk::SHRINK|Gtk::FILL, 0, 0);       
97
98         Gtk::HScale* scale_gamma_r(manage(new Gtk::HScale(adj_gamma_r)));
99         gamma_table->attach(*manage(new Gtk::Label(_("Red"))), 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); 
100         gamma_table->attach(*scale_gamma_r, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);    
101         adj_gamma_r.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_gamma_r_change));
102         
103         Gtk::HScale* scale_gamma_g(manage(new Gtk::HScale(adj_gamma_g)));
104         gamma_table->attach(*manage(new Gtk::Label(_("Green"))), 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);       
105         gamma_table->attach(*scale_gamma_g, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);    
106         adj_gamma_g.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_gamma_g_change));
107
108         Gtk::HScale* scale_gamma_b(manage(new Gtk::HScale(adj_gamma_b)));
109         gamma_table->attach(*manage(new Gtk::Label(_("Blue"))), 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);        
110         gamma_table->attach(*scale_gamma_b, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);    
111         adj_gamma_b.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_gamma_b_change));
112
113         gamma_table->attach(*manage(new Gtk::Label(_("Black Level"))), 0, 1, 4, 5, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); 
114         gamma_table->attach(black_level_selector, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);      
115         black_level_selector.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_black_level_change));
116
117         //gamma_table->attach(*manage(new Gtk::Label(_("Red-Blue Level"))), 0, 1, 5, 6, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);    
118         //gamma_table->attach(red_blue_level_selector, 1, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); 
119         //red_blue_level_selector.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_red_blue_level_change));
120
121
122         // Misc
123         Gtk::Table *misc_table=manage(new Gtk::Table(2,2,false));
124         notebook->append_page(*misc_table,_("Misc."));
125         
126         // Misc - Timestamp
127         timestamp_menu=manage(new class Gtk::Menu());
128         misc_table->attach(*manage(new Gtk::Label(_("Timestamp"))), 0, 1, 0, 1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);    
129         misc_table->attach(timestamp_optionmenu, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);       
130
131 #define ADD_TIMESTAMP(desc,x)   \
132         timestamp_menu->items().push_back(      \
133                 Gtk::Menu_Helpers::MenuElem(    \
134                         desc,   \
135                         sigc::bind(     \
136                                 sigc::mem_fun(  \
137                                         *this,  \
138                                         &studio::Dialog_Setup::set_time_format  \
139                                 ),      \
140                                 x       \
141                         )       \
142                 )       \
143         );
144         ADD_TIMESTAMP("HH:MM:SS.FF",Time::FORMAT_VIDEO);
145         ADD_TIMESTAMP("(HHh MMm SSs) FFf",Time::FORMAT_NORMAL);
146         ADD_TIMESTAMP("(HHhMMmSSs)FFf",Time::FORMAT_NORMAL|Time::FORMAT_NOSPACES);
147         ADD_TIMESTAMP("HHh MMm SSs FFf",Time::FORMAT_NORMAL|Time::FORMAT_FULL);
148         ADD_TIMESTAMP("HHhMMmSSsFFf",Time::FORMAT_NORMAL|Time::FORMAT_NOSPACES|Time::FORMAT_FULL);
149
150         timestamp_optionmenu.set_menu(*timestamp_menu);
151         
152 #undef ADD_TIMESTAMP
153
154         {
155                 ParamDesc param_desc;
156                 param_desc
157                         .set_hint("enum")
158                         .add_enum_value(Distance::SYSTEM_UNITS,"u",_("Units"))
159                         .add_enum_value(Distance::SYSTEM_PIXELS,"px",_("Pixels"))
160                         .add_enum_value(Distance::SYSTEM_POINTS,"pt",_("Points"))
161                         .add_enum_value(Distance::SYSTEM_INCHES,"in",_("Inches"))
162                         .add_enum_value(Distance::SYSTEM_METERS,"m",_("Meters"))
163                         .add_enum_value(Distance::SYSTEM_CENTIMETERS,"cm",_("Centimeters"))
164                         .add_enum_value(Distance::SYSTEM_MILLIMETERS,"mm",_("Millimeters"));
165
166                 widget_enum=manage(new Widget_Enum());
167                 widget_enum->set_param_desc(param_desc);
168
169                 misc_table->attach(*manage(new Gtk::Label(_("Unit System"))), 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);  
170                 misc_table->attach(*widget_enum, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);       
171         }
172
173         // Misc - recent files
174         Gtk::SpinButton* recent_files_spinbutton(manage(new Gtk::SpinButton(adj_recent_files,1,0)));
175         misc_table->attach(*manage(new Gtk::Label(_("Recent Files"))), 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0); 
176         misc_table->attach(*recent_files_spinbutton, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);   
177
178         // Misc - use_colorspace_gamma
179         misc_table->attach(toggle_use_colorspace_gamma, 0, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);        
180         
181         show_all_children();
182 }
183
184 Dialog_Setup::~Dialog_Setup()
185 {
186 }
187
188 void
189 Dialog_Setup::on_ok_pressed()
190 {
191     on_apply_pressed();
192         hide();
193 }
194
195 void
196 Dialog_Setup::on_apply_pressed()
197 {
198         App::gamma.set_all(1.0/adj_gamma_r.get_value(),1.0/adj_gamma_g.get_value(),1.0/adj_gamma_b.get_value(),black_level_selector.get_value(),red_blue_level_selector.get_value());
199
200         App::set_max_recent_files((int)adj_recent_files.get_value());   
201         
202         // Set the time format
203         App::set_time_format(get_time_format());
204         
205         // Set the use_colorspace_gamma flag
206         App::use_colorspace_gamma=toggle_use_colorspace_gamma.get_active();
207
208         App::distance_system=Distance::System(widget_enum->get_value());
209         
210         App::save_settings();
211 }
212
213 void
214 Dialog_Setup::on_gamma_r_change()
215 {
216         gamma_pattern.set_gamma_r(1.0/adj_gamma_r.get_value());
217         gamma_pattern.refresh();
218         gamma_pattern.queue_draw();
219 }
220
221 void
222 Dialog_Setup::on_gamma_g_change()
223 {
224         gamma_pattern.set_gamma_g(1.0/adj_gamma_g.get_value());
225         gamma_pattern.refresh();
226         gamma_pattern.queue_draw();
227 }
228
229 void
230 Dialog_Setup::on_gamma_b_change()
231 {
232         gamma_pattern.set_gamma_b(1.0/adj_gamma_b.get_value());
233         gamma_pattern.refresh();
234         gamma_pattern.queue_draw();
235 }
236
237 void
238 Dialog_Setup::on_black_level_change()
239 {
240         gamma_pattern.set_black_level(black_level_selector.get_value());
241         gamma_pattern.refresh();
242         gamma_pattern.queue_draw();
243 }
244
245 void
246 Dialog_Setup::on_red_blue_level_change()
247 {
248         gamma_pattern.set_red_blue_level(red_blue_level_selector.get_value());
249         gamma_pattern.refresh();
250         gamma_pattern.queue_draw();
251 }
252
253
254 void
255 Dialog_Setup::refresh()
256 {
257         adj_gamma_r.set_value(1.0/App::gamma.get_gamma_r());    
258         adj_gamma_g.set_value(1.0/App::gamma.get_gamma_g());    
259         adj_gamma_b.set_value(1.0/App::gamma.get_gamma_b());    
260         black_level_selector.set_value(App::gamma.get_black_level());
261         red_blue_level_selector.set_value(App::gamma.get_red_blue_level());
262         
263         // Refresh the temporary gamma
264         gamma_pattern.set_gamma_r(1.0/adj_gamma_r.get_value());
265         gamma_pattern.set_gamma_g(1.0/adj_gamma_g.get_value());
266         gamma_pattern.set_gamma_b(1.0/adj_gamma_b.get_value());
267         gamma_pattern.set_black_level(black_level_selector.get_value());
268         gamma_pattern.set_red_blue_level(red_blue_level_selector.get_value());
269         gamma_pattern.refresh();
270         
271         adj_recent_files.set_value(App::get_max_recent_files());
272         
273         // Refresh the time format
274         set_time_format(App::get_time_format());
275
276         widget_enum->set_value(App::distance_system);
277         
278         // Refresh the status of the use_colorspace_gamma flag
279         toggle_use_colorspace_gamma.set_active(App::use_colorspace_gamma);
280
281 }
282
283 GammaPattern::GammaPattern():
284         tile_w(80),
285         tile_h(80)
286 {
287         set_size_request(tile_w*4,tile_h*3);
288         signal_expose_event().connect(sigc::mem_fun(*this, &studio::GammaPattern::redraw));
289 }
290         
291 GammaPattern::~GammaPattern()
292 {
293 }
294
295 void
296 GammaPattern::refresh()
297 {
298         black[0].set_rgb_p(
299                 r_F32_to_F32(0.0),      
300                 g_F32_to_F32(0.0),      
301                 b_F32_to_F32(0.0)
302         );
303         white[0].set_rgb_p(
304                 r_F32_to_F32(1.0),      
305                 g_F32_to_F32(1.0),      
306                 b_F32_to_F32(1.0)
307         );
308         gray50[0].set_rgb_p(
309                 r_F32_to_F32(0.5),      
310                 g_F32_to_F32(0.5),      
311                 b_F32_to_F32(0.5)
312         );
313         gray25[0].set_rgb_p(
314                 r_F32_to_F32(0.25),     
315                 g_F32_to_F32(0.25),     
316                 b_F32_to_F32(0.25)
317         );
318
319         // Reds
320         black[1].set_rgb(black[0].get_red(),0,0);
321         gray25[1].set_rgb(gray25[0].get_red(),0,0);
322         gray50[1].set_rgb(gray50[0].get_red(),0,0);
323         white[1].set_rgb(white[0].get_red(),0,0);
324
325         // Greens
326         black[2].set_rgb(0,black[0].get_green(),0);
327         gray25[2].set_rgb(0,gray25[0].get_green(),0);
328         gray50[2].set_rgb(0,gray50[0].get_green(),0);
329         white[2].set_rgb(0,white[0].get_green(),0);
330
331         // blues
332         black[3].set_rgb(0,0,black[0].get_blue());
333         gray25[3].set_rgb(0,0,gray25[0].get_blue());
334         gray50[3].set_rgb(0,0,gray50[0].get_blue());
335         white[3].set_rgb(0,0,white[0].get_blue());
336 }
337
338 bool
339 GammaPattern::redraw(GdkEventExpose*bleh)
340 {
341         static const char hlines[] = { 3, 0 };
342
343         Glib::RefPtr<Gdk::GC> gc(Gdk::GC::create(get_window()));
344         
345         int i;
346         Gdk::Color trueblack("#000000");
347         
348         // 50% Pattern
349         for(i=0;i<4;i++)
350         {
351                 gc->set_rgb_fg_color(black[i]);
352                 get_window()->draw_rectangle(gc, true, i*tile_w, 0, tile_w, tile_h);
353         
354                 gc->set_stipple(Gdk::Bitmap::create(hlines,2,2));
355                 gc->set_fill(Gdk::STIPPLED);
356                 gc->set_rgb_fg_color(white[i]);
357                 get_window()->draw_rectangle(gc, true, i*tile_w, 0, tile_w, tile_h);
358         
359                 gc->set_fill(Gdk::SOLID);
360                 gc->set_rgb_fg_color(gray50[i]);
361         
362                 get_window()->draw_rectangle(gc, true, i*tile_w+tile_w/4, tile_h/4, tile_w-tile_w/2, tile_h-tile_h/2);
363         }
364
365         // 25% Pattern
366         for(i=0;i<4;i++)
367         {
368                 gc->set_rgb_fg_color(black[i]);
369                 get_window()->draw_rectangle(gc, true, i*tile_w, tile_h, tile_w, tile_h);
370         
371                 gc->set_stipple(Gdk::Bitmap::create(hlines,2,2));
372                 gc->set_fill(Gdk::STIPPLED);
373                 gc->set_rgb_fg_color(gray50[i]);
374                 get_window()->draw_rectangle(gc, true, i*tile_w, tile_h, tile_w, tile_h);
375         
376                 gc->set_fill(Gdk::SOLID);
377                 gc->set_rgb_fg_color(gray25[i]);
378         
379                 get_window()->draw_rectangle(gc, true, i*tile_w+tile_w/4, tile_h+tile_h/4, tile_w-tile_w/2, tile_h-tile_h/2);
380         }
381
382         // Black-level Pattern
383         gc->set_rgb_fg_color(trueblack);
384         get_window()->draw_rectangle(gc, true, 0, tile_h*2, tile_w*4, tile_h);
385         gc->set_fill(Gdk::SOLID);
386         for(i=0;i<4;i++)
387         {
388                 gc->set_rgb_fg_color(black[i]);
389         
390                 get_window()->draw_rectangle(gc, true, i*tile_w+tile_w/4, tile_h*2+tile_h/4, tile_w-tile_w/2, tile_h-tile_h/2);
391         }
392
393         return true;
394 }
395
396         
397 BlackLevelSelector::BlackLevelSelector()
398 {
399         set_size_request(-1,24);        
400         signal_expose_event().connect(sigc::mem_fun(*this, &studio::BlackLevelSelector::redraw));
401         
402         add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
403         add_events(Gdk::BUTTON1_MOTION_MASK);
404         add_events(Gdk::BUTTON1_MOTION_MASK);
405 }
406
407 BlackLevelSelector::~BlackLevelSelector()
408 {
409 }
410
411 bool
412 BlackLevelSelector::redraw(GdkEventExpose*bleh)
413 {
414         const int w(get_width()),h(get_height());
415
416         Gdk::Color color;
417
418         Glib::RefPtr<Gdk::GC> gc(Gdk::GC::create(get_window()));
419
420         int i;
421         
422         // Draw the gradient
423         for(i=0;i<w;i++)
424         {
425                 color.set_rgb(i*65536/w,i*65536/w,i*65536/w);
426                 
427                 gc->set_rgb_fg_color(color);
428                 get_window()->draw_rectangle(gc, true, i, 0, 1, h);
429         }
430                 
431         // Draw a frame
432         gc->set_rgb_fg_color(Gdk::Color("#000000"));
433         get_window()->draw_rectangle(gc, false, 0, 0, w-1, h-1);
434
435         // Draw the position of the current value
436         i=(int)(level*w+0.5);
437         gc->set_rgb_fg_color(Gdk::Color("#ff0000"));
438         get_window()->draw_rectangle(gc, true, i, 1, 1, h-1);
439
440         // Print out the value
441         Glib::RefPtr<Pango::Layout> layout(Pango::Layout::create(get_pango_context()));         
442         layout->set_text(etl::strprintf("%0.01f%%",level*100.0f));
443         layout->set_alignment(Pango::ALIGN_CENTER);
444         gc->set_rgb_fg_color(Gdk::Color("#a00000"));
445         get_window()->draw_layout(gc, w/2, 4, layout);
446
447         return true;
448 }
449
450
451
452 bool
453 BlackLevelSelector::on_event(GdkEvent *event)
454 {
455         int x(round_to_int(event->button.x));
456         //int y(round_to_int(event->button.y));
457
458     switch(event->type)
459     {
460         case GDK_MOTION_NOTIFY:
461                 level=(float)x/(float)get_width();
462                 if(level<0.0f)level=0.0f;
463                 if(level>1.0f)level=1.0f;
464                 signal_value_changed_();
465                 queue_draw();
466                 return true;
467                 break;
468         case GDK_BUTTON_PRESS:
469         case GDK_BUTTON_RELEASE:
470                 if(event->button.button==1)
471                 {
472                         level=(float)x/(float)get_width();
473                         if(level<0.0f)level=0.0f;
474                         if(level>1.0f)level=1.0f;
475                         signal_value_changed_();
476                         queue_draw();
477                         return true;
478                 }
479                 break;
480         default:
481                 break;
482         }
483
484         return false;
485 }
486
487
488 void
489 Dialog_Setup::set_time_format(Time::Format x)
490 {
491         time_format=x;
492         if(x<=Time::FORMAT_VIDEO)
493                 timestamp_optionmenu.set_history(0);
494         else
495         {
496                 if(x==(Time::FORMAT_NOSPACES|Time::FORMAT_FULL))
497                         timestamp_optionmenu.set_history(4);
498                 else if(x==(Time::FORMAT_FULL))
499                         timestamp_optionmenu.set_history(3);
500                 else if(x==(Time::FORMAT_NOSPACES))
501                         timestamp_optionmenu.set_history(2);
502                 else
503                         timestamp_optionmenu.set_history(1);
504         }
505 }
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522 RedBlueLevelSelector::RedBlueLevelSelector()
523 {
524         set_size_request(-1,24);        
525         signal_expose_event().connect(sigc::mem_fun(*this, &studio::RedBlueLevelSelector::redraw));
526         
527         add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
528         add_events(Gdk::BUTTON1_MOTION_MASK);
529         add_events(Gdk::BUTTON1_MOTION_MASK);
530 }
531
532 RedBlueLevelSelector::~RedBlueLevelSelector()
533 {
534 }
535
536 bool
537 RedBlueLevelSelector::redraw(GdkEventExpose*bleh)
538 {
539         const int w(get_width()),h(get_height());
540
541         Gdk::Color color;
542
543         Glib::RefPtr<Gdk::GC> gc(Gdk::GC::create(get_window()));
544
545         int i;
546         
547         // Draw the gradient
548         for(i=0;i<w;i++)
549         {
550                 float red_blue(((float(i)/float(w)+0.5f)-1.0f)/2.0f+1.0f);
551                 float blue_red(2.0f-(red_blue));
552                 if(red_blue>1.0f)red_blue=1.0f;
553                 if(blue_red>1.0f)blue_red=1.0f;
554                         
555                 color.set_rgb(
556                         round_to_int(min(red_blue,1.0f)*65535),
557                         round_to_int(sqrt(min(red_blue,blue_red))*65535),
558                         round_to_int(min(blue_red,1.0f)*65535)
559                 );
560                 
561                 gc->set_rgb_fg_color(color);
562                 get_window()->draw_rectangle(gc, true, i, 0, 1, h);
563         }
564                 
565         // Draw a frame
566         gc->set_rgb_fg_color(Gdk::Color("#000000"));
567         get_window()->draw_rectangle(gc, false, 0, 0, w-1, h-1);
568
569         // Draw the position of the current value
570         i=(int)(((level-1.0f)*2.0f+1.0f-0.5f)*w+0.5);
571         gc->set_rgb_fg_color(Gdk::Color("#00ff00"));
572         get_window()->draw_rectangle(gc, true, i, 1, 1, h-1);
573
574         // Print out the value
575         Glib::RefPtr<Pango::Layout> layout(Pango::Layout::create(get_pango_context()));         
576         layout->set_text(etl::strprintf("%0.02f",level));
577         layout->set_alignment(Pango::ALIGN_CENTER);
578         gc->set_rgb_fg_color(Gdk::Color("#a00000"));
579         get_window()->draw_layout(gc, w/2, 4, layout);
580
581         return true;
582 }
583
584
585
586 bool
587 RedBlueLevelSelector::on_event(GdkEvent *event)
588 {
589         int x(round_to_int(event->button.x));
590         //int y(round_to_int(event->button.y));
591
592     switch(event->type)
593     {
594         case GDK_MOTION_NOTIFY:
595                 level=(((float)(x)/(float)get_width()+0.5)-1.0f)/2.0f+1.0f;
596                 if(level<0.5f)level=0.5f;
597                 if(level>1.5f)level=1.5f;
598                 signal_value_changed_();
599                 queue_draw();
600                 return true;
601                 break;
602         case GDK_BUTTON_PRESS:
603         case GDK_BUTTON_RELEASE:
604                 if(event->button.button==1)
605                 {
606                         level=(((float)(x)/(float)get_width()+0.5)-1.0f)/2.0f+1.0f;
607                         if(level<0.5f)level=0.5f;
608                         if(level>1.5f)level=1.5f;
609                         signal_value_changed_();
610                         queue_draw();
611                         return true;
612                 }
613                 break;
614         default:
615                 break;
616         }
617
618         return false;
619 }