Improved layout of the Alert Panels
[wmaker-crm.git] / WINGs / wpanel.c
blobc38ba5da31db76b3c8ee477c464ce893f2c76766
2 #include "WINGsP.h"
4 #include <X11/keysym.h>
5 #include <stdint.h>
7 static void alertPanelOnClick(WMWidget * self, void *clientData)
9 WMAlertPanel *panel = clientData;
11 WMBreakModalLoop(WMWidgetScreen(self));
12 if (self == panel->defBtn) {
13 panel->result = WAPRDefault;
14 } else if (self == panel->othBtn) {
15 panel->result = WAPROther;
16 } else if (self == panel->altBtn) {
17 panel->result = WAPRAlternate;
21 static void handleKeyPress(XEvent * event, void *clientData)
23 WMAlertPanel *panel = (WMAlertPanel *) clientData;
24 KeySym ksym;
26 XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
28 if (ksym == XK_Return && panel->defBtn) {
29 WMPerformButtonClick(panel->defBtn);
30 } else if (ksym == XK_Escape) {
31 if (panel->altBtn || panel->othBtn) {
32 WMPerformButtonClick(panel->othBtn ? panel->othBtn : panel->altBtn);
33 } else {
34 panel->result = WAPRDefault;
35 WMBreakModalLoop(WMWidgetScreen(panel->win));
40 int
41 WMRunAlertPanel(WMScreen * scrPtr, WMWindow * owner,
42 const char *title, const char *msg, const char *defaultButton, const char *alternateButton, const char *otherButton)
44 WMAlertPanel *panel;
45 int tmp;
47 panel = WMCreateAlertPanel(scrPtr, owner, title, msg, defaultButton, alternateButton, otherButton);
50 int px, py;
51 WMView *view = WMWidgetView(panel->win);
53 if (owner) {
54 WMView *oview = WMWidgetView(owner);
55 WMPoint pt = WMGetViewScreenPosition(oview);
57 px = (W_VIEW_WIDTH(oview) - W_VIEW_WIDTH(view)) / 2;
58 py = (W_VIEW_HEIGHT(oview) - W_VIEW_HEIGHT(view)) / 2;
60 px += pt.x;
61 py += pt.y;
62 } else {
63 px = (W_VIEW_WIDTH(scrPtr->rootView) - W_VIEW_WIDTH(view)) / 2;
64 py = (W_VIEW_HEIGHT(scrPtr->rootView) - W_VIEW_HEIGHT(view)) / 2;
66 WMSetWindowInitialPosition(panel->win, px, py);
69 WMMapWidget(panel->win);
71 WMRunModalLoop(scrPtr, W_VIEW(panel->win));
73 tmp = panel->result;
75 WMDestroyAlertPanel(panel);
77 return tmp;
80 void WMDestroyAlertPanel(WMAlertPanel * panel)
82 WMUnmapWidget(panel->win);
83 WMDestroyWidget(panel->win);
84 wfree(panel);
87 WMAlertPanel *WMCreateAlertPanel(WMScreen * scrPtr, WMWindow * owner,
88 const char *title, const char *msg, const char *defaultButton,
89 const char *alternateButton, const char *otherButton)
91 WMAlertPanel *panel;
92 int dw = 0, aw = 0, ow = 0, w;
93 WMBox *hbox;
94 WMPixmap *icon;
95 int fw, fh;
96 int pwidth, pheight;
98 panel = wmalloc(sizeof(WMAlertPanel));
100 if (owner) {
101 panel->win = WMCreatePanelWithStyleForWindow(owner, "alertPanel", WMTitledWindowMask);
102 } else {
103 panel->win = WMCreateWindowWithStyle(scrPtr, "alertPanel", WMTitledWindowMask);
106 /* calculate and set the panel's size */
107 WMGetScaleBaseFromSystemFont(scrPtr, &fw, &fh);
108 pwidth = ScaleX(400);
109 pheight = ScaleY(5) /* upper margin */
110 + 64 /* icon size */
111 + ScaleY(5) /* space between icon and divider line */
112 + 2 /* divider line */
113 + ScaleY(5); /* space between divider line and message */
114 if (msg)
115 pheight += WMFontHeight(scrPtr->normalFont) * 4 + ScaleY(5);
116 pheight += ScaleY(44);
117 WMResizeWidget(panel->win, pwidth, pheight);
119 WMSetWindowInitialPosition(panel->win,
120 (scrPtr->rootView->size.width - pwidth) / 2,
121 (scrPtr->rootView->size.height - pheight) / 2);
123 WMSetWindowTitle(panel->win, "");
125 panel->vbox = WMCreateBox(panel->win);
126 WMSetViewExpandsToParent(WMWidgetView(panel->vbox), 0, 0, 0, 0);
127 WMSetBoxHorizontal(panel->vbox, False);
128 WMMapWidget(panel->vbox);
130 hbox = WMCreateBox(panel->vbox);
131 WMSetBoxBorderWidth(hbox, ScaleX(5));
132 WMSetBoxHorizontal(hbox, True);
133 WMMapWidget(hbox);
134 WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 64 + 2 * ScaleY(5), 0, ScaleY(5));
136 panel->iLbl = WMCreateLabel(hbox);
137 WMSetLabelImagePosition(panel->iLbl, WIPImageOnly);
138 WMMapWidget(panel->iLbl);
139 WMAddBoxSubview(hbox, WMWidgetView(panel->iLbl), False, True, 64, 0, 10);
140 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor *) NULL);
141 if (icon) {
142 WMSetLabelImage(panel->iLbl, icon);
143 WMReleasePixmap(icon);
144 } else {
145 WMSetLabelImage(panel->iLbl, scrPtr->applicationIconPixmap);
148 if (title) {
149 WMFont *largeFont;
151 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
153 panel->tLbl = WMCreateLabel(hbox);
154 WMMapWidget(panel->tLbl);
155 WMAddBoxSubview(hbox, WMWidgetView(panel->tLbl), True, True, 64, 0, 0);
156 WMSetLabelText(panel->tLbl, title);
157 WMSetLabelTextAlignment(panel->tLbl, WALeft);
158 WMSetLabelFont(panel->tLbl, largeFont);
160 WMReleaseFont(largeFont);
163 /* create divider line */
165 panel->line = WMCreateFrame(panel->win);
166 WMMapWidget(panel->line);
167 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->line), False, True, 2, 2, ScaleY(5));
168 WMSetFrameRelief(panel->line, WRGroove);
170 if (msg) {
171 panel->mLbl = WMCreateLabel(panel->vbox);
172 WMSetLabelWraps(panel->mLbl, True);
173 WMMapWidget(panel->mLbl);
174 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->mLbl), True, True,
175 WMFontHeight(scrPtr->normalFont) * 4, 0, ScaleY(5));
176 WMSetLabelText(panel->mLbl, msg);
177 WMSetLabelTextAlignment(panel->mLbl, WACenter);
180 panel->hbox = WMCreateBox(panel->vbox);
181 WMSetBoxBorderWidth(panel->hbox, ScaleX(10));
182 WMSetBoxHorizontal(panel->hbox, True);
183 WMMapWidget(panel->hbox);
184 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->hbox), False, True, ScaleY(44), 0, 0);
186 /* create buttons */
187 if (otherButton)
188 ow = WMWidthOfString(scrPtr->normalFont, otherButton, strlen(otherButton));
190 if (alternateButton)
191 aw = WMWidthOfString(scrPtr->normalFont, alternateButton, strlen(alternateButton));
193 if (defaultButton)
194 dw = WMWidthOfString(scrPtr->normalFont, defaultButton, strlen(defaultButton));
196 dw = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
198 aw += ScaleX(30);
199 ow += ScaleX(30);
200 dw += ScaleX(30);
202 w = WMAX(dw, WMAX(aw, ow));
203 if ((w + ScaleX(10)) * 3 < pwidth) {
204 aw = w;
205 ow = w;
206 dw = w;
207 } else {
208 int t;
210 t = pwidth - 4 * ScaleX(10) - aw - ow - dw;
211 aw += t / 3;
212 ow += t / 3;
213 dw += t / 3;
216 if (defaultButton) {
217 panel->defBtn = WMCreateCommandButton(panel->hbox);
218 WMResizeWidget(panel->defBtn, dw, ScaleY(24));
219 WMSetButtonAction(panel->defBtn, alertPanelOnClick, panel);
220 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->defBtn), False, True, dw, 0, 0);
221 WMSetButtonText(panel->defBtn, defaultButton);
222 WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
223 WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
224 WMSetButtonImagePosition(panel->defBtn, WIPRight);
226 if (alternateButton) {
227 panel->altBtn = WMCreateCommandButton(panel->hbox);
228 WMResizeWidget(panel->altBtn, aw, ScaleY(24));
229 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->altBtn), False, True, aw, 0, ScaleX(5));
230 WMSetButtonAction(panel->altBtn, alertPanelOnClick, panel);
231 WMSetButtonText(panel->altBtn, alternateButton);
233 if (otherButton) {
234 panel->othBtn = WMCreateCommandButton(panel->hbox);
235 WMResizeWidget(panel->othBtn, ow, ScaleY(24));
236 WMSetButtonAction(panel->othBtn, alertPanelOnClick, panel);
237 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->othBtn), False, True, ow, 0, ScaleX(5));
238 WMSetButtonText(panel->othBtn, otherButton);
241 WMMapSubwidgets(panel->hbox);
243 WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask, handleKeyPress, panel);
245 WMRealizeWidget(panel->win);
246 WMMapSubwidgets(panel->win);
248 return panel;
251 static void inputBoxOnClick(WMWidget * self, void *clientData)
253 WMInputPanel *panel = clientData;
255 WMBreakModalLoop(WMWidgetScreen(self));
256 if (self == panel->defBtn) {
257 panel->result = WAPRDefault;
258 } else if (self == panel->altBtn) {
259 panel->result = WAPRAlternate;
263 static void handleKeyPress2(XEvent * event, void *clientData)
265 WMInputPanel *panel = (WMInputPanel *) clientData;
266 KeySym ksym;
268 XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
270 if (ksym == XK_Return && panel->defBtn) {
271 WMPerformButtonClick(panel->defBtn);
272 } else if (ksym == XK_Escape) {
273 if (panel->altBtn) {
274 WMPerformButtonClick(panel->altBtn);
275 } else {
276 /* printf("got esc\n"); */
277 WMBreakModalLoop(WMWidgetScreen(panel->win));
278 panel->result = WAPRDefault;
283 char *WMRunInputPanel(WMScreen * scrPtr, WMWindow * owner, const char *title,
284 const char *msg, const char *defaultText, const char *okButton, const char *cancelButton)
286 WMInputPanel *panel;
287 char *tmp;
289 panel = WMCreateInputPanel(scrPtr, owner, title, msg, defaultText, okButton, cancelButton);
292 int px, py;
293 WMView *view = WMWidgetView(panel->win);
295 if (owner) {
296 WMView *oview = WMWidgetView(owner);
297 WMPoint pt = WMGetViewScreenPosition(oview);
299 px = (W_VIEW_WIDTH(oview) - W_VIEW_WIDTH(view)) / 2;
300 py = (W_VIEW_HEIGHT(oview) - W_VIEW_HEIGHT(view)) / 2;
302 px += pt.x;
303 py += pt.y;
304 } else {
305 px = (W_VIEW_WIDTH(scrPtr->rootView) - W_VIEW_WIDTH(view)) / 2;
306 py = (W_VIEW_HEIGHT(scrPtr->rootView) - W_VIEW_HEIGHT(view)) / 2;
308 WMSetWindowInitialPosition(panel->win, px, py);
311 WMMapWidget(panel->win);
313 WMRunModalLoop(scrPtr, W_VIEW(panel->win));
315 if (panel->result == WAPRDefault)
316 tmp = WMGetTextFieldText(panel->text);
317 else
318 tmp = NULL;
320 WMDestroyInputPanel(panel);
322 return tmp;
325 void WMDestroyInputPanel(WMInputPanel * panel)
327 WMRemoveNotificationObserver(panel);
328 WMUnmapWidget(panel->win);
329 WMDestroyWidget(panel->win);
330 wfree(panel);
333 static void endedEditingObserver(void *observerData, WMNotification * notification)
335 WMInputPanel *panel = (WMInputPanel *) observerData;
337 switch ((uintptr_t)WMGetNotificationClientData(notification)) {
338 case WMReturnTextMovement:
339 if (panel->defBtn)
340 WMPerformButtonClick(panel->defBtn);
341 break;
342 case WMEscapeTextMovement:
343 if (panel->altBtn)
344 WMPerformButtonClick(panel->altBtn);
345 else {
346 WMBreakModalLoop(WMWidgetScreen(panel->win));
347 panel->result = WAPRDefault;
349 break;
350 default:
351 break;
355 WMInputPanel *WMCreateInputPanel(WMScreen * scrPtr, WMWindow * owner, const char *title, const char *msg,
356 const char *defaultText, const char *okButton, const char *cancelButton)
358 WMInputPanel *panel;
359 int x, dw = 0, aw = 0, w;
361 panel = wmalloc(sizeof(WMInputPanel));
363 if (owner)
364 panel->win = WMCreatePanelWithStyleForWindow(owner, "inputPanel", WMTitledWindowMask);
365 else
366 panel->win = WMCreateWindowWithStyle(scrPtr, "inputPanel", WMTitledWindowMask);
367 WMSetWindowTitle(panel->win, "");
369 WMResizeWidget(panel->win, 320, 160);
371 if (title) {
372 WMFont *largeFont;
374 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
376 panel->tLbl = WMCreateLabel(panel->win);
377 WMMoveWidget(panel->tLbl, 20, 16);
378 WMResizeWidget(panel->tLbl, 320 - 40, WMFontHeight(largeFont) + 4);
379 WMSetLabelText(panel->tLbl, title);
380 WMSetLabelTextAlignment(panel->tLbl, WALeft);
381 WMSetLabelFont(panel->tLbl, largeFont);
383 WMReleaseFont(largeFont);
386 if (msg) {
387 panel->mLbl = WMCreateLabel(panel->win);
388 WMMoveWidget(panel->mLbl, 20, 50);
389 WMResizeWidget(panel->mLbl, 320 - 40, WMFontHeight(scrPtr->normalFont) * 2);
390 WMSetLabelText(panel->mLbl, msg);
391 WMSetLabelTextAlignment(panel->mLbl, WALeft);
394 panel->text = WMCreateTextField(panel->win);
395 WMMoveWidget(panel->text, 20, 85);
396 WMResizeWidget(panel->text, 320 - 40, WMWidgetHeight(panel->text));
397 WMSetTextFieldText(panel->text, defaultText);
399 WMAddNotificationObserver(endedEditingObserver, panel, WMTextDidEndEditingNotification, panel->text);
401 /* create buttons */
402 if (cancelButton)
403 aw = WMWidthOfString(scrPtr->normalFont, cancelButton, strlen(cancelButton));
405 if (okButton)
406 dw = WMWidthOfString(scrPtr->normalFont, okButton, strlen(okButton));
408 w = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
409 if (aw > w)
410 w = aw;
412 w += 30;
413 x = 310;
415 if (okButton) {
416 x -= w + 10;
418 panel->defBtn = WMCreateCustomButton(panel->win, WBBPushInMask
419 | WBBPushChangeMask | WBBPushLightMask);
420 WMSetButtonAction(panel->defBtn, inputBoxOnClick, panel);
421 WMMoveWidget(panel->defBtn, x, 124);
422 WMResizeWidget(panel->defBtn, w, 24);
423 WMSetButtonText(panel->defBtn, okButton);
424 WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
425 WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
426 WMSetButtonImagePosition(panel->defBtn, WIPRight);
428 if (cancelButton) {
429 x -= w + 10;
431 panel->altBtn = WMCreateCommandButton(panel->win);
432 WMSetButtonAction(panel->altBtn, inputBoxOnClick, panel);
433 WMMoveWidget(panel->altBtn, x, 124);
434 WMResizeWidget(panel->altBtn, w, 24);
435 WMSetButtonText(panel->altBtn, cancelButton);
438 WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask, handleKeyPress2, panel);
440 WMRealizeWidget(panel->win);
441 WMMapSubwidgets(panel->win);
443 WMSetFocusToWidget(panel->text);
445 return panel;
448 static void handleKeyPress3(XEvent * event, void *clientData)
450 WMGenericPanel *panel = (WMGenericPanel *) clientData;
451 KeySym ksym;
453 XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
455 if (ksym == XK_Return && panel->defBtn) {
456 WMPerformButtonClick(panel->defBtn);
457 } else if (ksym == XK_Escape) {
458 if (panel->altBtn) {
459 WMPerformButtonClick(panel->altBtn);
460 } else {
461 panel->result = WAPRDefault;
462 WMBreakModalLoop(WMWidgetScreen(panel->win));
467 void WMDestroyGenericPanel(WMGenericPanel * panel)
469 WMUnmapWidget(panel->win);
470 WMDestroyWidget(panel->win);
471 wfree(panel);
474 WMGenericPanel *WMCreateGenericPanel(WMScreen * scrPtr, WMWindow * owner,
475 const char *title, const char *defaultButton, const char *alternateButton)
477 WMGenericPanel *panel;
478 int dw = 0, aw = 0, w;
479 WMBox *hbox;
480 WMPixmap *icon;
482 panel = wmalloc(sizeof(WMGenericPanel));
484 if (owner) {
485 panel->win = WMCreatePanelWithStyleForWindow(owner, "genericPanel", WMTitledWindowMask);
486 } else {
487 panel->win = WMCreateWindowWithStyle(scrPtr, "genericPanel", WMTitledWindowMask);
490 WMSetWindowInitialPosition(panel->win,
491 (scrPtr->rootView->size.width - WMWidgetWidth(panel->win)) / 2,
492 (scrPtr->rootView->size.height - WMWidgetHeight(panel->win)) / 2);
494 WMSetWindowTitle(panel->win, "");
496 panel->vbox = WMCreateBox(panel->win);
497 WMSetViewExpandsToParent(WMWidgetView(panel->vbox), 0, 0, 0, 0);
498 WMSetBoxHorizontal(panel->vbox, False);
499 WMMapWidget(panel->vbox);
501 hbox = WMCreateBox(panel->vbox);
502 WMSetBoxBorderWidth(hbox, 5);
503 WMSetBoxHorizontal(hbox, True);
504 WMMapWidget(hbox);
505 WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 74, 0, 5);
507 panel->iLbl = WMCreateLabel(hbox);
508 WMSetLabelImagePosition(panel->iLbl, WIPImageOnly);
509 WMMapWidget(panel->iLbl);
510 WMAddBoxSubview(hbox, WMWidgetView(panel->iLbl), False, True, 64, 0, 10);
511 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor *) NULL);
512 if (icon) {
513 WMSetLabelImage(panel->iLbl, icon);
514 WMReleasePixmap(icon);
515 } else {
516 WMSetLabelImage(panel->iLbl, scrPtr->applicationIconPixmap);
519 if (title) {
520 WMFont *largeFont;
522 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
524 panel->tLbl = WMCreateLabel(hbox);
525 WMMapWidget(panel->tLbl);
526 WMAddBoxSubview(hbox, WMWidgetView(panel->tLbl), True, True, 64, 0, 0);
527 WMSetLabelText(panel->tLbl, title);
528 WMSetLabelTextAlignment(panel->tLbl, WALeft);
529 WMSetLabelFont(panel->tLbl, largeFont);
531 WMReleaseFont(largeFont);
534 /* create divider line */
536 panel->line = WMCreateFrame(panel->vbox);
537 WMMapWidget(panel->line);
538 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->line), False, True, 2, 2, 5);
539 WMSetFrameRelief(panel->line, WRGroove);
541 panel->content = WMCreateFrame(panel->vbox);
542 WMMapWidget(panel->content);
543 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->content), True, True, 50, 0, 5);
544 WMSetFrameRelief(panel->content, WRFlat);
546 hbox = WMCreateBox(panel->vbox);
547 WMSetBoxBorderWidth(hbox, 10);
548 WMSetBoxHorizontal(hbox, True);
549 WMMapWidget(hbox);
550 WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 44, 0, 0);
552 /* create buttons */
553 if (defaultButton)
554 dw = WMWidthOfString(scrPtr->normalFont, defaultButton, strlen(defaultButton));
556 if (alternateButton)
557 aw = WMWidthOfString(scrPtr->normalFont, alternateButton, strlen(alternateButton));
559 dw = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
561 aw += 30;
562 dw += 30;
564 w = WMAX(dw, aw);
565 if ((w + 10) * 2 < 400) {
566 dw = w;
567 } else {
568 int t;
570 t = 400 - 40 - aw - dw;
571 dw += t / 2;
574 if (defaultButton) {
575 panel->defBtn = WMCreateCommandButton(hbox);
576 WMSetButtonAction(panel->defBtn, alertPanelOnClick, panel);
577 WMAddBoxSubviewAtEnd(hbox, WMWidgetView(panel->defBtn), False, True, dw, 0, 0);
578 WMSetButtonText(panel->defBtn, defaultButton);
579 WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
580 WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
581 WMSetButtonImagePosition(panel->defBtn, WIPRight);
584 WMMapSubwidgets(hbox);
586 WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask, handleKeyPress3, panel);
588 WMRealizeWidget(panel->win);
589 WMMapSubwidgets(panel->win);
591 return panel;