#include "WINGsP.h"

#include <X11/keysym.h>



static void
alertPanelOnClick(WMWidget *self, void *clientData)
{
    WMAlertPanel *panel = clientData;

    WMBreakModalLoop(WMWidgetScreen(self));
    if (self == panel->defBtn) {
        panel->result = WAPRDefault;
    } else if (self == panel->othBtn) {
        panel->result = WAPROther;
    } else if (self == panel->altBtn) {
        panel->result = WAPRAlternate;
    }
}


static void
handleKeyPress(XEvent *event, void *clientData)
{
    WMAlertPanel *panel = (WMAlertPanel*)clientData;
    KeySym ksym;

    XLookupString(&event->xkey, NULL, 0, &ksym, NULL);

    if (ksym == XK_Return && panel->defBtn) {
        WMPerformButtonClick(panel->defBtn);
    } else if (ksym == XK_Escape) {
        if (panel->altBtn || panel->othBtn) {
            WMPerformButtonClick(panel->othBtn ? panel->othBtn : panel->altBtn);
        } else {
            panel->result = WAPRDefault;
            WMBreakModalLoop(WMWidgetScreen(panel->win));
        }
    }
}


int
WMRunAlertPanel(WMScreen *scrPtr, WMWindow *owner,
                char *title, char *msg, char *defaultButton,
                char *alternateButton, char *otherButton)
{
    WMAlertPanel *panel;
    int tmp;

    panel = WMCreateAlertPanel(scrPtr, owner, title, msg, defaultButton,
                               alternateButton, otherButton);

    {
        int px, py;
        WMView *view = WMWidgetView(panel->win);

        if (owner) {
            WMView *oview = WMWidgetView(owner);
            WMPoint pt = WMGetViewScreenPosition(oview);

            px = (W_VIEW_WIDTH(oview)-W_VIEW_WIDTH(view))/2;
            py = (W_VIEW_HEIGHT(oview)-W_VIEW_HEIGHT(view))/2;

            px += pt.x;
            py += pt.y;
        } else {
            px = (W_VIEW_WIDTH(scrPtr->rootView)-W_VIEW_WIDTH(view))/2;
            py = (W_VIEW_HEIGHT(scrPtr->rootView)-W_VIEW_HEIGHT(view))/2;
        }
        WMSetWindowInitialPosition(panel->win, px, py);
    }

    WMMapWidget(panel->win);

    WMRunModalLoop(scrPtr, W_VIEW(panel->win));

    tmp = panel->result;

    WMDestroyAlertPanel(panel);

    return tmp;
}


void
WMDestroyAlertPanel(WMAlertPanel *panel)
{
    WMUnmapWidget(panel->win);
    WMDestroyWidget(panel->win);
    wfree(panel);
}


