wmaker: Add keyboard shortcuts for keeping window on top or at bottom.
[wmaker-crm.git] / WPrefs.app / Icons.c
blobe68da5690861c594266a6f54fad327944eda0dcd
1 /* Icons.c- icon preferences
3 * WPrefs - Window Maker Preferences Program
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "WPrefs.h"
25 static const struct {
26 const char *db_value;
27 const char *label;
28 } icon_animation[] = {
29 { "zoom", N_("Shrinking/Zooming") },
30 { "twist", N_("Spinning/Twisting") },
31 { "flip", N_("3D-flipping") },
32 { "none", N_("None") }
36 * The code is using a convenient trick to make the link between the icon
37 * position and its representing number:
38 * bit[0] tell if the icon are arranged horizontally or vertically
39 * bit[2:1] tell the corner to which they are starting from:
40 * bit[2] is for Top or Bottom choice
41 * bit[1] is for Left or Right choice
43 static const char icon_position_dbvalue[][4] = {
44 /* 000: */ "tlv",
45 /* 001: */ "tlh",
46 /* 010: */ "trv",
47 /* 011: */ "trh",
48 /* 100: */ "blv",
49 /* 101: */ "blh",
50 /* 110: */ "brv",
51 /* 111: */ "brh"
54 typedef struct _Panel {
55 WMBox *box;
57 char *sectionName;
59 char *description;
61 CallbackRec callbacks;
63 Bool have_legacy_apercu;
65 WMWidget *parent;
67 WMFrame *posF;
68 WMFrame *posVF;
69 WMFrame *posV;
71 struct {
72 int width, height;
73 } icon_position;
75 WMButton *posB[wlengthof_nocheck(icon_position_dbvalue)];
77 WMFrame *animF;
78 WMButton *animB[wlengthof_nocheck(icon_animation)];
80 WMFrame *optF;
81 WMButton *arrB;
82 WMButton *omnB;
83 WMButton *sclB;
85 struct {
86 WMFrame *frame;
87 WMSlider *slider;
88 WMLabel *label;
89 } minipreview;
91 WMFrame *sizeF;
92 WMPopUpButton *sizeP;
94 int iconPos;
95 } _Panel;
98 * Minimum size for a Mini-Preview:
99 * This value is actually twice the size of the minimum icon size choosable.
100 * We set the slider min to taht number minus one, because when set to this
101 * value WPrefs will consider that the user wants the feature turned off.
103 static const int minipreview_minimum_size = 2 * 24 - 1;
105 static const int minipreview_maximum_size = 512; /* Arbitrary limit for the slider */
107 #define ICON_FILE "iconprefs"
109 static void showIconLayout(WMWidget * widget, void *data)
111 _Panel *panel = (_Panel *) data;
112 int w, h;
113 int i;
115 for (i = 0; i < wlengthof(panel->posB); i++) {
116 if (panel->posB[i] == widget) {
117 panel->iconPos = i;
118 break;
122 if (panel->iconPos & 1) {
123 w = 32;
124 h = 8;
125 } else {
126 w = 8;
127 h = 32;
129 WMResizeWidget(panel->posV, w, h);
131 switch (panel->iconPos & ~1) {
132 case 0:
133 WMMoveWidget(panel->posV, 2, 2);
134 break;
135 case 2:
136 WMMoveWidget(panel->posV, panel->icon_position.width - 2 - w, 2);
137 break;
138 case 4:
139 WMMoveWidget(panel->posV, 2, panel->icon_position.height - 2 - h);
140 break;
141 default:
142 WMMoveWidget(panel->posV, panel->icon_position.width - 2 - w, panel->icon_position.height - 2 - h);
143 break;
147 static void minipreview_slider_changed(WMWidget *w, void *data)
149 _Panel *panel = (_Panel *) data;
150 char buffer[64];
151 int value;
153 /* Parameter is not used, but tell the compiler that it is ok */
154 (void) w;
156 value = WMGetSliderValue(panel->minipreview.slider);
158 /* Round the value to a multiple of 8 because it makes the displayed value look better */
159 value &= ~7;
161 if (value <= minipreview_minimum_size)
162 sprintf(buffer, _("OFF"));
163 else
164 sprintf(buffer, "%i", value);
166 WMSetLabelText(panel->minipreview.label, buffer);
169 static void showData(_Panel * panel)
171 int i;
172 char *str;
173 Bool b;
175 WMSetButtonSelected(panel->arrB, GetBoolForKey("AutoArrangeIcons"));
176 WMSetButtonSelected(panel->omnB, GetBoolForKey("StickyIcons"));
177 WMSetButtonSelected(panel->sclB, GetBoolForKey("SingleClickLaunch"));
179 str = GetStringForKey("IconPosition");
180 if (str != NULL) {
181 for (i = 0; i < wlengthof(icon_position_dbvalue); i++)
182 if (strcmp(str, icon_position_dbvalue[i]) == 0) {
183 panel->iconPos = i;
184 goto found_position_value;
186 wwarning(_("bad value \"%s\" for option %s, using default \"%s\""),
187 str, "IconPosition", icon_position_dbvalue[5]);
189 panel->iconPos = 5;
190 found_position_value:
191 WMPerformButtonClick(panel->posB[panel->iconPos]);
193 i = GetIntegerForKey("IconSize");
194 i = (i - 24) / 8;
196 if (i < 0)
197 i = 0;
198 else if (i > 9)
199 i = 9;
200 WMSetPopUpButtonSelectedItem(panel->sizeP, i);
202 /* Mini-Previews for Icons */
205 * Backward Compatibility:
206 * These settings changed names after 0.95.6, so to avoid breaking user's
207 * config we still support the old names, and silently convert them to the
208 * new settings
209 * This hack should be kept for at least 2 years, that means >= 2017.
211 panel->have_legacy_apercu = False;
212 str = GetStringForKey("MiniwindowPreviewBalloons");
213 if (str != NULL) {
214 /* New names found, use them in priority */
215 b = GetBoolForKey("MiniwindowPreviewBalloons");
216 if (b) {
217 i = GetIntegerForKey("MiniPreviewSize");
218 if (i <= minipreview_minimum_size)
219 i = minipreview_minimum_size;
220 } else {
221 i = minipreview_minimum_size;
223 } else {
224 /* No new names, try the legacy names */
225 b = GetBoolForKey("MiniwindowApercuBalloons");
226 if (b) {
227 panel->have_legacy_apercu = True;
228 i = GetIntegerForKey("ApercuSize");
231 * In the beginning, the option was coded as a multiple of the icon
232 * size; then it was converted to pixel size
234 if (i < 24)
235 i *= GetIntegerForKey("IconSize");
237 if (i <= minipreview_minimum_size)
238 i = minipreview_minimum_size + 1; /* +1 to not display as "off" */
239 } else {
240 i = minipreview_minimum_size;
243 WMSetSliderValue(panel->minipreview.slider, i);
244 minipreview_slider_changed(panel->minipreview.slider, panel);
246 /* Animation */
247 str = GetStringForKey("IconificationStyle");
248 if (str != NULL) {
249 for (i = 0; i < wlengthof(icon_animation); i++) {
250 if (strcasecmp(str, icon_animation[i].db_value) == 0) {
251 WMPerformButtonClick(panel->animB[i]);
252 goto found_animation_value;
255 wwarning(_("animation style \"%s\" is unknown, resetting to \"%s\""),
256 str, icon_animation[0].db_value);
258 /* If we're here, no valid value have been found so we fall-back to the default */
259 WMPerformButtonClick(panel->animB[0]);
260 found_animation_value:
264 static void createPanel(Panel * p)
266 _Panel *panel = (_Panel *) p;
267 WMScreen *scr;
268 WMColor *color;
269 int i;
270 char buf[16];
271 int swidth, sheight;
272 int width, height;
273 int startx, starty;
275 panel->box = WMCreateBox(panel->parent);
276 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
278 /***************** Positioning of Icons *****************/
279 panel->posF = WMCreateFrame(panel->box);
280 WMResizeWidget(panel->posF, 268, 155);
281 WMMoveWidget(panel->posF, 12, 6);
282 WMSetFrameTitle(panel->posF, _("Icon Positioning"));
285 * There is an available area of 240 x 122, starting at x=14 y=20
286 * We have to keep 14 pixels on each side for the buttons,
287 * and an extra pixel for spacing. We also want the final dimension
288 * to be an even number so we can have the 2 buttons per side of
289 * the same size.
290 * In this area, we want to have a rectangle with the same aspect
291 * ratio as the screen.
293 scr = WMWidgetScreen(panel->parent);
294 swidth = WidthOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr)));
295 sheight = HeightOfScreen(DefaultScreenOfDisplay(WMScreenDisplay(scr)));
297 width = swidth * (122 - 15 * 2) / sheight;
298 if (width <= (240 - 15 * 2)) {
299 height = 122 - 15 * 2;
300 } else {
301 width = 240 - 15 * 2;
302 height = sheight * (240 - 15 * 2) / swidth;
305 panel->icon_position.width = width;
306 panel->icon_position.height = height;
308 startx = 14 + (240 - 15 * 2 - width) / 2;
309 starty = 20 + (122 - 15 * 2 - height) / 2;
311 for (i = 0; i < wlengthof(icon_position_dbvalue); i++) {
312 int x, y, w, h;
314 panel->posB[i] = WMCreateButton(panel->posF, WBTOnOff);
315 WMSetButtonAction(panel->posB[i], showIconLayout, panel);
317 if (i > 0)
318 WMGroupButtons(panel->posB[0], panel->posB[i]);
320 if (i & 1) { /* 0=Vertical, 1=Horizontal */
321 w = width / 2;
322 h = 14;
323 } else {
324 w = 14;
325 h = height / 2;
327 WMResizeWidget(panel->posB[i], w, h);
329 x = startx;
330 y = starty;
331 switch (i) {
332 case 0: x += 0; y += 15; break;
333 case 1: x += 15; y += 0; break;
334 case 2: x += 15 + width; y += 15; break;
335 case 3: x += 15 + w; y += 0; break;
336 case 4: x += 0; y += 15 + h; break;
337 case 5: x += 15; y += 15 + height; break;
338 case 6: x += 15 + width; y += 15 + h; break;
339 case 7: x += 15 + w; y += 15 + height; break;
341 WMMoveWidget(panel->posB[i], x, y);
344 color = WMCreateRGBColor(WMWidgetScreen(panel->parent), 0x5100, 0x5100, 0x7100, True);
345 panel->posVF = WMCreateFrame(panel->posF);
346 WMResizeWidget(panel->posVF, width, height);
347 WMMoveWidget(panel->posVF, startx + 15, starty + 15);
348 WMSetFrameRelief(panel->posVF, WRSunken);
349 WMSetWidgetBackgroundColor(panel->posVF, color);
350 WMReleaseColor(color);
352 panel->posV = WMCreateFrame(panel->posVF);
353 WMSetFrameRelief(panel->posV, WRSimple);
355 WMMapSubwidgets(panel->posF);
357 /***************** Icon Size ****************/
358 panel->sizeF = WMCreateFrame(panel->box);
359 WMResizeWidget(panel->sizeF, 100, 52);
360 WMMoveWidget(panel->sizeF, 12, 168);
361 WMSetFrameTitle(panel->sizeF, _("Icon Size"));
363 WMSetBalloonTextForView(_("The size of the dock/application icon and miniwindows"),
364 WMWidgetView(panel->sizeF));
366 panel->sizeP = WMCreatePopUpButton(panel->sizeF);
367 WMResizeWidget(panel->sizeP, 80, 20);
368 WMMoveWidget(panel->sizeP, 10, 19);
369 for (i = 24; i <= 96; i += 8) {
370 sprintf(buf, "%ix%i", i, i);
371 WMAddPopUpButtonItem(panel->sizeP, buf);
374 WMMapSubwidgets(panel->sizeF);
376 /***************** Mini-Previews ****************/
377 panel->minipreview.frame = WMCreateFrame(panel->box);
378 WMResizeWidget(panel->minipreview.frame, 156, 52);
379 WMMoveWidget(panel->minipreview.frame, 124, 168);
380 WMSetFrameTitle(panel->minipreview.frame, _("Mini-Previews for Icons"));
382 WMSetBalloonTextForView(_("The Mini-Preview provides a small view of the content of the\n"
383 "window when the mouse is placed over the icon."),
384 WMWidgetView(panel->minipreview.frame));
386 panel->minipreview.slider = WMCreateSlider(panel->minipreview.frame);
387 WMResizeWidget(panel->minipreview.slider, 109, 15);
388 WMMoveWidget(panel->minipreview.slider, 11, 23);
389 WMSetSliderMinValue(panel->minipreview.slider, minipreview_minimum_size);
390 WMSetSliderMaxValue(panel->minipreview.slider, minipreview_maximum_size);
391 WMSetSliderAction(panel->minipreview.slider, minipreview_slider_changed, panel);
393 panel->minipreview.label = WMCreateLabel(panel->minipreview.frame);
394 WMResizeWidget(panel->minipreview.label, 33, 15);
395 WMMoveWidget(panel->minipreview.label, 120, 23);
396 WMSetLabelText(panel->minipreview.label, _("OFF"));
398 WMMapSubwidgets(panel->minipreview.frame);
400 /***************** Animation ****************/
401 panel->animF = WMCreateFrame(panel->box);
402 WMResizeWidget(panel->animF, 215, 110);
403 WMMoveWidget(panel->animF, 292, 6);
404 WMSetFrameTitle(panel->animF, _("Iconification Animation"));
406 for (i = 0; i < wlengthof(icon_animation); i++) {
407 panel->animB[i] = WMCreateRadioButton(panel->animF);
408 WMResizeWidget(panel->animB[i], 192, 20);
409 WMMoveWidget(panel->animB[i], 12, 16 + i * 22);
411 if (i > 0)
412 WMGroupButtons(panel->animB[0], panel->animB[i]);
414 WMSetButtonText(panel->animB[i], _(icon_animation[i].label));
417 WMMapSubwidgets(panel->animF);
419 /***************** Options ****************/
420 panel->optF = WMCreateFrame(panel->box);
421 WMResizeWidget(panel->optF, 215, 90);
422 WMMoveWidget(panel->optF, 292, 130);
423 /* WMSetFrameTitle(panel->optF, _("Icon Display")); */
425 panel->arrB = WMCreateSwitchButton(panel->optF);
426 WMResizeWidget(panel->arrB, 198, 26);
427 WMMoveWidget(panel->arrB, 12, 8);
428 WMSetButtonText(panel->arrB, _("Auto-arrange icons"));
430 WMSetBalloonTextForView(_("Keep icons and miniwindows arranged all the time."), WMWidgetView(panel->arrB));
432 panel->omnB = WMCreateSwitchButton(panel->optF);
433 WMResizeWidget(panel->omnB, 198, 26);
434 WMMoveWidget(panel->omnB, 12, 34);
435 WMSetButtonText(panel->omnB, _("Omnipresent miniwindows"));
437 WMSetBalloonTextForView(_("Make miniwindows be present in all workspaces."), WMWidgetView(panel->omnB));
439 panel->sclB = WMCreateSwitchButton(panel->optF);
440 WMResizeWidget(panel->sclB, 198, 26);
441 WMMoveWidget(panel->sclB, 12, 60);
442 WMSetButtonText(panel->sclB, _("Single click activation"));
444 WMSetBalloonTextForView(_("Launch applications and restore windows with a single click."), WMWidgetView(panel->sclB));
446 WMMapSubwidgets(panel->optF);
448 WMRealizeWidget(panel->box);
449 WMMapSubwidgets(panel->box);
451 showData(panel);
454 static void storeData(_Panel * panel)
456 int i;
458 SetBoolForKey(WMGetButtonSelected(panel->arrB), "AutoArrangeIcons");
459 SetBoolForKey(WMGetButtonSelected(panel->omnB), "StickyIcons");
460 SetBoolForKey(WMGetButtonSelected(panel->sclB), "SingleClickLaunch");
462 SetIntegerForKey(WMGetPopUpButtonSelectedItem(panel->sizeP) * 8 + 24, "IconSize");
464 SetStringForKey(icon_position_dbvalue[panel->iconPos], "IconPosition");
466 i = WMGetSliderValue(panel->minipreview.slider);
467 if (i <= minipreview_minimum_size) {
468 SetBoolForKey(False, "MiniwindowPreviewBalloons");
469 } else {
470 SetBoolForKey(True, "MiniwindowPreviewBalloons");
471 if (i < minipreview_maximum_size) {
473 * If the value is bigger, it means it was edited by the user manually
474 * so we keep as-is. Otherwise, we round it to a multiple of 8 like it
475 * was done for display
477 i &= ~7;
479 SetIntegerForKey(i, "MiniPreviewSize");
481 if (panel->have_legacy_apercu) {
482 RemoveObjectForKey("MiniwindowApercuBalloons");
483 RemoveObjectForKey("ApercuSize");
486 for (i = 0; i < wlengthof(icon_animation); i++) {
487 if (WMGetButtonSelected(panel->animB[i])) {
488 SetStringForKey(icon_animation[i].db_value, "IconificationStyle");
489 break;
494 Panel *InitIcons(WMWidget *parent)
496 _Panel *panel;
498 panel = wmalloc(sizeof(_Panel));
500 panel->sectionName = _("Icon Preferences");
502 panel->description = _("Icon/Miniwindow handling options. Icon positioning\n"
503 "area, sizes of icons, miniaturization animation style.");
505 panel->parent = parent;
507 panel->callbacks.createWidgets = createPanel;
508 panel->callbacks.updateDomain = storeData;
510 AddSection(panel, ICON_FILE);
512 return panel;