/* winspector.c - window attribute inspector
 * 
 *  WindowMaker window manager
 * 
 *  Copyright (c) 1997 Alfredo K. Kojima
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "wconfig.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "generic/wwmlib.h"
#include "WindowMaker.h"
#include "screen.h"
#include "wcore.h"
#include "framewin.h"
#include "window.h"
#include "workspace.h"
#include "funcs.h"
#include "defaults.h"
#include "dialog.h"

#include <proplist.h>


typedef struct InspectorPanel {
    struct InspectorPanel *nextPtr;

    WWindow *frame;

  WWindow *inspected;       /* the window that's being inspected */

    WMWindow *win;

    /* common stuff */
    WMButton *revertBtn;
    WMButton *applyBtn;
    WMButton *saveBtn;

    WMButton *pageBtn1;
    WMButton *pageBtn2;
    WMButton *pageBtn3;
    WMButton *pageBtn4;

    /* first page. general stuff */
    
    WMFrame *specFrm;
    WMButton *instRb;
    WMButton *clsRb;
    WMButton *bothRb;

    WMLabel *specLbl;
    
    /* second page. attributes */
    
    WMFrame *attrFrm;
    WMButton *attrChk[9];
    
    /* 3rd page. more attributes */
    WMFrame *moreFrm;
    WMButton *moreChk[7];
    
    
    /* 4th page. icon and workspace */
    WMFrame *iconFrm;
    WMLabel *iconLbl;
    WMLabel *fileLbl;
    WMTextField *fileText;
    WMButton *alwChk;
    WMButton *updateIconBtn;
    WMButton *defaultIconBtn;
    
    WMFrame *wsFrm;
    WMButton *curRb;
    WMButton *setRb;
    WMTextField *wsText;
    
} InspectorPanel;


static InspectorPanel *panelList=NULL;


#define PWIDTH	260
#define PHEIGHT	350


#define COUNTARG(table)		(sizeof(table)/sizeof(WMArgument))




static WMArgument panelArgs[] = {
    {WARG_WIDTH,		(WMValue)PWIDTH},
    {WARG_HEIGHT,		(WMValue)PHEIGHT}
};

static WMArgument buttonArgs[] = {
    {WARG_X,			(WMValue)0},
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y,			(WMValue)310},
    {WARG_WIDTH,		(WMValue)62}
};

static WMArgument pageBtnArgs[] = {
    {WARG_X,			(WMValue)0},
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y,			(WMValue)10},
    {WARG_WIDTH,		(WMValue)30},
    {WARG_HEIGHT,		(WMValue)30},
    {WARG_TAG,			(WMValue)1}
};

static WMArgument specFrmArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_X,			(WMValue)40},
    {WARG_Y, 			(WMValue)65},
    {WARG_WIDTH,		(WMValue)180},
    {WARG_HEIGHT,		(WMValue)85}
};

static WMArgument specLblArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_ALIGNMENT,		(WMValue)WACenter},
    {WARG_X,			(WMValue)20},
    {WARG_Y,			(WMValue)170},
    {WARG_WIDTH,		(WMValue)210},
    {WARG_HEIGHT,		(WMValue)100}
};

static WMArgument specRadArgs[] = {
    {WARG_Y,			(WMValue)0},
    {WARG_CAPTION, 		(WMValue)NULL},
    {WARG_SELECTED,		(WMValue)1},
    {WARG_X, 			(WMValue)10},
    {WARG_WIDTH,		(WMValue)160},
    {WARG_TAG,			(WMValue)1}
};


static WMArgument attrFrmArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_X,			(WMValue)20},
    {WARG_Y, 			(WMValue)65},
    {WARG_WIDTH,		(WMValue)220},
    {WARG_HEIGHT,		(WMValue)210}
};

static WMArgument attrChkArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y, 			(WMValue)20},
    {WARG_SELECTED,		(WMValue)0},
    {WARG_X,			(WMValue)5},
    {WARG_WIDTH,		(WMValue)205},
    {WARG_HEIGHT,		(WMValue)20}
};


static WMArgument iconFrmArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y, 			(WMValue)50},
    {WARG_X,			(WMValue)15},
    {WARG_WIDTH,		(WMValue)230},
    {WARG_HEIGHT,		(WMValue)170}
};