WMAlertPanel*
WMCreateAlertPanel(WMScreen *scrPtr, WMWindow *owner,
                   char *title, char *msg, char *defaultButton,
                   char *alternateButton, char *otherButton)
{
    WMAlertPanel *panel;
    int dw=0, aw=0, ow=0, w;
    WMBox *hbox;
    WMPixmap *icon;


    panel = wmalloc(sizeof(WMAlertPanel));
    memset(panel, 0, sizeof(WMAlertPanel));

    if (owner) {
        panel->win = WMCreatePanelWithStyleForWindow(owner, "alertPanel",
                                                     WMTitledWindowMask);
    } else {
        panel->win = WMCreateWindowWithStyle(scrPtr, "alertPanel",
                                             WMTitledWindowMask);
    }

    WMSetWindowInitialPosition(panel->win,
                               (scrPtr->rootView->size.width - WMWidgetWidth(panel->win))/2,
                               (scrPtr->rootView->size.height - WMWidgetHeight(panel->win))/2);

    WMSetWindowTitle(panel->win, "");

    panel->vbox = WMCreateBox(panel->win);
    WMSetViewExpandsToParent(WMWidgetView(panel->vbox), 0, 0, 0, 0);
    WMSetBoxHorizontal(panel->vbox, False);
    WMMapWidget(panel->vbox);

    hbox = WMCreateBox(panel->vbox);
    WMSetBoxBorderWidth(hbox, 5);
    WMSetBoxHorizontal(hbox, True);
    WMMapWidget(hbox);
    WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 74, 0, 5);

    panel->iLbl = WMCreateLabel(hbox);
    WMSetLabelImagePosition(panel->iLbl, WIPImageOnly);
    WMMapWidget(panel->iLbl);
    WMAddBoxSubview(hbox, WMWidgetView(panel->iLbl), False, True, 64, 0, 10);
    icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor*)NULL);
    if (icon) {
        WMSetLabelImage(panel->iLbl, icon);
        WMReleasePixmap(icon);
    } else {
        WMSetLabelImage(panel->iLbl, scrPtr->applicationIconPixmap);
    }

    if (title) {
        WMFont *largeFont;

        largeFont = WMBoldSystemFontOfSize(scrPtr, 24);

        panel->tLbl = WMCreateLabel(hbox);
        WMMapWidget(panel->tLbl);
        WMAddBoxSubview(hbox, WMWidgetView(panel->tLbl), True, True,
                        64, 0, 0);
        WMSetLabelText(panel->tLbl, title);
        WMSetLabelTextAlignment(panel->tLbl, WALeft);
        WMSetLabelFont(panel->tLbl, largeFont);

        WMReleaseFont(largeFont);
    }

    /* create divider line */

    panel->line = WMCreateFrame(panel->win);
    WMMapWidget(panel->line);
    WMAddBoxSubview(panel->vbox, WMWidgetView(panel->line), False, True,
                    2, 2, 5);
    WMSetFrameRelief(panel->line, WRGroove);


    if (msg) {
        panel->mLbl = WMCreateLabel(panel->vbox);
        WMSetLabelWraps(panel->mLbl, True);
        WMMapWidget(panel->mLbl);
        WMAddBoxSubview(panel->vbox, WMWidgetView(panel->mLbl), True, True,
                        WMFontHeight(scrPtr->normalFont)*4, 0, 5);
        WMSetLabelText(panel->mLbl, msg);
        WMSetLabelTextAlignment(panel->mLbl, WACenter);
    }

    panel->hbox = WMCreateBox(panel->vbox);
    WMSetBoxBorderWidth(panel->hbox, 10);
    WMSetBoxHorizontal(panel->hbox, True);
    WMMapWidget(panel->hbox);
    WMAddBoxSubview(panel->vbox, WMWidgetView(panel->hbox), False, True, 44, 0, 0);

    /* create buttons */
    if (otherButton)
        ow = WMWidthOfString(scrPtr->normalFont, otherButton,
                             strlen(otherButton));

    if (alternateButton)
        aw = WMWidthOfString(scrPtr->normalFont, alternateButton,
                             strlen(alternateButton));

    if (defaultButton)
        dw = WMWidthOfString(scrPtr->normalFont, defaultButton,
                             strlen(defaultButton));

    dw = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);

    aw += 30;
    ow += 30;
    dw += 30;

    w = WMAX(dw, WMAX(aw, ow));
    if ((w+10)*3 < 400) {
        aw = w;
        ow = w;
        dw = w;
    } else {
        int t;

        t = 400 - 40 - aw - ow - dw;
        aw += t/3;
        ow += t/3;
        dw += t/3;
    }

    if (defaultButton) {
        panel->defBtn = WMCreateCommandButton(panel->hbox);
        WMSetButtonAction(panel->defBtn, alertPanelOnClick, panel);
        WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->defBtn),
                             False, True, dw, 0, 0);
        WMSetButtonText(panel->defBtn, defaultButton);
        WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
        WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
        WMSetButtonImagePosition(panel->defBtn, WIPRight);
    }
    if (alternateButton) {
        panel->altBtn = WMCreateCommandButton(panel->hbox);
        WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->altBtn),
                             False, True, aw, 0, 5);
        WMSetButtonAction(panel->altBtn, alertPanelOnClick, panel);
        WMSetButtonText(panel->altBtn, alternateButton);
    }
    if (otherButton) {
        panel->othBtn = WMCreateCommandButton(panel->hbox);
        WMSetButtonAction(panel->othBtn, alertPanelOnClick, panel);
        WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(panel->othBtn),
                             False, True, ow, 0, 5);
        WMSetButtonText(panel->othBtn, otherButton);
    }

    WMMapSubwidgets(panel->hbox);

    WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask,
                         handleKeyPress, panel);

    WMRealizeWidget(panel->win);
    WMMapSubwidgets(panel->win);

    return panel;
}





