9b7dcd4ad4510be828645506b12c1c28fd4bce13
[synfig.git] /
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 **      Copyright (c) 2007, 2008 Chris Moore
10 **  Copyright (c) 2008 Carlos López
11 **
12 **      This package is free software; you can redistribute it and/or
13 **      modify it under the terms of the GNU General Public License as
14 **      published by the Free Software Foundation; either version 2 of
15 **      the License, or (at your option) any later version.
16 **
17 **      This package is distributed in the hope that it will be useful,
18 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
19 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 **      General Public License for more details.
21 **      \endlegal
22 */
23 /* ========================================================================= */
24
25 /* === H E A D E R S ======================================================= */
26
27 #ifdef USING_PCH
28 #       include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 #       include <config.h>
32 #endif
33
34 #include "dialog_setup.h"
35 #include "app.h"
36 #include <gtkmm/scale.h>
37 #include <gtkmm/table.h>
38 #include <gtkmm/frame.h>
39 #include <gtkmm/notebook.h>
40 #include <gtkmm/spinbutton.h>
41 #include "widget_enum.h"
42 #include "autorecover.h"
43
44 #include <ETL/stringf>
45 #include <ETL/misc>
46 #include "general.h"
47
48 #endif
49
50 /* === U S I N G =========================================================== */
51
52 using namespace std;
53 using namespace etl;
54 using namespace synfig;
55 using namespace studio;
56
57 /* === M A C R O S ========================================================= */
58
59 /* === G L O B A L S ======================================================= */
60
61 /* === P R O C E D U R E S ================================================= */
62
63 /* === M E T H O D S ======================================================= */
64
65 static void
66 attach_label(Gtk::Table *table, String str, guint col, guint xpadding, guint ypadding)
67 {
68         Gtk::Label* label(manage(new Gtk::Label((str + ":").c_str())));
69         label->set_alignment(Gtk::ALIGN_RIGHT, Gtk::ALIGN_CENTER);
70         table->attach(*label, 0, 1, col, col+1, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
71 }
72
73 Dialog_Setup::Dialog_Setup():
74         Dialog(_("Synfig Studio Setup"),false,true),
75         adj_gamma_r(2.2,0.1,3.0,0.025,0.025,0.025),
76         adj_gamma_g(2.2,0.1,3.0,0.025,0.025,0.025),
77         adj_gamma_b(2.2,0.1,3.0,0.025,0.025,0.025),
78         adj_recent_files(15,1,50,1,1,0),
79         adj_undo_depth(100,10,5000,1,1,1),
80         toggle_use_colorspace_gamma(_("Visually Linear Color Selection")),
81 #ifdef SINGLE_THREADED
82         toggle_single_threaded(_("Use Only a Single Thread")),
83 #endif
84         toggle_restrict_radius_ducks(_("Restrict Real-Valued Ducks to Top Right Quadrant")),
85         adj_pref_x_size(480,1,10000,1,10,0),
86         adj_pref_y_size(270,1,10000,1,10,0)
87         
88         {
89         // Setup the buttons
90
91         Gtk::Button *ok_button(manage(new class Gtk::Button(Gtk::StockID("gtk-ok"))));
92         ok_button->show();
93         add_action_widget(*ok_button,2);
94         ok_button->signal_clicked().connect(sigc::mem_fun(*this, &Dialog_Setup::on_ok_pressed));
95
96         Gtk::Button *apply_button(manage(new class Gtk::Button(Gtk::StockID("gtk-apply"))));
97         apply_button->show();
98         add_action_widget(*apply_button,1);
99         apply_button->signal_clicked().connect(sigc::mem_fun(*this, &Dialog_Setup::on_apply_pressed));
100
101         Gtk::Button *cancel_button(manage(new class Gtk::Button(Gtk::StockID("gtk-close"))));
102         cancel_button->show();
103         add_action_widget(*cancel_button,0);
104         cancel_button->signal_clicked().connect(sigc::mem_fun(*this, &Dialog_Setup::hide));
105
106
107         // Notebook
108         Gtk::Notebook *notebook=manage(new class Gtk::Notebook());
109         get_vbox()->pack_start(*notebook);
110
111
112         // Gamma
113         Gtk::Table *gamma_table=manage(new Gtk::Table(2,2,false));
114         notebook->append_page(*gamma_table,_("Gamma"));
115         //gamma_frame->add(*gamma_table);
116
117         gamma_table->attach(gamma_pattern, 0, 2, 0, 1, Gtk::EXPAND, Gtk::SHRINK|Gtk::FILL, 0, 0);
118
119         Gtk::HScale* scale_gamma_r(manage(new Gtk::HScale(adj_gamma_r)));
120         gamma_table->attach(*manage(new Gtk::Label(_("Red"))), 0, 1, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
121         gamma_table->attach(*scale_gamma_r, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
122         adj_gamma_r.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_gamma_r_change));
123
124         Gtk::HScale* scale_gamma_g(manage(new Gtk::HScale(adj_gamma_g)));
125         gamma_table->attach(*manage(new Gtk::Label(_("Green"))), 0, 1, 2, 3, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
126         gamma_table->attach(*scale_gamma_g, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
127         adj_gamma_g.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_gamma_g_change));
128
129         Gtk::HScale* scale_gamma_b(manage(new Gtk::HScale(adj_gamma_b)));
130         gamma_table->attach(*manage(new Gtk::Label(_("Blue"))), 0, 1, 3, 4, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
131         gamma_table->attach(*scale_gamma_b, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
132         adj_gamma_b.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_gamma_b_change));
133
134         gamma_table->attach(*manage(new Gtk::Label(_("Black Level"))), 0, 1, 4, 5, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
135         gamma_table->attach(black_level_selector, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
136         black_level_selector.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_black_level_change));
137
138         //gamma_table->attach(*manage(new Gtk::Label(_("Red-Blue Level"))), 0, 1, 5, 6, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
139         //gamma_table->attach(red_blue_level_selector, 1, 2, 5, 6, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, 0, 0);
140         //red_blue_level_selector.signal_value_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_red_blue_level_change));
141
142
143         // Misc
144         Gtk::Table *misc_table=manage(new Gtk::Table(2,2,false));
145         notebook->append_page(*misc_table,_("Misc."));
146
147         int xpadding(8), ypadding(8);
148
149         // Misc - Timestamp
150         timestamp_menu=manage(new class Gtk::Menu());
151         attach_label(misc_table, _("Timestamp"), 0, xpadding, ypadding);
152         misc_table->attach(timestamp_optionmenu, 1, 2, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
153
154 #define ADD_TIMESTAMP(desc,x)                                                                   \
155         timestamp_menu->items().push_back(                                                      \
156                 Gtk::Menu_Helpers::MenuElem(                                                    \
157                         desc,                                                                                           \
158                         sigc::bind(                                                                                     \
159                                 sigc::mem_fun(                                                                  \
160                                         *this,                                                                          \
161                                         &studio::Dialog_Setup::set_time_format),        \
162                                 x)));
163         ADD_TIMESTAMP("HH:MM:SS.FF",            Time::FORMAT_VIDEO      );
164         ADD_TIMESTAMP("(HHh MMm SSs) FFf",      Time::FORMAT_NORMAL     );
165         ADD_TIMESTAMP("(HHhMMmSSs)FFf",         Time::FORMAT_NORMAL     | Time::FORMAT_NOSPACES );
166         ADD_TIMESTAMP("HHh MMm SSs FFf",        Time::FORMAT_NORMAL     | Time::FORMAT_FULL             );
167         ADD_TIMESTAMP("HHhMMmSSsFFf",           Time::FORMAT_NORMAL     | Time::FORMAT_NOSPACES | Time::FORMAT_FULL);
168         ADD_TIMESTAMP("FFf",                            Time::FORMAT_FRAMES );
169
170         timestamp_optionmenu.set_menu(*timestamp_menu);
171
172 #undef ADD_TIMESTAMP
173
174         {
175                 ParamDesc param_desc;
176                 param_desc
177                         .set_hint("enum")
178                         .add_enum_value(Distance::SYSTEM_UNITS,"u",_("Units"))
179                         .add_enum_value(Distance::SYSTEM_PIXELS,"px",_("Pixels"))
180                         .add_enum_value(Distance::SYSTEM_POINTS,"pt",_("Points"))
181                         .add_enum_value(Distance::SYSTEM_INCHES,"in",_("Inches"))
182                         .add_enum_value(Distance::SYSTEM_METERS,"m",_("Meters"))
183                         .add_enum_value(Distance::SYSTEM_CENTIMETERS,"cm",_("Centimeters"))
184                         .add_enum_value(Distance::SYSTEM_MILLIMETERS,"mm",_("Millimeters"));
185
186                 widget_enum=manage(new Widget_Enum());
187                 widget_enum->set_param_desc(param_desc);
188
189                 attach_label(misc_table, _("Unit System"), 1, xpadding, ypadding);
190                 misc_table->attach(*widget_enum, 1, 2, 1, 2, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
191         }
192
193         // Misc - recent files
194         Gtk::SpinButton* recent_files_spinbutton(manage(new Gtk::SpinButton(adj_recent_files,1,0)));
195         attach_label(misc_table, _("Recent Files"), 2, xpadding, ypadding);
196         misc_table->attach(*recent_files_spinbutton, 1, 2, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
197
198         // Misc - use_colorspace_gamma
199         misc_table->attach(toggle_use_colorspace_gamma, 0, 2, 7, 8, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
200
201 #ifdef SINGLE_THREADED
202         // Misc - single_threaded
203         misc_table->attach(toggle_single_threaded, 0, 2, 9, 10, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
204 #endif
205
206         // Misc - auto backup interval
207         attach_label(misc_table, _("Auto Backup Interval (0 to disable)"), 3, xpadding, ypadding);
208         misc_table->attach(auto_backup_interval, 1, 2, 3, 4, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
209
210         // Misc - restrict_radius_ducks
211         misc_table->attach(toggle_restrict_radius_ducks, 0, 2, 8, 9, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
212
213         // Misc - browser_command
214         attach_label(misc_table, _("Browser Command"), 4, xpadding, ypadding);
215         misc_table->attach(textbox_browser_command, 1, 2, 4, 5, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
216
217         // Document
218         Gtk::Table *document_table=manage(new Gtk::Table(2,4,false));
219         notebook->append_page(*document_table,_("Document"));
220
221         // Document - Preferred file name prefix
222         attach_label(document_table, _("New Document filename prefix"), 0, xpadding, ypadding);
223         document_table->attach(textbox_custom_filename_prefix, 1, 4, 0, 1, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
224         tooltips_.set_tip(textbox_custom_filename_prefix,_("File name prefix for the new created document"));
225
226         // Document - New Document X size
227         Gtk::SpinButton* pref_x_size_spinbutton(manage(new Gtk::SpinButton(adj_pref_x_size,1,0)));
228         attach_label(document_table,_("New Document X size"),1, xpadding, ypadding);
229         document_table->attach(*pref_x_size_spinbutton, 1, 2, 1, 2,Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding); 
230         tooltips_.set_tip(*pref_x_size_spinbutton,_("Width in pixels of the new created document"));
231         
232         // Document - New Document Y size
233         Gtk::SpinButton* pref_y_size_spinbutton(manage(new Gtk::SpinButton(adj_pref_y_size,1,0)));
234         attach_label(document_table,_("New Document Y size"),2, xpadding, ypadding);
235         document_table->attach(*pref_y_size_spinbutton, 1, 2, 2, 3,Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding); 
236         tooltips_.set_tip(*pref_y_size_spinbutton,_("High in pixels of the new created document"));
237
238         //Document - Template for predefined sizes of canvases.
239         size_template_combo=Gtk::manage(new Gtk::ComboBoxText());
240         Gtk::Label* label(manage(new Gtk::Label(_("Predefined Resolutions:"))));
241         label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER);
242         document_table->attach(*label, 2, 3, 1, 2, Gtk::SHRINK|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
243         document_table->attach(*size_template_combo,2, 3, 2, 3, Gtk::EXPAND|Gtk::FILL, Gtk::SHRINK|Gtk::FILL, xpadding, ypadding);
244         size_template_combo->signal_changed().connect(sigc::mem_fun(*this,&studio::Dialog_Setup::on_size_template_combo_change));
245         size_template_combo->prepend_text(_("4096x3112 Full Aperture 4K"));
246         size_template_combo->prepend_text(_("2048x1556 Full Aperture Native 2K"));
247         size_template_combo->prepend_text(_("1920x1080 HDTV 1080p/i"));
248         size_template_combo->prepend_text(_("1280x720  HDTV 720p"));
249         size_template_combo->prepend_text(_("720x576   DVD PAL"));
250         size_template_combo->prepend_text(_("720x480   DVD NTSC"));
251         size_template_combo->prepend_text(_("720x540   Web 720x"));
252         size_template_combo->prepend_text(_("720x405   Web 720x HD"));
253         size_template_combo->prepend_text(_("640x480   Web 640x"));
254         size_template_combo->prepend_text(_("640x360   Web 640x HD"));
255         size_template_combo->prepend_text(_("480x360   Web 480x"));
256         size_template_combo->prepend_text(_("480x270   Web 480x HD"));
257         size_template_combo->prepend_text(_("360x270   Web 360x"));
258         size_template_combo->prepend_text(_("360x203   Web 360x HD"));
259         size_template_combo->prepend_text(DEFAULT_PREDEFINED_SIZE);
260
261         show_all_children();
262 }
263
264 Dialog_Setup::~Dialog_Setup()
265 {
266 }
267
268 void
269 Dialog_Setup::on_ok_pressed()
270 {
271     on_apply_pressed();
272         hide();
273 }
274
275 void
276 Dialog_Setup::on_apply_pressed()
277 {
278         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());
279
280         App::set_max_recent_files((int)adj_recent_files.get_value());
281
282         // Set the time format
283         App::set_time_format(get_time_format());
284
285         // Set the use_colorspace_gamma flag
286         App::use_colorspace_gamma=toggle_use_colorspace_gamma.get_active();
287
288 #ifdef SINGLE_THREADED
289         // Set the single_threaded flag
290         App::single_threaded=toggle_single_threaded.get_active();
291 #endif
292
293         // Set the auto backup interval
294         App::auto_recover->set_timeout(auto_backup_interval.get_value() * 1000);
295
296         App::distance_system=Distance::System(widget_enum->get_value());
297
298         // Set the restrict_radius_ducks flag
299         App::restrict_radius_ducks=toggle_restrict_radius_ducks.get_active();
300
301         // Set the browser_command textbox
302         App::browser_command=textbox_browser_command.get_text();
303
304         // Set the preferred file name prefix
305         App::custom_filename_prefix=textbox_custom_filename_prefix.get_text();
306
307         // Set the preferred new Document X dimension
308         App::preferred_x_size=int(adj_pref_x_size.get_value());
309
310         // Set the preferred new Document Y dimension
311         App::preferred_y_size=int(adj_pref_y_size.get_value());
312         
313         // Set the preferred Predefined size
314         App::predefined_size=size_template_combo->get_active_text();
315
316         App::save_settings();
317 }
318
319 void
320 Dialog_Setup::on_gamma_r_change()
321 {
322         gamma_pattern.set_gamma_r(1.0/adj_gamma_r.get_value());
323         gamma_pattern.refresh();
324         gamma_pattern.queue_draw();
325 }
326
327 void
328 Dialog_Setup::on_gamma_g_change()
329 {
330         gamma_pattern.set_gamma_g(1.0/adj_gamma_g.get_value());
331         gamma_pattern.refresh();
332         gamma_pattern.queue_draw();
333 }
334
335 void
336 Dialog_Setup::on_gamma_b_change()
337 {
338         gamma_pattern.set_gamma_b(1.0/adj_gamma_b.get_value());
339         gamma_pattern.refresh();
340         gamma_pattern.queue_draw();
341 }
342
343 void
344 Dialog_Setup::on_black_level_change()
345 {
346         gamma_pattern.set_black_level(black_level_selector.get_value());
347         gamma_pattern.refresh();
348         gamma_pattern.queue_draw();
349 }
350
351 void
352 Dialog_Setup::on_red_blue_level_change()
353 {
354         gamma_pattern.set_red_blue_level(red_blue_level_selector.get_value());
355         gamma_pattern.refresh();
356         gamma_pattern.queue_draw();
357 }
358
359 void
360 Dialog_Setup::on_size_template_combo_change()
361 {
362         String selection(size_template_combo->get_active_text());
363         if(selection==DEFAULT_PREDEFINED_SIZE) 
364         {
365                 return;
366         }
367         String::size_type locx=selection.find_first_of("x"); // here should be some comparison with string::npos
368         String::size_type locspace=selection.find_first_of(" ");
369         String x_size(selection.substr(0,locx));
370         String y_size(selection.substr(locx+1,locspace));
371         int x=atoi(x_size.c_str());
372         int y=atoi(y_size.c_str());
373         adj_pref_x_size.set_value(x);
374         adj_pref_y_size.set_value(y);
375         return;
376 }
377
378 void
379 Dialog_Setup::refresh()
380 {
381         // Refresh the temporary gamma; do this before adjusting the sliders,
382         // or variables will be used before their initialization.
383         gamma_pattern.set_gamma_r(App::gamma.get_gamma_r());
384         gamma_pattern.set_gamma_g(App::gamma.get_gamma_g());
385         gamma_pattern.set_gamma_b(App::gamma.get_gamma_b());
386         gamma_pattern.set_black_level(App::gamma.get_black_level());
387         gamma_pattern.set_red_blue_level(App::gamma.get_red_blue_level());
388
389         adj_gamma_r.set_value(1.0/App::gamma.get_gamma_r());
390         adj_gamma_g.set_value(1.0/App::gamma.get_gamma_g());
391         adj_gamma_b.set_value(1.0/App::gamma.get_gamma_b());
392         black_level_selector.set_value(App::gamma.get_black_level());
393         red_blue_level_selector.set_value(App::gamma.get_red_blue_level());
394
395         gamma_pattern.refresh();
396
397         adj_recent_files.set_value(App::get_max_recent_files());
398
399         // Refresh the time format
400         set_time_format(App::get_time_format());
401
402         widget_enum->set_value(App::distance_system);
403
404         // Refresh the status of the use_colorspace_gamma flag
405         toggle_use_colorspace_gamma.set_active(App::use_colorspace_gamma);
406
407 #ifdef SINGLE_THREADED
408         // Refresh the status of the single_threaded flag
409         toggle_single_threaded.set_active(App::single_threaded);
410 #endif
411
412         // Refresh the value of the auto backup interval
413         auto_backup_interval.set_value(App::auto_recover->get_timeout() / 1000);
414
415         // Refresh the status of the restrict_radius_ducks flag
416         toggle_restrict_radius_ducks.set_active(App::restrict_radius_ducks);
417
418         // Refresh the browser_command textbox
419         textbox_browser_command.set_text(App::browser_command);
420
421         // Refresh the preferred filename prefix
422         textbox_custom_filename_prefix.set_text(App::custom_filename_prefix);
423
424         // Refresh the preferred new Document X dimension
425         adj_pref_x_size.set_value(App::preferred_x_size);
426         
427         // Refresh the preferred new Document Y dimension
428         adj_pref_y_size.set_value(App::preferred_y_size);
429         
430         // Refresh the preferred Predefined size
431         size_template_combo->set_active_text(App::predefined_size);
432 }
433
434 GammaPattern::GammaPattern():
435         tile_w(80),
436         tile_h(80)
437 {
438         set_size_request(tile_w*4,tile_h*3);
439         signal_expose_event().connect(sigc::mem_fun(*this, &studio::GammaPattern::redraw));
440 }
441
442 GammaPattern::~GammaPattern()
443 {
444 }
445
446 void
447 GammaPattern::refresh()
448 {
449         black[0].set_rgb_p(
450                 r_F32_to_F32(0.0),
451                 g_F32_to_F32(0.0),
452                 b_F32_to_F32(0.0)
453         );
454         white[0].set_rgb_p(
455                 r_F32_to_F32(1.0),
456                 g_F32_to_F32(1.0),
457                 b_F32_to_F32(1.0)
458         );
459         gray50[0].set_rgb_p(
460                 r_F32_to_F32(0.5),
461                 g_F32_to_F32(0.5),
462                 b_F32_to_F32(0.5)
463         );
464         gray25[0].set_rgb_p(
465                 r_F32_to_F32(0.25),
466                 g_F32_to_F32(0.25),
467                 b_F32_to_F32(0.25)
468         );
469
470         // Reds
471         black[1].set_rgb(black[0].get_red(),0,0);
472         gray25[1].set_rgb(gray25[0].get_red(),0,0);
473         gray50[1].set_rgb(gray50[0].get_red(),0,0);
474         white[1].set_rgb(white[0].get_red(),0,0);
475
476         // Greens
477         black[2].set_rgb(0,black[0].get_green(),0);
478         gray25[2].set_rgb(0,gray25[0].get_green(),0);
479         gray50[2].set_rgb(0,gray50[0].get_green(),0);
480         white[2].set_rgb(0,white[0].get_green(),0);
481
482         // blues
483         black[3].set_rgb(0,0,black[0].get_blue());
484         gray25[3].set_rgb(0,0,gray25[0].get_blue());
485         gray50[3].set_rgb(0,0,gray50[0].get_blue());
486         white[3].set_rgb(0,0,white[0].get_blue());
487 }
488
489 bool
490 GammaPattern::redraw(GdkEventExpose */*bleh*/)
491 {
492         static const char hlines[] = { 3, 0 };
493
494         Glib::RefPtr<Gdk::GC> gc(Gdk::GC::create(get_window()));
495
496         int i;
497         Gdk::Color trueblack("#000000");
498
499         // 50% Pattern
500         for(i=0;i<4;i++)
501         {
502                 gc->set_rgb_fg_color(black[i]);
503                 get_window()->draw_rectangle(gc, true, i*tile_w, 0, tile_w, tile_h);
504
505                 gc->set_stipple(Gdk::Bitmap::create(hlines,2,2));
506                 gc->set_fill(Gdk::STIPPLED);
507                 gc->set_rgb_fg_color(white[i]);
508                 get_window()->draw_rectangle(gc, true, i*tile_w, 0, tile_w, tile_h);
509
510                 gc->set_fill(Gdk::SOLID);
511                 gc->set_rgb_fg_color(gray50[i]);
512
513                 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);
514         }
515
516         // 25% Pattern
517         for(i=0;i<4;i++)
518         {
519                 gc->set_rgb_fg_color(black[i]);
520                 get_window()->draw_rectangle(gc, true, i*tile_w, tile_h, tile_w, tile_h);
521
522                 gc->set_stipple(Gdk::Bitmap::create(hlines,2,2));
523                 gc->set_fill(Gdk::STIPPLED);
524                 gc->set_rgb_fg_color(gray50[i]);
525                 get_window()->draw_rectangle(gc, true, i*tile_w, tile_h, tile_w, tile_h);
526
527                 gc->set_fill(Gdk::SOLID);
528                 gc->set_rgb_fg_color(gray25[i]);
529
530                 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);
531         }
532
533         // Black-level Pattern
534         gc->set_rgb_fg_color(trueblack);
535         get_window()->draw_rectangle(gc, true, 0, tile_h*2, tile_w*4, tile_h);
536         gc->set_fill(Gdk::SOLID);
537         for(i=0;i<4;i++)
538         {
539                 gc->set_rgb_fg_color(black[i]);
540
541                 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);
542         }
543
544         return true;
545 }
546
547
548 BlackLevelSelector::BlackLevelSelector()
549 {
550         set_size_request(-1,24);
551         signal_expose_event().connect(sigc::mem_fun(*this, &studio::BlackLevelSelector::redraw));
552
553         add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
554         add_events(Gdk::BUTTON1_MOTION_MASK);
555         add_events(Gdk::BUTTON1_MOTION_MASK);
556 }
557
558 BlackLevelSelector::~BlackLevelSelector()
559 {
560 }
561
562 bool
563 BlackLevelSelector::redraw(GdkEventExpose */*bleh*/)
564 {
565         const int w(get_width()),h(get_height());
566
567         Gdk::Color color;
568
569         Glib::RefPtr<Gdk::GC> gc(Gdk::GC::create(get_window()));
570
571         int i;
572
573         // Draw the gradient
574         for(i=0;i<w;i++)
575         {
576                 color.set_rgb(i*65536/w,i*65536/w,i*65536/w);
577
578                 gc->set_rgb_fg_color(color);
579                 get_window()->draw_rectangle(gc, true, i, 0, 1, h);
580         }
581
582         // Draw a frame
583         gc->set_rgb_fg_color(Gdk::Color("#000000"));
584         get_window()->draw_rectangle(gc, false, 0, 0, w-1, h-1);
585
586         // Draw the position of the current value
587         i=(int)(level*w+0.5);
588         gc->set_rgb_fg_color(Gdk::Color("#ff0000"));
589         get_window()->draw_rectangle(gc, true, i, 1, 1, h-1);
590
591         // Print out the value
592         Glib::RefPtr<Pango::Layout> layout(Pango::Layout::create(get_pango_context()));
593         layout->set_text(etl::strprintf("%0.01f%%",level*100.0f));
594         layout->set_alignment(Pango::ALIGN_CENTER);
595         gc->set_rgb_fg_color(Gdk::Color("#a00000"));
596         get_window()->draw_layout(gc, w/2, 4, layout);
597
598         return true;
599 }
600
601
602
603 bool
604 BlackLevelSelector::on_event(GdkEvent *event)
605 {
606         int x(round_to_int(event->button.x));
607         //int y(round_to_int(event->button.y));
608
609     switch(event->type)
610     {
611         case GDK_MOTION_NOTIFY:
612                 level=(float)x/(float)get_width();
613                 if(level<0.0f)level=0.0f;
614                 if(level>1.0f)level=1.0f;
615                 signal_value_changed_();
616                 queue_draw();
617                 return true;
618                 break;
619         case GDK_BUTTON_PRESS:
620         case GDK_BUTTON_RELEASE:
621                 if(event->button.button==1)
622                 {
623                         level=(float)x/(float)get_width();
624                         if(level<0.0f)level=0.0f;
625                         if(level>1.0f)level=1.0f;
626                         signal_value_changed_();
627                         queue_draw();
628                         return true;
629                 }
630                 break;
631         default:
632                 break;
633         }
634
635         return false;
636 }
637
638
639 void
640 Dialog_Setup::set_time_format(synfig::Time::Format x)
641 {
642         time_format=x;
643         if (x <= Time::FORMAT_VIDEO)
644                 timestamp_optionmenu.set_history(0);
645         else if (x == (Time::FORMAT_NORMAL))
646                 timestamp_optionmenu.set_history(1);
647         else if (x == (Time::FORMAT_NORMAL | Time::FORMAT_NOSPACES))
648                 timestamp_optionmenu.set_history(2);
649         else if (x == (Time::FORMAT_NORMAL | Time::FORMAT_FULL))
650                 timestamp_optionmenu.set_history(3);
651         else if (x == (Time::FORMAT_NORMAL | Time::FORMAT_NOSPACES | Time::FORMAT_FULL))
652                 timestamp_optionmenu.set_history(4);
653         else if (x == (Time::FORMAT_FRAMES))
654                 timestamp_optionmenu.set_history(5);
655         else
656                 timestamp_optionmenu.set_history(1);
657 }
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674 RedBlueLevelSelector::RedBlueLevelSelector()
675 {
676         set_size_request(-1,24);
677         signal_expose_event().connect(sigc::mem_fun(*this, &studio::RedBlueLevelSelector::redraw));
678
679         add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK);
680         add_events(Gdk::BUTTON1_MOTION_MASK);
681         add_events(Gdk::BUTTON1_MOTION_MASK);
682 }
683
684 RedBlueLevelSelector::~RedBlueLevelSelector()
685 {
686 }
687
688 bool
689 RedBlueLevelSelector::redraw(GdkEventExpose */*bleh*/)
690 {
691         const int w(get_width()),h(get_height());
692
693         Gdk::Color color;
694
695         Glib::RefPtr<Gdk::GC> gc(Gdk::GC::create(get_window()));
696
697         int i;
698
699         // Draw the gradient
700         for(i=0;i<w;i++)
701         {
702                 float red_blue(((float(i)/float(w)+0.5f)-1.0f)/2.0f+1.0f);
703                 float blue_red(2.0f-(red_blue));
704                 if(red_blue>1.0f)red_blue=1.0f;
705                 if(blue_red>1.0f)blue_red=1.0f;
706
707                 color.set_rgb(
708                         round_to_int(min(red_blue,1.0f)*65535),
709                         round_to_int(sqrt(min(red_blue,blue_red))*65535),
710                         round_to_int(min(blue_red,1.0f)*65535)
711                 );
712
713                 gc->set_rgb_fg_color(color);
714                 get_window()->draw_rectangle(gc, true, i, 0, 1, h);
715         }
716
717         // Draw a frame
718         gc->set_rgb_fg_color(Gdk::Color("#000000"));
719         get_window()->draw_rectangle(gc, false, 0, 0, w-1, h-1);
720
721         // Draw the position of the current value
722         i=(int)(((level-1.0f)*2.0f+1.0f-0.5f)*w+0.5);
723         gc->set_rgb_fg_color(Gdk::Color("#00ff00"));
724         get_window()->draw_rectangle(gc, true, i, 1, 1, h-1);
725
726         // Print out the value
727         Glib::RefPtr<Pango::Layout> layout(Pango::Layout::create(get_pango_context()));
728         layout->set_text(etl::strprintf("%0.02f",level));
729         layout->set_alignment(Pango::ALIGN_CENTER);
730         gc->set_rgb_fg_color(Gdk::Color("#a00000"));
731         get_window()->draw_layout(gc, w/2, 4, layout);
732
733         return true;
734 }
735
736
737
738 bool
739 RedBlueLevelSelector::on_event(GdkEvent *event)
740 {
741         int x(round_to_int(event->button.x));
742         //int y(round_to_int(event->button.y));
743
744     switch(event->type)
745     {
746         case GDK_MOTION_NOTIFY:
747                 level=(((float)(x)/(float)get_width()+0.5)-1.0f)/2.0f+1.0f;
748                 if(level<0.5f)level=0.5f;
749                 if(level>1.5f)level=1.5f;
750                 signal_value_changed_();
751                 queue_draw();
752                 return true;
753                 break;
754         case GDK_BUTTON_PRESS:
755         case GDK_BUTTON_RELEASE:
756                 if(event->button.button==1)
757                 {
758                         level=(((float)(x)/(float)get_width()+0.5)-1.0f)/2.0f+1.0f;
759                         if(level<0.5f)level=0.5f;
760                         if(level>1.5f)level=1.5f;
761                         signal_value_changed_();
762                         queue_draw();
763                         return true;
764                 }
765                 break;
766         default:
767                 break;
768         }
769
770         return false;
771 }