static WMArgument wsFrmArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y, 			(WMValue)225},
    {WARG_X,			(WMValue)15},
    {WARG_WIDTH,		(WMValue)230},
    {WARG_HEIGHT,		(WMValue)70}
};


static WMArgument iconLblArgs[] = {
    {WARG_X,			(WMValue)130},
    {WARG_Y, 			(WMValue)30},
    {WARG_WIDTH,		(WMValue)64},
    {WARG_HEIGHT,		(WMValue)64},
    {WARG_RELIEF,		(WMValue)WRRaised},
    {WARG_IMAGE_POSITION,	(WMValue)WIPImageOnly}
};


static WMArgument updateIconBtnArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y, 			(WMValue)35},
    {WARG_X,			(WMValue)22},
    {WARG_WIDTH,		(WMValue)70}
};

static WMArgument fileLblArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_X,			(WMValue)20},
    {WARG_Y, 			(WMValue)95},
    {WARG_WIDTH,		(WMValue)104}
};

static WMArgument fileArgs[] = {
    {WARG_TEXT,			(WMValue)NULL},
    {WARG_X,			(WMValue)20},
    {WARG_Y, 			(WMValue)115},
    {WARG_WIDTH,		(WMValue)186}
};

static WMArgument alwChkArgs[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_X,			(WMValue)20},
    {WARG_Y, 			(WMValue)140},
    {WARG_WIDTH,		(WMValue)186}
};



static WMArgument workspaceArgs[] = {
    {WARG_TEXT,			(WMValue)NULL},
    {WARG_X,			(WMValue)30},
    {WARG_Y, 			(WMValue)40},
    {WARG_WIDTH,		(WMValue)170}
};

static WMArgument wsRad1Args[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y, 			(WMValue)15},
    {WARG_X,			(WMValue)10},
    {WARG_WIDTH,		(WMValue)180},
    {WARG_TAG,			(WMValue)1}
};

static WMArgument wsRad2Args[] = {
    {WARG_CAPTION,		(WMValue)NULL},
    {WARG_Y, 			(WMValue)40},
    {WARG_X,			(WMValue)10},
    {WARG_WIDTH,		(WMValue)25},
    {WARG_TAG,			(WMValue)1}
};



static void
destroyInspector(WCoreWindow *foo, void *data, XEvent *event)
{
    InspectorPanel *panel;
    InspectorPanel *tmp;
    
    panel = panelList;
    while (panel->frame!=data)
	panel = panel->nextPtr;

    WMDestroyWidget(panel->win);
    wUnmanageWindow(panel->frame, False);

    panel->inspected->flags.inspector_open = 0;

    if (panelList == panel) 
	panelList = panel->nextPtr;
    else {
	tmp = panelList;
	while (tmp->nextPtr!=panel) {
	    tmp = tmp->nextPtr;
	}
	tmp->nextPtr = panel->nextPtr;
    }

    free(panel);
}



static void
changePage(WMButton *button, InspectorPanel *panel)
{
    if (button == panel->pageBtn1) {
	WMMapWidget(panel->specFrm);
	WMMapWidget(panel->specLbl);
    } else if (button == panel->pageBtn2) {
	WMMapWidget(panel->attrFrm);	
    } else if (button == panel->pageBtn3) {	
	WMMapWidget(panel->moreFrm);
    } else {
	WMMapWidget(panel->iconFrm);
	WMMapWidget(panel->wsFrm);
    }
    
    if (button!=panel->pageBtn1) {
	WMUnmapWidget(panel->specFrm);
	WMUnmapWidget(panel->specLbl);
    }
    if (button!=panel->pageBtn2)
	WMUnmapWidget(panel->attrFrm);
    if (button!=panel->pageBtn3)
	WMUnmapWidget(panel->moreFrm);
    if (button!=panel->pageBtn4) {
	WMUnmapWidget(panel->iconFrm);
	WMUnmapWidget(panel->wsFrm);
    }
}