static void
inputBoxOnClick(WMWidget *self, void *clientData)
{
    WMInputPanel *panel = clientData;

    WMBreakModalLoop(WMWidgetScreen(self));
    if (self == panel->defBtn) {
        panel->result = WAPRDefault;
    } else if (self == panel->altBtn) {
        panel->result = WAPRAlternate;
    }
}



static void
handleKeyPress2(XEvent *event, void *clientData)
{
    WMInputPanel *panel = (WMInputPanel*)clientData;
    KeySym ksym;

    XLookupString(&event->xkey, NULL, 0, &ksym, NULL);

    if (ksym == XK_Return && panel->defBtn) {
        WMPerformButtonClick(panel->defBtn);
    } else if (ksym == XK_Escape) {
        if (panel->altBtn) {
            WMPerformButtonClick(panel->altBtn);
        } else {
            /*           printf("got esc\n");*/
            WMBreakModalLoop(WMWidgetScreen(panel->win));
            panel->result = WAPRDefault;
        }
    }
}


char*
WMRunInputPanel(WMScreen *scrPtr, WMWindow *owner, char *title,
                char *msg, char *defaultText,
                char *okButton, char *cancelButton)
{
    WMInputPanel *panel;
    char *tmp;

    panel = WMCreateInputPanel(scrPtr, owner, title, msg, defaultText,
                               okButton, cancelButton);


    {
        int px, py;
        WMView *view = WMWidgetView(panel->win);

        if (owner) {
            WMView *oview = WMWidgetView(owner);
            WMPoint pt = WMGetViewScreenPosition(oview);

            px = (W_VIEW_WIDTH(oview)-W_VIEW_WIDTH(view))/2;
            py = (W_VIEW_HEIGHT(oview)-W_VIEW_HEIGHT(view))/2;

            px += pt.x;
            py += pt.y;
        } else {
            px = (W_VIEW_WIDTH(scrPtr->rootView)-W_VIEW_WIDTH(view))/2;
            py = (W_VIEW_HEIGHT(scrPtr->rootView)-W_VIEW_HEIGHT(view))/2;
        }
        WMSetWindowInitialPosition(panel->win, px, py);
    }

    WMMapWidget(panel->win);

    WMRunModalLoop(scrPtr, W_VIEW(panel->win));

    if (panel->result == WAPRDefault)
        tmp = WMGetTextFieldText(panel->text);
    else
        tmp = NULL;

    WMDestroyInputPanel(panel);

    return tmp;
}


void
WMDestroyInputPanel(WMInputPanel *panel)
{
    WMRemoveNotificationObserver(panel);
    WMUnmapWidget(panel->win);
    WMDestroyWidget(panel->win);
    wfree(panel);
}



static void
endedEditingObserver(void *observerData, WMNotification *notification)
{
    WMInputPanel *panel = (WMInputPanel*)observerData;

    switch ((int)WMGetNotificationClientData(notification)) {
    case WMReturnTextMovement:
        if (panel->defBtn)
            WMPerformButtonClick(panel->defBtn);
        break;
    case WMEscapeTextMovement:
        if (panel->altBtn)
            WMPerformButtonClick(panel->altBtn);
        else {
            WMBreakModalLoop(WMWidgetScreen(panel->win));
            panel->result = WAPRDefault;
        }
        break;
    default:
        break;
    }
}


