Mac OS X-style window cycling.
[wmaker-crm.git] / WINGs / wpanel.c
blobf85804f86e83400904fdcdc65ffd4b099e8a1be7
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 char *title, char *msg, char *defaultButton, char *alternateButton, 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 char *title, char *msg, char *defaultButton,
89 char *alternateButton, char *otherButton)
91 WMAlertPanel *panel;
92 int dw = 0, aw = 0, ow = 0, w;
93 WMBox *hbox;
94 WMPixmap *icon;
96 panel = wmalloc(sizeof(WMAlertPanel));
97 memset(panel, 0, sizeof(WMAlertPanel));
99 if (owner) {
100 panel->win = WMCreatePanelWithStyleForWindow(owner, "alertPanel", WMTitledWindowMask);
101 } else {
102 panel->win = WMCreateWindowWithStyle(scrPtr, "alertPanel", WMTitledWindowMask);
105 WMSetWindowInitialPosition(panel->win,
106 (scrPtr->rootView->size.width - WMWidgetWidth(panel->win)) / 2,
107 (scrPtr->rootView->size.height - WMWidgetHeight(panel->win)) / 2);
109 WMSetWindowTitle(panel->win, "");
111 panel->vbox = WMCreateBox(panel->win);
112 WMSetViewExpandsToParent(WMWidgetView(panel->vbox), 0, 0, 0, 0);
113 WMSetBoxHorizontal(panel->vbox, False);
114 WMMapWidget(panel->vbox);
116 hbox = WMCreateBox(panel->vbox);
117 WMSetBoxBorderWidth(hbox, 5);
118 WMSetBoxHorizontal(hbox, True);
119 WMMapWidget(hbox);
120 WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 74, 0, 5);
122 panel->iLbl = WMCreateLabel(hbox);
123 WMSetLabelImagePosition(panel->iLbl, WIPImageOnly);
124 WMMapWidget(panel->iLbl);
125 WMAddBoxSubview(hbox, WMWidgetView(panel->iLbl), False, True, 64, 0, 10);
126 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor *) NULL);
127 if (icon) {
128 WMSetLabelImage(panel->iLbl, icon);
129 WMReleasePixmap(icon);
130 } else {
131 WMSetLabelImage(panel->iLbl, scrPtr->applicationIconPixmap);
134 if (title) {
135 WMFont *largeFont;
137 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
139 panel->tLbl = WMCreateLabel(hbox);
140 WMMapWidget(panel->tLbl);
141 WMAddBoxSubview(hbox, WMWidgetView(panel->tLbl), True, True, 64, 0, 0);
142 WMSetLabelText(panel->tLbl, title);
143 WMSetLabelTextAlignment(panel->tLbl, WALeft);
144 WMSetLabelFont(panel->tLbl, largeFont);
146 WMReleaseFont(largeFont);
149 /* create divider line */
151 panel->line = WMCreateFrame(panel->win);
152 WMMapWidget(panel->line);
153 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->line), False, True, 2, 2, 5);
154 WMSetFrameRelief(panel->line, WRGroove);
156 if (msg) {
157 panel->mLbl = WMCreateLabel(panel->vbox);
158 WMSetLabelWraps(panel->mLbl, True);
159 WMMapWidget(panel->mLbl);
160 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->mLbl), True, True,
161 WMFontHeight(scrPtr->normalFont) * 4, 0, 5);
162 WMSetLabelText(panel->mLbl, msg);
163 WMSetLabelTextAlignment(panel->mLbl, WACenter);
166 panel->hbox = WMCreateBox(panel->vbox);
167 WMSetBoxBorderWidth(panel->hbox, 10);
168 WMSetBoxHorizontal(panel->hbox, True);
169 WMMapWidget(panel->hbox);
170 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->hbox), False, True, 44, 0, 0);
172 /* create buttons */
173 if (otherButton)
174 ow = WMWidthOfString(scrPtr->normalFont, otherButton, strlen(otherButton));
176 if (alternateButton)
177 aw = WMWidthOfString(scrPtr->normalFont, alternateButton, strlen(alternateButton));
179 if (defaultButton)
180 dw = WMWidthOfString(scrPtr->normalFont, defaultButton, strlen(defaultButton));
182 dw = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
184 aw += 30;
185 ow += 30;
186 dw += 30;
188 w = WMAX(dw, WMAX(aw, ow));
189 if ((w + 10) * 3 < 400) {
190 aw = w;
191 ow = w;
192 dw = w;
193 } else {
194 int t;
196 t = 400 - 40 - aw - ow - dw;
197 aw += t / 3;
198 ow += t / 3;
199 dw += t / 3;
202 if (defaultButton) {
203 panel->defBtn = WMCreateCommandButton(panel->hbox);
204 WMSetButtonAction(panel->defBtn, alertPanelOnClick, panel);
205 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->defBtn), False, True, dw, 0, 0);
206 WMSetButtonText(panel->defBtn, defaultButton);
207 WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
208 WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
209 WMSetButtonImagePosition(panel->defBtn, WIPRight);
211 if (alternateButton) {
212 panel->altBtn = WMCreateCommandButton(panel->hbox);
213 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->altBtn), False, True, aw, 0, 5);
214 WMSetButtonAction(panel->altBtn, alertPanelOnClick, panel);
215 WMSetButtonText(panel->altBtn, alternateButton);
217 if (otherButton) {
218 panel->othBtn = WMCreateCommandButton(panel->hbox);
219 WMSetButtonAction(panel->othBtn, alertPanelOnClick, panel);
220 WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->othBtn), False, True, ow, 0, 5);
221 WMSetButtonText(panel->othBtn, otherButton);
224 WMMapSubwidgets(panel->hbox);
226 WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask, handleKeyPress, panel);
228 WMRealizeWidget(panel->win);
229 WMMapSubwidgets(panel->win);
231 return panel;
234 static void inputBoxOnClick(WMWidget * self, void *clientData)
236 WMInputPanel *panel = clientData;
238 WMBreakModalLoop(WMWidgetScreen(self));
239 if (self == panel->defBtn) {
240 panel->result = WAPRDefault;
241 } else if (self == panel->altBtn) {
242 panel->result = WAPRAlternate;
246 static void handleKeyPress2(XEvent * event, void *clientData)
248 WMInputPanel *panel = (WMInputPanel *) clientData;
249 KeySym ksym;
251 XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
253 if (ksym == XK_Return && panel->defBtn) {
254 WMPerformButtonClick(panel->defBtn);
255 } else if (ksym == XK_Escape) {
256 if (panel->altBtn) {
257 WMPerformButtonClick(panel->altBtn);
258 } else {
259 /* printf("got esc\n"); */
260 WMBreakModalLoop(WMWidgetScreen(panel->win));
261 panel->result = WAPRDefault;
266 char *WMRunInputPanel(WMScreen * scrPtr, WMWindow * owner, char *title,
267 char *msg, char *defaultText, char *okButton, char *cancelButton)
269 WMInputPanel *panel;
270 char *tmp;
272 panel = WMCreateInputPanel(scrPtr, owner, title, msg, defaultText, okButton, cancelButton);
275 int px, py;
276 WMView *view = WMWidgetView(panel->win);
278 if (owner) {
279 WMView *oview = WMWidgetView(owner);
280 WMPoint pt = WMGetViewScreenPosition(oview);
282 px = (W_VIEW_WIDTH(oview) - W_VIEW_WIDTH(view)) / 2;
283 py = (W_VIEW_HEIGHT(oview) - W_VIEW_HEIGHT(view)) / 2;
285 px += pt.x;
286 py += pt.y;
287 } else {
288 px = (W_VIEW_WIDTH(scrPtr->rootView) - W_VIEW_WIDTH(view)) / 2;
289 py = (W_VIEW_HEIGHT(scrPtr->rootView) - W_VIEW_HEIGHT(view)) / 2;
291 WMSetWindowInitialPosition(panel->win, px, py);
294 WMMapWidget(panel->win);
296 WMRunModalLoop(scrPtr, W_VIEW(panel->win));
298 if (panel->result == WAPRDefault)
299 tmp = WMGetTextFieldText(panel->text);
300 else
301 tmp = NULL;
303 WMDestroyInputPanel(panel);
305 return tmp;
308 void WMDestroyInputPanel(WMInputPanel * panel)
310 WMRemoveNotificationObserver(panel);
311 WMUnmapWidget(panel->win);
312 WMDestroyWidget(panel->win);
313 wfree(panel);
316 static void endedEditingObserver(void *observerData, WMNotification * notification)
318 WMInputPanel *panel = (WMInputPanel *) observerData;
320 switch ((uintptr_t)WMGetNotificationClientData(notification)) {
321 case WMReturnTextMovement:
322 if (panel->defBtn)
323 WMPerformButtonClick(panel->defBtn);
324 break;
325 case WMEscapeTextMovement:
326 if (panel->altBtn)
327 WMPerformButtonClick(panel->altBtn);
328 else {
329 WMBreakModalLoop(WMWidgetScreen(panel->win));
330 panel->result = WAPRDefault;
332 break;
333 default:
334 break;
338 WMInputPanel *WMCreateInputPanel(WMScreen * scrPtr, WMWindow * owner, char *title, char *msg,
339 char *defaultText, char *okButton, char *cancelButton)
341 WMInputPanel *panel;
342 int x, dw = 0, aw = 0, w;
344 panel = wmalloc(sizeof(WMInputPanel));
345 memset(panel, 0, sizeof(WMInputPanel));
347 if (owner)
348 panel->win = WMCreatePanelWithStyleForWindow(owner, "inputPanel", WMTitledWindowMask);
349 else
350 panel->win = WMCreateWindowWithStyle(scrPtr, "inputPanel", WMTitledWindowMask);
351 WMSetWindowTitle(panel->win, "");
353 WMResizeWidget(panel->win, 320, 160);
355 if (title) {
356 WMFont *largeFont;
358 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
360 panel->tLbl = WMCreateLabel(panel->win);
361 WMMoveWidget(panel->tLbl, 20, 16);
362 WMResizeWidget(panel->tLbl, 320 - 40, WMFontHeight(largeFont) + 4);
363 WMSetLabelText(panel->tLbl, title);
364 WMSetLabelTextAlignment(panel->tLbl, WALeft);
365 WMSetLabelFont(panel->tLbl, largeFont);
367 WMReleaseFont(largeFont);
370 if (msg) {
371 panel->mLbl = WMCreateLabel(panel->win);
372 WMMoveWidget(panel->mLbl, 20, 50);
373 WMResizeWidget(panel->mLbl, 320 - 40, WMFontHeight(scrPtr->normalFont) * 2);
374 WMSetLabelText(panel->mLbl, msg);
375 WMSetLabelTextAlignment(panel->mLbl, WALeft);
378 panel->text = WMCreateTextField(panel->win);
379 WMMoveWidget(panel->text, 20, 85);
380 WMResizeWidget(panel->text, 320 - 40, WMWidgetHeight(panel->text));
381 WMSetTextFieldText(panel->text, defaultText);
383 WMAddNotificationObserver(endedEditingObserver, panel, WMTextDidEndEditingNotification, panel->text);
385 /* create buttons */
386 if (cancelButton)
387 aw = WMWidthOfString(scrPtr->normalFont, cancelButton, strlen(cancelButton));
389 if (okButton)
390 dw = WMWidthOfString(scrPtr->normalFont, okButton, strlen(okButton));
392 w = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
393 if (aw > w)
394 w = aw;
396 w += 30;
397 x = 310;
399 if (okButton) {
400 x -= w + 10;
402 panel->defBtn = WMCreateCustomButton(panel->win, WBBPushInMask
403 | WBBPushChangeMask | WBBPushLightMask);
404 WMSetButtonAction(panel->defBtn, inputBoxOnClick, panel);
405 WMMoveWidget(panel->defBtn, x, 124);
406 WMResizeWidget(panel->defBtn, w, 24);
407 WMSetButtonText(panel->defBtn, okButton);
408 WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
409 WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
410 WMSetButtonImagePosition(panel->defBtn, WIPRight);
412 if (cancelButton) {
413 x -= w + 10;
415 panel->altBtn = WMCreateCommandButton(panel->win);
416 WMSetButtonAction(panel->altBtn, inputBoxOnClick, panel);
417 WMMoveWidget(panel->altBtn, x, 124);
418 WMResizeWidget(panel->altBtn, w, 24);
419 WMSetButtonText(panel->altBtn, cancelButton);
422 WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask, handleKeyPress2, panel);
424 WMRealizeWidget(panel->win);
425 WMMapSubwidgets(panel->win);
427 WMSetFocusToWidget(panel->text);
429 return panel;
432 static void handleKeyPress3(XEvent * event, void *clientData)
434 WMGenericPanel *panel = (WMGenericPanel *) clientData;
435 KeySym ksym;
437 XLookupString(&event->xkey, NULL, 0, &ksym, NULL);
439 if (ksym == XK_Return && panel->defBtn) {
440 WMPerformButtonClick(panel->defBtn);
441 } else if (ksym == XK_Escape) {
442 if (panel->altBtn) {
443 WMPerformButtonClick(panel->altBtn);
444 } else {
445 panel->result = WAPRDefault;
446 WMBreakModalLoop(WMWidgetScreen(panel->win));
451 void WMDestroyGenericPanel(WMGenericPanel * panel)
453 WMUnmapWidget(panel->win);
454 WMDestroyWidget(panel->win);
455 wfree(panel);
458 WMGenericPanel *WMCreateGenericPanel(WMScreen * scrPtr, WMWindow * owner,
459 char *title, char *defaultButton, char *alternateButton)
461 WMGenericPanel *panel;
462 int dw = 0, aw = 0, w;
463 WMBox *hbox;
464 WMPixmap *icon;
466 panel = wmalloc(sizeof(WMGenericPanel));
467 memset(panel, 0, sizeof(WMGenericPanel));
469 if (owner) {
470 panel->win = WMCreatePanelWithStyleForWindow(owner, "genericPanel", WMTitledWindowMask);
471 } else {
472 panel->win = WMCreateWindowWithStyle(scrPtr, "genericPanel", WMTitledWindowMask);
475 WMSetWindowInitialPosition(panel->win,
476 (scrPtr->rootView->size.width - WMWidgetWidth(panel->win)) / 2,
477 (scrPtr->rootView->size.height - WMWidgetHeight(panel->win)) / 2);
479 WMSetWindowTitle(panel->win, "");
481 panel->vbox = WMCreateBox(panel->win);
482 WMSetViewExpandsToParent(WMWidgetView(panel->vbox), 0, 0, 0, 0);
483 WMSetBoxHorizontal(panel->vbox, False);
484 WMMapWidget(panel->vbox);
486 hbox = WMCreateBox(panel->vbox);
487 WMSetBoxBorderWidth(hbox, 5);
488 WMSetBoxHorizontal(hbox, True);
489 WMMapWidget(hbox);
490 WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 74, 0, 5);
492 panel->iLbl = WMCreateLabel(hbox);
493 WMSetLabelImagePosition(panel->iLbl, WIPImageOnly);
494 WMMapWidget(panel->iLbl);
495 WMAddBoxSubview(hbox, WMWidgetView(panel->iLbl), False, True, 64, 0, 10);
496 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor *) NULL);
497 if (icon) {
498 WMSetLabelImage(panel->iLbl, icon);
499 WMReleasePixmap(icon);
500 } else {
501 WMSetLabelImage(panel->iLbl, scrPtr->applicationIconPixmap);
504 if (title) {
505 WMFont *largeFont;
507 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
509 panel->tLbl = WMCreateLabel(hbox);
510 WMMapWidget(panel->tLbl);
511 WMAddBoxSubview(hbox, WMWidgetView(panel->tLbl), True, True, 64, 0, 0);
512 WMSetLabelText(panel->tLbl, title);
513 WMSetLabelTextAlignment(panel->tLbl, WALeft);
514 WMSetLabelFont(panel->tLbl, largeFont);
516 WMReleaseFont(largeFont);
519 /* create divider line */
521 panel->line = WMCreateFrame(panel->vbox);
522 WMMapWidget(panel->line);
523 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->line), False, True, 2, 2, 5);
524 WMSetFrameRelief(panel->line, WRGroove);
526 panel->content = WMCreateFrame(panel->vbox);
527 WMMapWidget(panel->content);
528 WMAddBoxSubview(panel->vbox, WMWidgetView(panel->content), True, True, 50, 0, 5);
529 WMSetFrameRelief(panel->content, WRFlat);
531 hbox = WMCreateBox(panel->vbox);
532 WMSetBoxBorderWidth(hbox, 10);
533 WMSetBoxHorizontal(hbox, True);
534 WMMapWidget(hbox);
535 WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 44, 0, 0);
537 /* create buttons */
538 if (defaultButton)
539 dw = WMWidthOfString(scrPtr->normalFont, defaultButton, strlen(defaultButton));
541 if (alternateButton)
542 aw = WMWidthOfString(scrPtr->normalFont, alternateButton, strlen(alternateButton));
544 dw = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
546 aw += 30;
547 dw += 30;
549 w = WMAX(dw, aw);
550 if ((w + 10) * 2 < 400) {
551 aw = w;
552 dw = w;
553 } else {
554 int t;
556 t = 400 - 40 - aw - dw;
557 aw += t / 2;
558 dw += t / 2;
561 if (defaultButton) {
562 panel->defBtn = WMCreateCommandButton(hbox);
563 WMSetButtonAction(panel->defBtn, alertPanelOnClick, panel);
564 WMAddBoxSubviewAtEnd(hbox, WMWidgetView(panel->defBtn), False, True, dw, 0, 0);
565 WMSetButtonText(panel->defBtn, defaultButton);
566 WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
567 WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
568 WMSetButtonImagePosition(panel->defBtn, WIPRight);
571 WMMapSubwidgets(hbox);
573 WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask, handleKeyPress3, panel);
575 WMRealizeWidget(panel->win);
576 WMMapSubwidgets(panel->win);
578 return panel;