static void
updateIcon(WMButton *button, InspectorPanel *panel)
{
    WMPixmap *pixmap;
    WMArgument arg[1];
    char *file;
    
    file = WMGetTextFromTextField(panel->fileText);
    if (!file)
	return;
    
    pixmap = WMCreatePixmapFromFile(W_SCREEN(button), file);
    free(file);
    
    if (!pixmap) {
	wMessageDialog(panel->frame->screen_ptr, _("Error"), 
		       _("Could not open specified icon file"), WD_ERROR);
	/*
	WMRunAlertPanel(W_SCREN(button), _("Error"),
			_("Could not open icon file"), _("OK"), NULL, NULL);
	 */
	return;
    }
    
    arg[0].argument = WARG_IMAGE;
    arg[0].value = (WMValue)pixmap;
    WMConfigureLabel(panel->iconLbl, arg, 1);
    WMReleasePixmap(pixmap);
}


static InspectorPanel*
createInspectorForWindow(WWindow *wwin)
{
    WScreen *scr = wwin->screen_ptr;

    InspectorPanel *panel;
    Window parent;
    char charbuf[128];
    int i, sel;

    panel = malloc(sizeof(InspectorPanel));
    if (!panel) {
	wWarning(_("not enough memory to open window inspector panel"));
	return NULL;
    }

    
    panel->inspected = wwin;

    panel->nextPtr = panelList;
    panelList = panel;
    

    sprintf(charbuf, "Inspecting  %s.%s", 
	    wwin->wm_instance ? wwin->wm_instance : "?",
	    wwin->wm_class ? wwin->wm_class : "?");

    parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, PWIDTH, PHEIGHT, 
				 0, 0, 0);


    XSetTransientForHint(dpy, parent, wwin->client_win);

    panel->win = WMCreateWindow(scr->wmscreen, parent, panelArgs,
				COUNTARG(panelArgs));

    /**** create common stuff ****/
    
    /* command buttons */
    buttonArgs[0].value = (WMValue)30;
    buttonArgs[1].value = (WMValue)_("Save");
    panel->saveBtn = WMCreateCommandButton(panel->win, buttonArgs, 
					    COUNTARG(buttonArgs));

    buttonArgs[0].value = (WMValue)100;
    buttonArgs[1].value = (WMValue)_("Apply");
    panel->applyBtn = WMCreateCommandButton(panel->win, buttonArgs, 
					    COUNTARG(buttonArgs));

    buttonArgs[0].value = (WMValue)170;
    buttonArgs[1].value = (WMValue)_("Revert");
    panel->revertBtn = WMCreateCommandButton(panel->win, buttonArgs,
					     COUNTARG(buttonArgs));
    
    /* page selection buttons */
    pageBtnArgs[0].value = (WMValue)70;
    pageBtnArgs[1].value = (WMValue)"1";
    panel->pageBtn1 = WMCreateButton(panel->win, WBTOnOff, pageBtnArgs,
					    COUNTARG(pageBtnArgs));
    WMBindEvent(panel->pageBtn1, WEV_CLICK, changePage, panel);
    
    pageBtnArgs[0].value = (WMValue)100;
    pageBtnArgs[1].value = (WMValue)"2";
    panel->pageBtn2 = WMCreateButton(panel->win, WBTOnOff, pageBtnArgs,
					    COUNTARG(pageBtnArgs));
    WMBindEvent(panel->pageBtn2, WEV_CLICK, changePage, panel);
    
    pageBtnArgs[0].value = (WMValue)130;
    pageBtnArgs[1].value = (WMValue)"3";
    panel->pageBtn3 = WMCreateButton(panel->win, WBTOnOff, pageBtnArgs,
					    COUNTARG(pageBtnArgs));
    WMBindEvent(panel->pageBtn3, WEV_CLICK, changePage, panel);
    
    pageBtnArgs[0].value = (WMValue)160;
    pageBtnArgs[1].value = (WMValue)"4";
    panel->pageBtn4 = WMCreateButton(panel->win, WBTOnOff, pageBtnArgs,
					    COUNTARG(pageBtnArgs));
    WMBindEvent(panel->pageBtn4, WEV_CLICK, changePage, panel);

    /**** window spec ****/
    specFrmArgs[0].value = (WMValue)_("Window Specification");
    panel->specFrm = WMCreateFrame(panel->win, specFrmArgs, 
				   COUNTARG(specFrmArgs));

    sel = 1;
    if (wwin->wm_class && wwin->wm_instance) {
	sprintf(charbuf, "%s.%s", wwin->wm_instance, wwin->wm_class);
	specRadArgs[0].value = (WMValue)18;
	specRadArgs[1].value = (WMValue)charbuf;
	specRadArgs[2].value = (WMValue)sel; sel=0;
	panel->bothRb = WMCreateRadioButton(panel->specFrm, specRadArgs, 
					    COUNTARG(specRadArgs));
    }

    if (wwin->wm_instance) {
	specRadArgs[0].value = (WMValue)38;
	specRadArgs[1].value = (WMValue)wwin->wm_instance;
	specRadArgs[2].value = (WMValue)sel; sel=0;
	panel->instRb = WMCreateRadioButton(panel->specFrm, specRadArgs, 
					    COUNTARG(specRadArgs));
    }

    if (wwin->wm_class) {
	specRadArgs[0].value = (WMValue)58;
	specRadArgs[1].value = (WMValue)wwin->wm_class;
	specRadArgs[2].value = (WMValue)sel; sel=0;
	panel->clsRb = WMCreateRadioButton(panel->specFrm, specRadArgs, 
					   COUNTARG(specRadArgs));
    }
    
    specLblArgs[0].value = (WMValue)_("The configuration will apply to all\nwindows that have their WM_CLASS property set to the above\nselected name.");

    specLblArgs[0].value = (WMValue)"THIS FUNCTIONALITY IS NOT YET IMPLEMENTED";
    panel->specLbl = WMCreateLabel(panel->win, specLblArgs, 
				   COUNTARG(specLblArgs));
    
    /**** attributes ****/
    attrFrmArgs[0].value = (WMValue)_("Attributes");
    panel->attrFrm = WMCreateFrame(panel->win, attrFrmArgs,
				   COUNTARG(attrFrmArgs));

    for (i=0; i < 8; i++) {
	switch (i) {
	 case 0:
	    attrChkArgs[0].value = (WMValue)_("Disable titlebar");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.titlebar;
	    break;
	 case 1:
	    attrChkArgs[0].value = (WMValue)_("Not miniaturizable");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.miniaturizable;
	    break;
	 case 2:
	    attrChkArgs[0].value = (WMValue)_("Not closable");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.closable;
	    break;
	 case 3:
	    attrChkArgs[0].value = (WMValue)_("Disable resizebar");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.resizable;
	    break;
	 case 4:
	    attrChkArgs[0].value = (WMValue)_("Keep on top");
	    attrChkArgs[2].value = (WMValue)wwin->window_flags.floating;
	    break;
	 case 5:
	    attrChkArgs[0].value = (WMValue)_("Omnipresent");
	    attrChkArgs[2].value = (WMValue)wwin->window_flags.omnipresent;
	    break;
	 case 6:
	    attrChkArgs[0].value = (WMValue)_("Don't let it take focus");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.focusable;
	    break;
	 case 7:
	    attrChkArgs[0].value = (WMValue)_("Skip window list");
	    attrChkArgs[2].value = (WMValue)wwin->window_flags.skip_window_list;
	    break;
	}
	attrChkArgs[1].value = (WMValue)(20*(i+1));
	panel->attrChk[i] = WMCreateSwitchButton(panel->attrFrm, attrChkArgs,
						 COUNTARG(attrChkArgs));
    }
    

    
    /**** more attributes ****/
    attrFrmArgs[0].value = (WMValue)_("Advanced");
    panel->moreFrm = WMCreateFrame(panel->win, attrFrmArgs,
				   COUNTARG(attrFrmArgs));

    for (i=0; i < 5; i++) {
	switch (i) {
	 case 0:
	    attrChkArgs[0].value = (WMValue)_("Ignore HideOthers");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.hide_others;
	    break;
	 case 1:
	    attrChkArgs[0].value = (WMValue)_("Don't bind keyboard shortcuts");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.bind_keys;
	    break;
	 case 2:
	    attrChkArgs[0].value = (WMValue)_("Don't bind mouse clicks");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.bind_mouse;
	    break;
	 case 3:
	    attrChkArgs[0].value = (WMValue)_("Keep inside screen");
	    attrChkArgs[2].value = (WMValue)wwin->window_flags.dont_move_off;
	    break;
	 case 4:
	    attrChkArgs[0].value = (WMValue)_("No application icon");
	    attrChkArgs[2].value = (WMValue)!wwin->window_flags.application;
	    break;
	}
	attrChkArgs[1].value = (WMValue)(20*(i+1));
	panel->moreChk[i] = WMCreateSwitchButton(panel->moreFrm, attrChkArgs,
						 COUNTARG(attrChkArgs));
    }

    
    /* miniwindow/workspace */
    
    iconFrmArgs[0].value = (WMValue)_("Miniwindow Image");
    panel->iconFrm = WMCreateFrame(panel->win, iconFrmArgs,
				   COUNTARG(iconFrmArgs));
    panel->iconLbl = WMCreateLabel(panel->iconFrm, iconLblArgs,
				   COUNTARG(iconLblArgs));

    updateIconBtnArgs[0].value = (WMValue)_("Default");
    panel->updateIconBtn = WMCreateCommandButton(panel->iconFrm, 
						 updateIconBtnArgs,
						 COUNTARG(updateIconBtnArgs));
