Improve dockapp recognition
[wmaker-crm.git] / WPrefs.app / KeyboardShortcuts.c
blob13b844476050c1f673ff5b8054923c7d3e36652a
1 /* KeyboardShortcuts.c- keyboard shortcut bindings
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
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
23 #include "config.h" /* for HAVE_XCONVERTCASE */
25 #include "WPrefs.h"
26 #include <ctype.h>
28 #include <X11/keysym.h>
30 typedef struct _Panel {
31 WMBox *box;
33 char *sectionName;
35 char *description;
37 CallbackRec callbacks;
39 WMWidget *parent;
41 WMLabel *actL;
42 WMList *actLs;
44 WMFrame *shoF;
45 WMTextField *shoT;
46 WMButton *cleB;
47 WMButton *defB;
49 WMLabel *instructionsL;
51 WMColor *white;
52 WMColor *black;
53 WMColor *gray;
54 WMFont *font;
56 /**/ char capturing;
57 char **shortcuts;
58 int actionCount;
59 } _Panel;
61 #define ICON_FILE "keyshortcuts"
64 * Must be in the same order as the corresponding items in
65 * "actions list" in createPanel()
67 static char *keyOptions[] = {
68 "RootMenuKey",
69 "WindowListKey",
70 "WindowMenuKey",
71 "HideKey",
72 "HideOthersKey",
73 "MiniaturizeKey",
74 "MinimizeAllKey",
75 "CloseKey",
76 "MaximizeKey",
77 "VMaximizeKey",
78 "HMaximizeKey",
79 "LHMaximizeKey",
80 "RHMaximizeKey",
81 "MaximusKey",
82 "RaiseKey",
83 "LowerKey",
84 "RaiseLowerKey",
85 "ShadeKey",
86 "MoveResizeKey",
87 "SelectKey",
88 "FocusNextKey",
89 "FocusPrevKey",
90 "GroupNextKey",
91 "GroupPrevKey",
92 "NextWorkspaceKey",
93 "PrevWorkspaceKey",
94 "NextWorkspaceLayerKey",
95 "PrevWorkspaceLayerKey",
96 "Workspace1Key",
97 "Workspace2Key",
98 "Workspace3Key",
99 "Workspace4Key",
100 "Workspace5Key",
101 "Workspace6Key",
102 "Workspace7Key",
103 "Workspace8Key",
104 "Workspace9Key",
105 "Workspace10Key",
106 "WindowShortcut1Key",
107 "WindowShortcut2Key",
108 "WindowShortcut3Key",
109 "WindowShortcut4Key",
110 "WindowShortcut5Key",
111 "WindowShortcut6Key",
112 "WindowShortcut7Key",
113 "WindowShortcut8Key",
114 "WindowShortcut9Key",
115 "WindowShortcut10Key",
116 "ScreenSwitchKey",
117 "DockRaiseLowerKey",
118 #ifndef XKB_MODELOCK
119 "ClipRaiseLowerKey"
120 #else
121 "ClipRaiseLowerKey",
122 "ToggleKbdModeKey"
123 #endif /* XKB_MODELOCK */
126 #ifndef HAVE_XCONVERTCASE
127 /* from Xlib */
129 static void XConvertCase(register KeySym sym, KeySym * lower, KeySym * upper)
131 *lower = sym;
132 *upper = sym;
133 switch (sym >> 8) {
134 case 0: /* Latin 1 */
135 if ((sym >= XK_A) && (sym <= XK_Z))
136 *lower += (XK_a - XK_A);
137 else if ((sym >= XK_a) && (sym <= XK_z))
138 *upper -= (XK_a - XK_A);
139 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
140 *lower += (XK_agrave - XK_Agrave);
141 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
142 *upper -= (XK_agrave - XK_Agrave);
143 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
144 *lower += (XK_oslash - XK_Ooblique);
145 else if ((sym >= XK_oslash) && (sym <= XK_thorn))
146 *upper -= (XK_oslash - XK_Ooblique);
147 break;
148 case 1: /* Latin 2 */
149 /* Assume the KeySym is a legal value (ignore discontinuities) */
150 if (sym == XK_Aogonek)
151 *lower = XK_aogonek;
152 else if (sym >= XK_Lstroke && sym <= XK_Sacute)
153 *lower += (XK_lstroke - XK_Lstroke);
154 else if (sym >= XK_Scaron && sym <= XK_Zacute)
155 *lower += (XK_scaron - XK_Scaron);
156 else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
157 *lower += (XK_zcaron - XK_Zcaron);
158 else if (sym == XK_aogonek)
159 *upper = XK_Aogonek;
160 else if (sym >= XK_lstroke && sym <= XK_sacute)
161 *upper -= (XK_lstroke - XK_Lstroke);
162 else if (sym >= XK_scaron && sym <= XK_zacute)
163 *upper -= (XK_scaron - XK_Scaron);
164 else if (sym >= XK_zcaron && sym <= XK_zabovedot)
165 *upper -= (XK_zcaron - XK_Zcaron);
166 else if (sym >= XK_Racute && sym <= XK_Tcedilla)
167 *lower += (XK_racute - XK_Racute);
168 else if (sym >= XK_racute && sym <= XK_tcedilla)
169 *upper -= (XK_racute - XK_Racute);
170 break;
171 case 2: /* Latin 3 */
172 /* Assume the KeySym is a legal value (ignore discontinuities) */
173 if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
174 *lower += (XK_hstroke - XK_Hstroke);
175 else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
176 *lower += (XK_gbreve - XK_Gbreve);
177 else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
178 *upper -= (XK_hstroke - XK_Hstroke);
179 else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
180 *upper -= (XK_gbreve - XK_Gbreve);
181 else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
182 *lower += (XK_cabovedot - XK_Cabovedot);
183 else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
184 *upper -= (XK_cabovedot - XK_Cabovedot);
185 break;
186 case 3: /* Latin 4 */
187 /* Assume the KeySym is a legal value (ignore discontinuities) */
188 if (sym >= XK_Rcedilla && sym <= XK_Tslash)
189 *lower += (XK_rcedilla - XK_Rcedilla);
190 else if (sym >= XK_rcedilla && sym <= XK_tslash)
191 *upper -= (XK_rcedilla - XK_Rcedilla);
192 else if (sym == XK_ENG)
193 *lower = XK_eng;
194 else if (sym == XK_eng)
195 *upper = XK_ENG;
196 else if (sym >= XK_Amacron && sym <= XK_Umacron)
197 *lower += (XK_amacron - XK_Amacron);
198 else if (sym >= XK_amacron && sym <= XK_umacron)
199 *upper -= (XK_amacron - XK_Amacron);
200 break;
201 case 6: /* Cyrillic */
202 /* Assume the KeySym is a legal value (ignore discontinuities) */
203 if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
204 *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
205 else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
206 *upper += (XK_Serbian_DJE - XK_Serbian_dje);
207 else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
208 *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
209 else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
210 *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
211 break;
212 case 7: /* Greek */
213 /* Assume the KeySym is a legal value (ignore discontinuities) */
214 if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
215 *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
216 else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
217 sym != XK_Greek_iotaaccentdieresis && sym != XK_Greek_upsilonaccentdieresis)
218 *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
219 else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
220 *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
221 else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && sym != XK_Greek_finalsmallsigma)
222 *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
223 break;
224 case 0x14: /* Armenian */
225 if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
226 *lower = sym | 1;
227 *upper = sym & ~1;
229 break;
232 #endif
234 static char *captureShortcut(Display * dpy, _Panel * panel)
236 XEvent ev;
237 KeySym ksym, lksym, uksym;
238 char buffer[64];
239 char *key = NULL;
241 while (panel->capturing) {
242 XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
243 WMNextEvent(dpy, &ev);
244 if (ev.type == KeyPress && ev.xkey.keycode != 0) {
245 ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0);
246 if (!IsModifierKey(ksym)) {
247 XConvertCase(ksym, &lksym, &uksym);
248 key = XKeysymToString(uksym);
250 panel->capturing = 0;
251 break;
254 WMHandleEvent(&ev);
257 if (!key)
258 return NULL;
260 buffer[0] = 0;
262 if (ev.xkey.state & ControlMask) {
263 strcat(buffer, "Control+");
265 if (ev.xkey.state & ShiftMask) {
266 strcat(buffer, "Shift+");
268 if (ev.xkey.state & Mod1Mask) {
269 strcat(buffer, "Mod1+");
271 if (ev.xkey.state & Mod2Mask) {
272 strcat(buffer, "Mod2+");
274 if (ev.xkey.state & Mod3Mask) {
275 strcat(buffer, "Mod3+");
277 if (ev.xkey.state & Mod4Mask) {
278 strcat(buffer, "Mod4+");
280 if (ev.xkey.state & Mod5Mask) {
281 strcat(buffer, "Mod5+");
283 strcat(buffer, key);
285 return wstrdup(buffer);
288 static void captureClick(WMWidget * w, void *data)
290 _Panel *panel = (_Panel *) data;
291 Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
292 char *shortcut;
294 if (!panel->capturing) {
295 panel->capturing = 1;
296 WMSetButtonText(w, _("Cancel"));
297 WMSetLabelText(panel->instructionsL,
298 _("Press the desired shortcut key(s) or click Cancel to stop capturing."));
299 XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, GrabModeAsync, GrabModeAsync, CurrentTime);
300 shortcut = captureShortcut(dpy, panel);
301 if (shortcut) {
302 int row = WMGetListSelectedItemRow(panel->actLs);
304 WMSetTextFieldText(panel->shoT, shortcut);
305 if (row >= 0) {
306 if (panel->shortcuts[row])
307 wfree(panel->shortcuts[row]);
308 panel->shortcuts[row] = shortcut;
310 WMRedisplayWidget(panel->actLs);
311 } else {
312 wfree(shortcut);
316 panel->capturing = 0;
317 WMSetButtonText(w, _("Capture"));
318 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
319 XUngrabKeyboard(dpy, CurrentTime);
322 static void clearShortcut(WMWidget * w, void *data)
324 _Panel *panel = (_Panel *) data;
325 int row = WMGetListSelectedItemRow(panel->actLs);
327 WMSetTextFieldText(panel->shoT, NULL);
329 if (row >= 0) {
330 if (panel->shortcuts[row])
331 wfree(panel->shortcuts[row]);
332 panel->shortcuts[row] = NULL;
333 WMRedisplayWidget(panel->actLs);
337 static void typedKeys(void *observerData, WMNotification * notification)
339 _Panel *panel = (_Panel *) observerData;
340 int row = WMGetListSelectedItemRow(panel->actLs);
342 if (row < 0)
343 return;
345 if (panel->shortcuts[row])
346 wfree(panel->shortcuts[row]);
347 panel->shortcuts[row] = WMGetTextFieldText(panel->shoT);
348 if (strlen(panel->shortcuts[row]) == 0) {
349 wfree(panel->shortcuts[row]);
350 panel->shortcuts[row] = NULL;
352 WMRedisplayWidget(panel->actLs);
355 static void listClick(WMWidget * w, void *data)
357 _Panel *panel = (_Panel *) data;
358 int row = WMGetListSelectedItemRow(w);
360 WMSetTextFieldText(panel->shoT, panel->shortcuts[row]);
363 static char *trimstr(char *str)
365 char *p = str;
366 int i;
368 while (isspace(*p))
369 p++;
370 p = wstrdup(p);
371 i = strlen(p);
372 while (isspace(p[i]) && i > 0) {
373 p[i] = 0;
374 i--;
377 return p;
380 static void showData(_Panel * panel)
382 char *str;
383 int i;
385 for (i = 0; i < panel->actionCount; i++) {
387 str = GetStringForKey(keyOptions[i]);
388 if (panel->shortcuts[i])
389 wfree(panel->shortcuts[i]);
390 if (str)
391 panel->shortcuts[i] = trimstr(str);
392 else
393 panel->shortcuts[i] = NULL;
395 if (panel->shortcuts[i] &&
396 (strcasecmp(panel->shortcuts[i], "none") == 0 || strlen(panel->shortcuts[i]) == 0)) {
397 wfree(panel->shortcuts[i]);
398 panel->shortcuts[i] = NULL;
401 WMRedisplayWidget(panel->actLs);
404 static void paintItem(WMList * lPtr, int index, Drawable d, char *text, int state, WMRect * rect)
406 int width, height, x, y;
407 _Panel *panel = (_Panel *) WMGetHangedData(lPtr);
408 WMScreen *scr = WMWidgetScreen(lPtr);
409 Display *dpy = WMScreenDisplay(scr);
410 WMColor *backColor = (state & WLDSSelected) ? panel->white : panel->gray;
412 width = rect->size.width;
413 height = rect->size.height;
414 x = rect->pos.x;
415 y = rect->pos.y;
417 XFillRectangle(dpy, d, WMColorGC(backColor), x, y, width, height);
419 if (panel->shortcuts[index]) {
420 WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);
421 WMSize size = WMGetPixmapSize(pix);
423 WMDrawPixmap(pix, d, x + (20 - size.width) / 2, (height - size.height) / 2 + y);
424 WMReleasePixmap(pix);
427 WMDrawString(scr, d, panel->black, panel->font, x + 20, y, text, strlen(text));
430 static void createPanel(Panel * p)
432 _Panel *panel = (_Panel *) p;
433 WMScreen *scr = WMWidgetScreen(panel->parent);
434 WMColor *color;
435 WMFont *boldFont;
437 panel->capturing = 0;
439 panel->white = WMWhiteColor(scr);
440 panel->black = WMBlackColor(scr);
441 panel->gray = WMGrayColor(scr);
442 panel->font = WMSystemFontOfSize(scr, 12);
444 panel->box = WMCreateBox(panel->parent);
445 WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2);
447 boldFont = WMBoldSystemFontOfSize(scr, 12);
449 /* **************** Actions **************** */
450 panel->actL = WMCreateLabel(panel->box);
451 WMResizeWidget(panel->actL, 280, 20);
452 WMMoveWidget(panel->actL, 20, 10);
453 WMSetLabelFont(panel->actL, boldFont);
454 WMSetLabelText(panel->actL, _("Actions"));
455 WMSetLabelRelief(panel->actL, WRSunken);
456 WMSetLabelTextAlignment(panel->actL, WACenter);
457 color = WMDarkGrayColor(scr);
458 WMSetWidgetBackgroundColor(panel->actL, color);
459 WMReleaseColor(color);
460 WMSetLabelTextColor(panel->actL, panel->white);
462 panel->actLs = WMCreateList(panel->box);
463 WMResizeWidget(panel->actLs, 280, 190);
464 WMMoveWidget(panel->actLs, 20, 32);
465 WMSetListUserDrawProc(panel->actLs, paintItem);
466 WMHangData(panel->actLs, panel);
468 WMAddListItem(panel->actLs, _("Open applications menu"));
469 WMAddListItem(panel->actLs, _("Open window list menu"));
470 WMAddListItem(panel->actLs, _("Open window commands menu"));
471 WMAddListItem(panel->actLs, _("Hide active application"));
472 WMAddListItem(panel->actLs, _("Hide other applications"));
473 WMAddListItem(panel->actLs, _("Miniaturize active window"));
474 WMAddListItem(panel->actLs, _("Miniaturize all windows"));
475 WMAddListItem(panel->actLs, _("Close active window"));
476 WMAddListItem(panel->actLs, _("Maximize active window"));
477 WMAddListItem(panel->actLs, _("Maximize active window vertically"));
478 WMAddListItem(panel->actLs, _("Maximize active window horizontally"));
479 WMAddListItem(panel->actLs, _("Maximize active window left half"));
480 WMAddListItem(panel->actLs, _("Maximize active window right half"));
481 WMAddListItem(panel->actLs, _("Maximus: Tiled maximization "));
482 WMAddListItem(panel->actLs, _("Raise active window"));
483 WMAddListItem(panel->actLs, _("Lower active window"));
484 WMAddListItem(panel->actLs, _("Raise/Lower window under mouse pointer"));
485 WMAddListItem(panel->actLs, _("Shade active window"));
486 WMAddListItem(panel->actLs, _("Move/Resize active window"));
487 WMAddListItem(panel->actLs, _("Select active window"));
488 WMAddListItem(panel->actLs, _("Focus next window"));
489 WMAddListItem(panel->actLs, _("Focus previous window"));
490 WMAddListItem(panel->actLs, _("Focus next group window"));
491 WMAddListItem(panel->actLs, _("Focus previous group window"));
492 WMAddListItem(panel->actLs, _("Switch to next workspace"));
493 WMAddListItem(panel->actLs, _("Switch to previous workspace"));
494 WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
495 WMAddListItem(panel->actLs, _("Switch to previous ten workspaces"));
496 WMAddListItem(panel->actLs, _("Switch to workspace 1"));
497 WMAddListItem(panel->actLs, _("Switch to workspace 2"));
498 WMAddListItem(panel->actLs, _("Switch to workspace 3"));
499 WMAddListItem(panel->actLs, _("Switch to workspace 4"));
500 WMAddListItem(panel->actLs, _("Switch to workspace 5"));
501 WMAddListItem(panel->actLs, _("Switch to workspace 6"));
502 WMAddListItem(panel->actLs, _("Switch to workspace 7"));
503 WMAddListItem(panel->actLs, _("Switch to workspace 8"));
504 WMAddListItem(panel->actLs, _("Switch to workspace 9"));
505 WMAddListItem(panel->actLs, _("Switch to workspace 10"));
506 WMAddListItem(panel->actLs, _("Shortcut for window 1"));
507 WMAddListItem(panel->actLs, _("Shortcut for window 2"));
508 WMAddListItem(panel->actLs, _("Shortcut for window 3"));
509 WMAddListItem(panel->actLs, _("Shortcut for window 4"));
510 WMAddListItem(panel->actLs, _("Shortcut for window 5"));
511 WMAddListItem(panel->actLs, _("Shortcut for window 6"));
512 WMAddListItem(panel->actLs, _("Shortcut for window 7"));
513 WMAddListItem(panel->actLs, _("Shortcut for window 8"));
514 WMAddListItem(panel->actLs, _("Shortcut for window 9"));
515 WMAddListItem(panel->actLs, _("Shortcut for window 10"));
516 WMAddListItem(panel->actLs, _("Switch to Next Screen/Monitor"));
517 WMAddListItem(panel->actLs, _("Raise/Lower Dock"));
518 WMAddListItem(panel->actLs, _("Raise/Lower Clip"));
519 #ifdef XKB_MODELOCK
520 WMAddListItem(panel->actLs, _("Toggle keyboard language"));
521 #endif /* XKB_MODELOCK */
523 WMSetListAction(panel->actLs, listClick, panel);
525 panel->actionCount = WMGetListNumberOfRows(panel->actLs);
526 panel->shortcuts = wmalloc(sizeof(char *) * panel->actionCount);
527 memset(panel->shortcuts, 0, sizeof(char *) * panel->actionCount);
529 /***************** Shortcut ****************/
531 panel->shoF = WMCreateFrame(panel->box);
532 WMResizeWidget(panel->shoF, 190, 210);
533 WMMoveWidget(panel->shoF, 315, 10);
534 WMSetFrameTitle(panel->shoF, _("Shortcut"));
536 panel->shoT = WMCreateTextField(panel->shoF);
537 WMResizeWidget(panel->shoT, 160, 20);
538 WMMoveWidget(panel->shoT, 15, 65);
539 WMAddNotificationObserver(typedKeys, panel, WMTextDidChangeNotification, panel->shoT);
541 panel->cleB = WMCreateCommandButton(panel->shoF);
542 WMResizeWidget(panel->cleB, 75, 24);
543 WMMoveWidget(panel->cleB, 15, 95);
544 WMSetButtonText(panel->cleB, _("Clear"));
545 WMSetButtonAction(panel->cleB, clearShortcut, panel);
547 panel->defB = WMCreateCommandButton(panel->shoF);
548 WMResizeWidget(panel->defB, 75, 24);
549 WMMoveWidget(panel->defB, 100, 95);
550 WMSetButtonText(panel->defB, _("Capture"));
551 WMSetButtonAction(panel->defB, captureClick, panel);
553 panel->instructionsL = WMCreateLabel(panel->shoF);
554 WMResizeWidget(panel->instructionsL, 160, 55);
555 WMMoveWidget(panel->instructionsL, 15, 140);
556 WMSetLabelTextAlignment(panel->instructionsL, WACenter);
557 WMSetLabelWraps(panel->instructionsL, True);
558 WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
560 WMMapSubwidgets(panel->shoF);
562 WMReleaseFont(boldFont);
564 WMRealizeWidget(panel->box);
565 WMMapSubwidgets(panel->box);
567 showData(panel);
570 static void storeData(_Panel * panel)
572 int i;
573 char *str;
575 for (i = 0; i < panel->actionCount; i++) {
576 str = NULL;
577 if (panel->shortcuts[i]) {
578 str = trimstr(panel->shortcuts[i]);
579 if (strlen(str) == 0) {
580 wfree(str);
581 str = NULL;
584 if (str) {
585 SetStringForKey(str, keyOptions[i]);
586 wfree(str);
587 } else {
588 SetStringForKey("None", keyOptions[i]);
593 Panel *InitKeyboardShortcuts(WMScreen * scr, WMWidget * parent)
595 _Panel *panel;
597 panel = wmalloc(sizeof(_Panel));
598 memset(panel, 0, sizeof(_Panel));
600 panel->sectionName = _("Keyboard Shortcut Preferences");
602 panel->description = _("Change the keyboard shortcuts for actions such\n"
603 "as changing workspaces and opening menus.");
605 panel->parent = parent;
607 panel->callbacks.createWidgets = createPanel;
608 panel->callbacks.updateDomain = storeData;
610 AddSection(panel, ICON_FILE);
612 return panel;