WMInputPanel*
WMCreateInputPanel(WMScreen *scrPtr, WMWindow *owner, char *title, char *msg,
                   char *defaultText, char *okButton, char *cancelButton)
{
    WMInputPanel *panel;
    int x, dw=0, aw=0, w;


    panel = wmalloc(sizeof(WMInputPanel));
    memset(panel, 0, sizeof(WMInputPanel));

    if (owner)
        panel->win = WMCreatePanelWithStyleForWindow(owner, "inputPanel",
                                                     WMTitledWindowMask);
    else
        panel->win = WMCreateWindowWithStyle(scrPtr, "inputPanel",
                                             WMTitledWindowMask);
    WMSetWindowTitle(panel->win, "");

    WMResizeWidget(panel->win, 320, 160);

    if (title) {
        WMFont *largeFont;

        largeFont = WMBoldSystemFontOfSize(scrPtr, 24);

        panel->tLbl = WMCreateLabel(panel->win);
        WMMoveWidget(panel->tLbl, 20, 16);
        WMResizeWidget(panel->tLbl, 320 - 40, WMFontHeight(largeFont)+4);
        WMSetLabelText(panel->tLbl, title);
        WMSetLabelTextAlignment(panel->tLbl, WALeft);
        WMSetLabelFont(panel->tLbl, largeFont);

        WMReleaseFont(largeFont);
    }


    if (msg) {
        panel->mLbl = WMCreateLabel(panel->win);
        WMMoveWidget(panel->mLbl, 20, 50);
        WMResizeWidget(panel->mLbl, 320 - 40,
                       WMFontHeight(scrPtr->normalFont)*2);
        WMSetLabelText(panel->mLbl, msg);
        WMSetLabelTextAlignment(panel->mLbl, WALeft);
    }

    panel->text = WMCreateTextField(panel->win);
    WMMoveWidget(panel->text, 20, 85);
    WMResizeWidget(panel->text, 320 - 40, WMWidgetHeight(panel->text));
    WMSetTextFieldText(panel->text, defaultText);

    WMAddNotificationObserver(endedEditingObserver, panel,
                              WMTextDidEndEditingNotification, panel->text);

    /* create buttons */
    if (cancelButton)
        aw = WMWidthOfString(scrPtr->normalFont, cancelButton,
                             strlen(cancelButton));

    if (okButton)
        dw = WMWidthOfString(scrPtr->normalFont, okButton,
                             strlen(okButton));

    w = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);
    if (aw > w)
        w = aw;

    w += 30;
    x = 310;

    if (okButton) {
        x -= w + 10;

        panel->defBtn = WMCreateCustomButton(panel->win, WBBPushInMask
                                             |WBBPushChangeMask
                                             |WBBPushLightMask);
        WMSetButtonAction(panel->defBtn, inputBoxOnClick, panel);
        WMMoveWidget(panel->defBtn, x, 124);
        WMResizeWidget(panel->defBtn, w, 24);
        WMSetButtonText(panel->defBtn, okButton);
        WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
        WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
        WMSetButtonImagePosition(panel->defBtn, WIPRight);
    }
    if (cancelButton) {
        x -= w + 10;

        panel->altBtn = WMCreateCommandButton(panel->win);
        WMSetButtonAction(panel->altBtn, inputBoxOnClick, panel);
        WMMoveWidget(panel->altBtn, x, 124);
        WMResizeWidget(panel->altBtn, w, 24);
        WMSetButtonText(panel->altBtn, cancelButton);
    }

    WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask,
                         handleKeyPress2, panel);

    WMRealizeWidget(panel->win);
    WMMapSubwidgets(panel->win);

    WMSetFocusToWidget(panel->text);

    return panel;
}




static void
handleKeyPress3(XEvent *event, void *clientData)
{
    WMGenericPanel *panel = (WMGenericPanel*)clientData;
    KeySym ksym;

    XLookupString(&event->xkey, NULL, 0, &ksym, NULL);

    if (ksym == XK_Return && panel->defBtn) {
        WMPerformButtonClick(panel->defBtn);
    } else if (ksym == XK_Escape) {
        if (panel->altBtn) {
            WMPerformButtonClick(panel->altBtn);
        } else {
            panel->result = WAPRDefault;
            WMBreakModalLoop(WMWidgetScreen(panel->win));
        }
    }
}


void
WMDestroyGenericPanel(WMGenericPanel *panel)
{
    WMUnmapWidget(panel->win);
    WMDestroyWidget(panel->win);
    wfree(panel);
}