/*    WMBindEvent(panel->updateIconBtn, WEV_CLICK, updateIcon, panel);
 */

    updateIconBtnArgs[0].value = (WMValue)_("Update");
    updateIconBtnArgs[1].value = (WMValue)65;
    panel->updateIconBtn = WMCreateCommandButton(panel->iconFrm, 
						 updateIconBtnArgs,
						 COUNTARG(updateIconBtnArgs));
    WMBindEvent(panel->updateIconBtn, WEV_CLICK, updateIcon, panel);    
    
    fileLblArgs[0].value = (WMValue)_("Icon file name:");
    panel->fileLbl = WMCreateLabel(panel->iconFrm, fileLblArgs,
				   COUNTARG(fileLblArgs));
    
    fileArgs[0].value = (WMValue)"test";
    panel->fileText = WMCreateTextField(panel->iconFrm, fileArgs,
					COUNTARG(fileArgs));
    
    alwChkArgs[0].value = (WMValue)_("Ignore client supplied icon");
    panel->alwChk = WMCreateSwitchButton(panel->iconFrm, alwChkArgs,
					 COUNTARG(alwChkArgs));
    
    
    wsFrmArgs[0].value = (WMValue)_("Initial Workspace");
    panel->wsFrm = WMCreateFrame(panel->win, wsFrmArgs, COUNTARG(wsFrmArgs));
    

    wsRad1Args[0].value = (WMValue)_("Current workspace");
    panel->curRb = WMCreateRadioButton(panel->wsFrm, wsRad1Args,
				       COUNTARG(wsRad1Args));
    
    panel->setRb = WMCreateRadioButton(panel->wsFrm, wsRad2Args,
				       COUNTARG(wsRad2Args));

