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