WMGenericPanel*
WMCreateGenericPanel(WMScreen *scrPtr, WMWindow *owner,
                     char *title, char *defaultButton,
                     char *alternateButton)
{
    WMGenericPanel *panel;
    int dw=0, aw=0, w;
    WMBox *hbox;
    WMPixmap *icon;


    panel = wmalloc(sizeof(WMGenericPanel));
    memset(panel, 0, sizeof(WMGenericPanel));

    if (owner) {
        panel->win = WMCreatePanelWithStyleForWindow(owner, "genericPanel",
                                                     WMTitledWindowMask);
    } else {
        panel->win = WMCreateWindowWithStyle(scrPtr, "genericPanel",
                                             WMTitledWindowMask);
    }

    WMSetWindowInitialPosition(panel->win,
                               (scrPtr->rootView->size.width - WMWidgetWidth(panel->win))/2,
                               (scrPtr->rootView->size.height - WMWidgetHeight(panel->win))/2);

    WMSetWindowTitle(panel->win, "");

    panel->vbox = WMCreateBox(panel->win);
    WMSetViewExpandsToParent(WMWidgetView(panel->vbox), 0, 0, 0, 0);
    WMSetBoxHorizontal(panel->vbox, False);
    WMMapWidget(panel->vbox);

    hbox = WMCreateBox(panel->vbox);
    WMSetBoxBorderWidth(hbox, 5);
    WMSetBoxHorizontal(hbox, True);
    WMMapWidget(hbox);
    WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 74, 0, 5);

    panel->iLbl = WMCreateLabel(hbox);
    WMSetLabelImagePosition(panel->iLbl, WIPImageOnly);
    WMMapWidget(panel->iLbl);
    WMAddBoxSubview(hbox, WMWidgetView(panel->iLbl), False, True, 64, 0, 10);
    icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor*)NULL);
    if (icon) {
        WMSetLabelImage(panel->iLbl, icon);
        WMReleasePixmap(icon);
    } else {
        WMSetLabelImage(panel->iLbl, scrPtr->applicationIconPixmap);
    }

    if (title) {
        WMFont *largeFont;

        largeFont = WMBoldSystemFontOfSize(scrPtr, 24);

        panel->tLbl = WMCreateLabel(hbox);
        WMMapWidget(panel->tLbl);
        WMAddBoxSubview(hbox, WMWidgetView(panel->tLbl), True, True,
                        64, 0, 0);
        WMSetLabelText(panel->tLbl, title);
        WMSetLabelTextAlignment(panel->tLbl, WALeft);
        WMSetLabelFont(panel->tLbl, largeFont);

        WMReleaseFont(largeFont);
    }

    /* create divider line */

    panel->line = WMCreateFrame(panel->vbox);
    WMMapWidget(panel->line);
    WMAddBoxSubview(panel->vbox, WMWidgetView(panel->line), False, True,
                    2, 2, 5);
    WMSetFrameRelief(panel->line, WRGroove);


    panel->content = WMCreateFrame(panel->vbox);
    WMMapWidget(panel->content);
    WMAddBoxSubview(panel->vbox, WMWidgetView(panel->content), True, True,
                    50, 0, 5);
    WMSetFrameRelief(panel->content, WRFlat);

    hbox = WMCreateBox(panel->vbox);
    WMSetBoxBorderWidth(hbox, 10);
    WMSetBoxHorizontal(hbox, True);
    WMMapWidget(hbox);
    WMAddBoxSubview(panel->vbox, WMWidgetView(hbox), False, True, 44, 0, 0);

    /* create buttons */
    if (defaultButton)
        dw = WMWidthOfString(scrPtr->normalFont, defaultButton,
                             strlen(defaultButton));

    if (alternateButton)
        aw = WMWidthOfString(scrPtr->normalFont, alternateButton,
                             strlen(alternateButton));


    dw = dw + (scrPtr->buttonArrow ? scrPtr->buttonArrow->width : 0);

    aw += 30;
    dw += 30;

    w = WMAX(dw, aw);
    if ((w+10)*2 < 400) {
        aw = w;
        dw = w;
    } else {
        int t;

        t = 400 - 40 - aw - dw;
        aw += t/2;
        dw += t/2;
    }

    if (defaultButton) {
        panel->defBtn = WMCreateCommandButton(hbox);
        WMSetButtonAction(panel->defBtn, alertPanelOnClick, panel);
        WMAddBoxSubviewAtEnd(hbox, WMWidgetView(panel->defBtn),
                             False, True, dw, 0, 0);
        WMSetButtonText(panel->defBtn, defaultButton);
        WMSetButtonImage(panel->defBtn, scrPtr->buttonArrow);
        WMSetButtonAltImage(panel->defBtn, scrPtr->pushedButtonArrow);
        WMSetButtonImagePosition(panel->defBtn, WIPRight);
    }

    WMMapSubwidgets(hbox);

    WMCreateEventHandler(W_VIEW(panel->win), KeyPressMask,
                         handleKeyPress3, panel);

    WMRealizeWidget(panel->win);
    WMMapSubwidgets(panel->win);

    return panel;
}




syntax highlighted by Code2HTML, v. 0.9.1