/*    workspaceArgs[0].value = (WMValue)scr->workspaces[scr->current_workspace]->name;
 */
    panel->wsText = WMCreateTextField(panel->wsFrm, workspaceArgs,
				      COUNTARG(workspaceArgs));

    
    /*********/
    
    panel->frame = wManageInternalWindow(scr, parent, wwin->client_win, charbuf,
					 wwin->frame_x+wwin->frame->core->width/2,
					 wwin->frame_y+wwin->frame->top_width*2, 
					 PWIDTH, PHEIGHT);
    
    panel->frame->window_flags.closable = 1;
    wWindowUpdateButtonImages(panel->frame);
    wFrameWindowShowButton(panel->frame->frame, WFF_RIGHT_BUTTON);
    panel->frame->frame->on_click_right = destroyInspector;

    
    WMMapSubwidgets(panel->win);
    WMMapSubwidgets(panel->specFrm);
    WMMapSubwidgets(panel->attrFrm);
    WMMapSubwidgets(panel->moreFrm);
    WMMapSubwidgets(panel->iconFrm);
    WMMapSubwidgets(panel->wsFrm);

    WMPerformButtonClick(panel->pageBtn1);

    WMMapWidget(panel->win);
    
    return panel;
}


void
wShowInspectorForWindow(WWindow *wwin)
{
    InspectorPanel *panel;

    if (wwin->flags.inspector_open)
      return;

    wwin->flags.inspector_open = 1;
    panel = createInspectorForWindow(wwin);
}
