]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormColorpicker.C
Strip out another 180 #includes.
[lyx.git] / src / frontends / xforms / FormColorpicker.C
1 /**
2  * \file FormColorpicker.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "FormColorpicker.h"
14 #include "forms/form_colorpicker.h"
15
16 #include "Tooltips.h"
17 #include "xforms_resize.h"
18
19 #include "gettext.h"
20 #include "lyxrc.h"
21
22 #include "support/filetools.h" //  LibFileSearch
23 #include "support/LAssert.h"
24 #include "support/tostr.h"
25
26 #include "lyx_forms.h"
27
28
29 namespace {
30
31 enum GuiColors {
32         GUI_COLOR_CHOICE   = FL_FREE_COL13,
33         GUI_COLOR_HUE_DIAL = FL_FREE_COL14,
34 };
35
36
37 string const fillLabel(RGBColor const & rgb)
38 {
39         return tostr(rgb.r) + ", " + tostr(rgb.g) + ", " + tostr(rgb.b);
40 }
41
42
43 string const fillLabel(HSVColor const & hsv)
44 {
45         int const h = int(hsv.h);
46         int const s = int(100.0 * hsv.s);
47         int const v = int(100.0 * hsv.v);
48
49         return tostr(h) + ", " + tostr(s) + ", " + tostr(v);
50 }
51
52 } // namespace anon
53
54
55 extern "C" {
56
57 // Callback function invoked by xforms when the dialog is closed by the
58 // window manager.
59 static int C_WMHideCB(FL_FORM * form, void *);
60
61 } // extern "C"
62
63
64 FormColorpicker::FormColorpicker()
65         : minw_(0), minh_(0),
66           title_(_("Select Color")),
67           finished_(true),
68           icon_pixmap_(0), icon_mask_(0),
69           tooltips_(new Tooltips)
70 {}
71
72
73 FormColorpicker::~FormColorpicker()
74 {
75         if (icon_pixmap_)
76                 XFreePixmap(fl_get_display(), icon_pixmap_);
77 }
78
79
80 RGBColor const & FormColorpicker::requestColor(RGBColor const & color)
81 {
82         input_color_ = color;
83         color_ = color;
84
85         show();
86
87         fl_deactivate_all_forms();
88         fl_activate_form(form());
89
90         finished_ = false;
91         while (!finished_)
92                 fl_check_forms();
93
94         fl_activate_all_forms();
95         return color_;
96 }
97
98
99 void FormColorpicker::show()
100 {
101         if (!form()) {
102                 build();
103                 prepare_to_show();
104         }
105
106         // make sure the form is up to date.
107         fl_freeze_form(form());
108         update();
109         fl_unfreeze_form(form());
110
111         if (form()->visible) {
112                 fl_raise_form(form());
113                 /* This XMapWindow() will hopefully ensure that
114                  * iconified dialogs are de-iconified. Mad props
115                  * out to those crazy Xlib guys for forgetting a
116                  * XDeiconifyWindow(). At least WindowMaker, when
117                  * being notified of the redirected MapRequest will
118                  * specifically de-iconify. From source, fvwm2 seems
119                  * to do the same.
120                  */
121                 XMapWindow(fl_get_display(), form()->window);
122         } else {
123                 // calls to fl_set_form_minsize/maxsize apply only to the next
124                 // fl_show_form(), so this comes first.
125                 fl_set_form_minsize(form(), minw_, minh_);
126
127                 string const maximize_title = "LyX: " + title_;
128                 int const iconify_policy =
129                         lyxrc.dialogs_iconify_with_main ? FL_TRANSIENT : 0;
130
131                 fl_show_form(form(),
132                              FL_PLACE_MOUSE | FL_FREE_SIZE,
133                              iconify_policy,
134                              maximize_title.c_str());
135         }
136 }
137
138
139 void FormColorpicker::hide() const
140 {
141         // xforms sometimes tries to process a hint-type MotionNotify, and
142         // use XQueryPointer, without verifying if the window still exists.
143         // So we try to clear out motion events in the queue before the
144         // DestroyNotify
145         XSync(fl_get_display(), false);
146
147         if (form() && form()->visible)
148                 fl_hide_form(form());
149 }
150
151
152 void FormColorpicker::build()
153 {
154         dialog_.reset(build_colorpicker(this));
155         rgb_.reset(build_colorpicker_rgb(this));
156         hsv_.reset(build_colorpicker_hsv(this));
157
158         fl_set_object_color(dialog_->button_color,
159                             GUI_COLOR_CHOICE, GUI_COLOR_CHOICE);
160
161         fl_set_object_color(hsv_->dial_hue, GUI_COLOR_HUE_DIAL, FL_BLACK);
162         fl_set_dial_bounds(hsv_->dial_hue, 0.0, 360.0);
163         fl_set_dial_step(hsv_->dial_hue, 1.0);
164         fl_set_dial_return(hsv_->dial_hue, FL_RETURN_CHANGED);
165
166         fl_set_slider_bounds(hsv_->slider_saturation, 0.0, 1.0);
167         fl_set_slider_step(hsv_->slider_saturation, 0.01);
168         fl_set_slider_return(hsv_->slider_saturation, FL_RETURN_CHANGED);
169
170         fl_set_slider_bounds(hsv_->slider_value, 0.0, 1.0);
171         fl_set_slider_step(hsv_->slider_value, 0.01);
172         fl_set_slider_return(hsv_->slider_value, FL_RETURN_CHANGED);
173
174         fl_set_slider_bounds(rgb_->slider_red, 0.0, 255.0);
175         fl_set_slider_step(rgb_->slider_red, 1.0);
176         fl_set_slider_return(rgb_->slider_red, FL_RETURN_CHANGED);
177
178         fl_set_slider_bounds(rgb_->slider_green, 0.0, 255.0);
179         fl_set_slider_step(rgb_->slider_green, 1.0);
180         fl_set_slider_return(rgb_->slider_green, FL_RETURN_CHANGED);
181
182         fl_set_slider_bounds(rgb_->slider_blue, 0.0, 255.0);
183         fl_set_slider_step(rgb_->slider_blue, 1.0);
184         fl_set_slider_return(rgb_->slider_blue, FL_RETURN_CHANGED);
185
186         // Stack tabs
187         fl_addto_tabfolder(dialog_->tabfolder,_("RGB").c_str(), rgb_->form);
188         fl_addto_tabfolder(dialog_->tabfolder,_("HSV").c_str(), hsv_->form);
189 }
190
191
192 void FormColorpicker::update() const
193 {
194         fl_mapcolor(GUI_COLOR_CHOICE, color_.r, color_.g, color_.b);
195
196         FL_FORM * folder = fl_get_active_folder(dialog_->tabfolder);
197
198         if (!folder)
199                 folder = rgb_->form;
200
201         if (folder == rgb_->form) {
202                 fl_set_slider_value(rgb_->slider_red,   color_.r);
203                 fl_set_slider_value(rgb_->slider_green, color_.g);
204                 fl_set_slider_value(rgb_->slider_blue,  color_.b);
205
206                 fl_set_object_label(dialog_->text_color_values,
207                                     fillLabel(color_).c_str());
208
209         } else if (folder == hsv_->form) {
210                 HSVColor hsv = HSVColor(color_);
211                 hsv.h = std::max(hsv.h, 0.0);
212
213                 fl_set_dial_value(hsv_->dial_hue, hsv.h);
214                 fl_set_slider_value(hsv_->slider_saturation, hsv.s);
215                 fl_set_slider_value(hsv_->slider_value, hsv.v);
216
217                 fl_set_object_label(dialog_->text_color_values,
218                                     fillLabel(hsv).c_str());
219
220                 RGBColor col = HSVColor(hsv.h, 1.0, 1.0);
221                 col.r = std::max(col.r, 0u);
222                 fl_mapcolor(GUI_COLOR_HUE_DIAL, col.r, col.g, col.b);
223                 fl_redraw_object(hsv_->dial_hue);
224         }
225 }
226
227
228 void FormColorpicker::input(FL_OBJECT * ob, long)
229 {
230         if (ob == dialog_->tabfolder) {
231                 update();
232
233         } else if (ob == hsv_->dial_hue ||
234                    ob == hsv_->slider_saturation ||
235                    ob == hsv_->slider_value) {
236                 InputHSV();
237
238         } else if (ob == rgb_->slider_red ||
239                    ob == rgb_->slider_green ||
240                    ob == rgb_->slider_blue) {
241                 InputRGB();
242
243         } else if (ob == dialog_->button_ok) {
244                 hide();
245                 finished_ = true;
246
247         } else if (ob == dialog_->button_close || ob == 0) {
248                 color_ = input_color_;
249                 hide();
250                 finished_ = true;
251         }
252 }
253
254
255 FL_FORM * FormColorpicker::form() const
256 {
257         return dialog_.get() ? dialog_->form : 0;
258 }
259
260
261 Tooltips & FormColorpicker::tooltips() const
262 {
263         return *tooltips_;
264 }
265
266
267 void FormColorpicker::prepare_to_show()
268 {
269         double const scale = get_scale_to_fit(form());
270         if (scale > 1.001)
271                 scale_form_horizontally(form(), scale);
272
273         // work around dumb xforms sizing bug
274         minw_ = form()->w;
275         minh_ = form()->h;
276
277         fl_set_form_atclose(form(), C_WMHideCB, 0);
278
279         // set the title for the minimized form
280         if (!lyxrc.dialogs_iconify_with_main)
281                 fl_winicontitle(form()->window, title_.c_str());
282
283         //  assign an icon to the form
284         string const iconname =
285                 lyx::support::LibFileSearch("images", "lyx", "xpm");
286
287         if (!iconname.empty()) {
288                 unsigned int w, h;
289                 icon_pixmap_ = fl_read_pixmapfile(fl_root,
290                                                   iconname.c_str(),
291                                                   &w,
292                                                   &h,
293                                                   &icon_mask_,
294                                                   0, 0, 0);
295                 fl_set_form_icon(form(), icon_pixmap_, icon_mask_);
296         }
297 }
298
299
300 void FormColorpicker::InputRGB()
301 {
302         int const red   = int(fl_get_slider_value(rgb_->slider_red));
303         int const green = int(fl_get_slider_value(rgb_->slider_green));
304         int const blue  = int(fl_get_slider_value(rgb_->slider_blue));
305
306         color_ = RGBColor(red, green, blue);
307
308         fl_freeze_form(dialog_->form);
309
310         fl_set_object_label(dialog_->text_color_values,
311                             fillLabel(color_).c_str());
312
313         fl_mapcolor(GUI_COLOR_CHOICE, color_.r, color_.g, color_.b);
314         fl_redraw_object(dialog_->button_color);
315
316         fl_unfreeze_form(dialog_->form);
317 }
318
319
320 void FormColorpicker::InputHSV()
321 {
322         double const hue = fl_get_dial_value(hsv_->dial_hue);
323         double const sat = fl_get_slider_value(hsv_->slider_saturation);
324         double const val = fl_get_slider_value(hsv_->slider_value);
325
326         HSVColor hsv = HSVColor(hue, sat, val);
327         color_ = hsv;
328
329         fl_freeze_form(dialog_->form);
330
331         fl_set_object_label(dialog_->text_color_values, fillLabel(hsv).c_str());
332
333         fl_mapcolor(GUI_COLOR_CHOICE, color_.r, color_.g, color_.b);
334         fl_redraw_object(dialog_->button_color);
335
336         RGBColor col = HSVColor(hue, 1.0, 1.0);
337         col.r = std::max(col.r, 0u);
338         fl_mapcolor(GUI_COLOR_HUE_DIAL, col.r, col.g, col.b);
339         fl_redraw_object(hsv_->dial_hue);
340
341         fl_unfreeze_form(dialog_->form);
342 }
343
344
345 extern "C" {
346
347 void C_FormColorpickerInputCB(FL_OBJECT * ob, long d)
348 {
349         lyx::support::Assert(ob && ob->form && ob->form->u_vdata);
350         FormColorpicker * ptr =
351                 static_cast<FormColorpicker *>(ob->form->u_vdata);
352         ptr->input(ob, d);
353 }
354
355
356 static int C_WMHideCB(FL_FORM * form, void *)
357 {
358         // Close the dialog cleanly, even if the WM is used to do so.
359         lyx::support::Assert(form && form->u_vdata);
360         FormColorpicker * ptr = static_cast<FormColorpicker *>(form->u_vdata);
361         ptr->input(0, 0);
362         return FL_CANCEL;
363 }
364
365 } // extern "C"