#include "alive.h"
#include "xvars.h"
#ifdef X11R5
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Box.h>
#include <X11/Xaw/Paned.h>
#else
#include <X11/Label.h>
#include <X11/Command.h>
#include <X11/Box.h>
#include <X11/VPaned.h>
#endif
#include <X11/Shell.h>
#include "LabeledPicture.h"
#include "LoadFace.h"
#include "ArrangeBox.h"
#include "MachineInfo.h"
#include <varargs.h>
#include "version.h"
#include <math.h>
#include <X11/Xresource.h>
#include <X11/StringDefs.h>
#define DEFAULT_RATIO 3.0
#ifdef BITMAP_ICON
#include "bitmap/icon.icon"
#endif
#ifndef XtRDouble
#define XtRDouble "Double"
#endif
static Widget title,vpane,exitButton,topbar;
static Widget popdownButton;
static Widget helpButton,helpScreen;
static Widget helpPane,loadBox[AiFaceNum];
static Widget helpTitle;
static double windowRatio = DEFAULT_RATIO;
extern char *OrgFile;
static AiFaceData *HelpFaces;
static AiLoadBound *HelpBound;
static AiLoadBound defaultLoadBound = {10,90,180,450,900};
static void exitDisplay(),popdown(),showHelp(),popdownHelp();
Widget mkWidget();
static XrmOptionDescRec optionTable[] = {
{"-interval", "*interval", XrmoptionSepArg,(caddr_t)NULL},
{"-bitmapdir", "*bitmapFileDirectory", XrmoptionSepArg,(caddr_t)NULL},
{"-titlefont", "*title.font", XrmoptionSepArg,(caddr_t)NULL},
{"-windowratio","*windowRatio", XrmoptionSepArg,(caddr_t)NULL},
{"-nosort", "*sortHosts", XrmoptionNoArg, (caddr_t)"False"},
{"-loadbound", "*loadBound", XrmoptionSepArg,(caddr_t)NULL},
{"-org", "*orgFile", XrmoptionSepArg,(caddr_t)NULL},
};
static char *loadHelpText[] = {
"Idle ( - %4.2f)",
"Run ( - %4.2f)",
"Busy ( - %4.2f)",
"Heavy ( - %4.2f)",
"Fever ( - %4.2f)",
"Crazy (%4.2f - )",
"Down",
};
/*
* converter from String to Double
*/
static void
convertStr2Dbl(args,numargs,from,to)
XrmValue *args;
Cardinal *numargs;
XrmValue *from;
XrmValue *to;
{
double r;
to->size = sizeof(double);
r = atof(from->addr);
to->addr = XtMalloc(sizeof(double));
*(double*)to->addr = r;
}
/*
* makeToplevel(): creare toplevel widget
*/
makeToplevel(argc,argv)
int *argc;
char *argv[];
{
XtAppContext app;
XrmDatabase db;
XrmValue val,realVal;
char rname[64],cname[64];
char *type;
char *argv0;
/***** Top level *****/
Toplevel = XtInitialize("main",
"xloadface",
optionTable,
XtNumber(optionTable),
argc,argv);
app = XtWidgetToApplicationContext(Toplevel);
XtAppAddConverter(app,XtRString,XtRDouble,
convertStr2Dbl,NULL,0);
db = XtDatabase(XtDisplay(Toplevel));
for (argv0 = argv[0]+strlen(argv[0])-1;
argv0 >= argv[0] && *argv0 != '/';
argv0--);
argv0++;
sprintf(rname,"%s.windowRatio",argv0);
sprintf(cname,"%s.Ratio",argv0);
if (XrmGetResource(db,rname,cname,&type,&val)) {
XtConvert(Toplevel,type,&val,XtRDouble,&realVal);
windowRatio = *(double*)realVal.addr;
if (windowRatio <= 0) {
XtAppWarning(app,"Invalid window ratio; using default value.");
windowRatio = DEFAULT_RATIO;
}
}
sprintf(rname,"%s.sortHosts",argv0);
sprintf(cname,"%s.Sort",argv0);
if (XrmGetResource(db,rname,cname,&type,&val)) {
XtConvert(Toplevel,type,&val,XtRBoolean,&realVal);
SortHosts = *(Boolean*)realVal.addr;
}
sprintf(rname,"%s.orgFile",argv0);
sprintf(cname,"%s.OrgFile",argv0);
if (XrmGetResource(db,rname,cname,&type,&val)) {
#if 0
if (type != XtRString) {
XtAppWarning(app,"OrgFile type is not XtRString");
}
else {
OrgFile = (String)val.addr;
}
#endif
XtConvert(Toplevel, type, &val, XtRString, &realVal);
OrgFile = (String)realVal.addr;
}
}
/*
* initializeWidgets(): Initialize almost all widgets and pixmaps
*/
initializeWidgets()
{
int i;
static char titleString[60];
static XtCallbackRec exitCallback[] = {
exitDisplay, NULL,
NULL, NULL,
};
static XtCallbackRec popdownCallback[] = {
popdown, NULL,
NULL, NULL,
};
static XtCallbackRec helpCallback[] = {
showHelp, (caddr_t)&helpButton,
NULL, NULL,
};
static XtCallbackRec helpPopdownCallback[] = {
popdownHelp, NULL,
NULL, NULL,
};
char widgetname[64];
char loadtext[32];
/***** Pane *****/
#ifdef X11R5
vpane = mkWidget("pane",panedWidgetClass,Toplevel,
XtNallowResize, (XtArgVal)True,
NULL);
#else
vpane = mkWidget("pane",vPanedWidgetClass,Toplevel,
XtNallowResize, (XtArgVal)True,
NULL);
#endif
topbar = mkWidget("topbar",boxWidgetClass,vpane,
NULL);
/***** Title *****/
strcpy(titleString,"Hosts in ");
for (i = 0; i < DisplayOrganNum; i++) {
strcat(titleString,DisplayOrgans[i]);
if (i != DisplayOrganNum-1) {
strcat(titleString,",");
}
}
title = mkWidget("title",labelWidgetClass,topbar,
XtNlabel,titleString,
XtNborderWidth, 0,
NULL);
/***** Buttons *****/
exitButton = mkWidget("exitButton",commandWidgetClass,topbar,
XtNlabel,"Exit",
XtNcallback,exitCallback,
NULL);
helpButton = mkWidget("helpButton",commandWidgetClass,topbar,
XtNlabel,"Help",
XtNcallback,helpCallback,
NULL);
/***** Face Field *****/
FaceField = mkWidget("Faces",boxWidgetClass,vpane,
NULL);
/***** Popup Info *****/
PopupInfo = XtCreatePopupShell("PopupInfo",transientShellWidgetClass,
Toplevel,NULL,NULL);
PopupPane = mkWidget("InfoPane",arrangeBoxWidgetClass,PopupInfo,
AiNvertNum, 1,
AiNresizeParent, True,
NULL);
popdownButton = mkWidget("PopdownButton",commandWidgetClass,PopupPane,
XtNlabel,"Push here to popdown",
XtNcallback,popdownCallback,
NULL);
/***** Popup Help *****/
helpScreen = XtCreatePopupShell("Help",transientShellWidgetClass,
Toplevel,NULL,NULL);
addFaces();
adjustWindowSize();
XtRealizeWidget(Toplevel);
/***** Set Help Screen *****/
#define HELPWIDTH 200
helpPane = mkWidget("HelpPane",boxWidgetClass, helpScreen,
NULL);
sprintf(widgetname,"xloadface version %s",XLOADFACE_VERSION);
helpTitle = mkWidget("HelpTitle",commandWidgetClass, helpPane,
XtNlabel, widgetname,
XtNwidth, HELPWIDTH,
XtNreverseVideo, True,
XtNcallback, helpPopdownCallback,
NULL);
HelpFaces = AiGetDefaultFaceData(loadFaceWidgetClass);
HelpBound = &defaultLoadBound;
for (i = 0; i < AiFaceNum; i++) {
char *label;
sprintf(widgetname,"LoadBox%d",i);
if (i < AiLoadBoundNum)
sprintf(loadtext,
loadHelpText[i],
(double)HelpBound->value[i]/100);
else
sprintf(loadtext,
loadHelpText[i],
(double)HelpBound->value[AiLoadBoundNum-1]/100);
label = XtMalloc(strlen(loadtext)+10);
strcpy(label,loadtext);
loadBox[i] = mkWidget(widgetname,labeledPictureWidgetClass,helpPane,
XtNborderWidth, 0,
XtNwidth, HELPWIDTH,
AiNtextPosition, right,
AiNpixmap, HelpFaces[i].pixmap,
AiNlabel, label,
AiNsensitive, False,
NULL);
}
}
#ifdef BITMAP_ICON
static Pixmap iconBitmap;
#endif
initializeBitmaps(w)
Widget w;
{
int i;
XWMHints hint;
#ifdef BITMAP_ICON
iconBitmap = XCreateBitmapFromData(XtDisplay(w),XtWindow(w),
icon_bits,icon_width,icon_height);
hint.flags = IconPixmapHint;
hint.icon_pixmap = iconBitmap;
XSetWMHints(XtDisplay(w),XtWindow(w),&hint);
#endif
}
freeBitmaps(w)
Widget w;
{
#ifdef BITMAP_ICON
XFreePixmap(XtDisplay(w),iconBitmap);
#endif
}
static void popupInformation();
/*
* Create new host widget
*/
Widget
makeHostWidget(sitedata,parent)
struct whod *sitedata;
Widget parent;
{
static XtCallbackRec popupit[] = {
popupInformation, NULL,
NULL, NULL,
};
Widget newone;
newone = mkWidget(sitedata->wd_hostname,
loadFaceWidgetClass,parent,
XtNcallback,popupit,
XtNborderWidth,0,
NULL);
AiChangeLoad(newone,sitedata);
return newone;
}
/*
* Add face widgets
*/
addFaces()
{
int i;
Widget w;
for (i = 0; i < WhNum; i++) {
if ((w = AiFindWidgetByName(FaceField,Whodata[i].wd_hostname)) == NULL) {
makeHostWidget(&Whodata[i],FaceField);
}
else
AiChangeLoad(w,&Whodata[i]);
}
}
/*
* Resize window.
*/
adjustWindowSize()
{
int width,height,xheight;
int awidth,aheight;
int w,h,vnum,hnum;
int hsp,vsp,thsp,tvsp;
int wd;
int num = queryNumberOfChild(FaceField);
int maxwidth = DisplayWidth(XtDisplay(Toplevel),DefaultScreen(XtDisplay(Toplevel)));
int minwidth;
WidgetList queryChild(), children;
int i;
if (num == 0)
return;
hnum = ceil(sqrt((double)num*windowRatio));
vnum = ceil((double)num/hnum);
queryBoxSpace(FaceField,&hsp,&vsp);
queryBoxSpace(topbar,&thsp,&tvsp);
children = queryChild(FaceField);
width = height = 0;
for (i = 0; i < num; i++) {
queryFigure(children[i], NULL, NULL, &awidth, &aheight);
width += awidth;
height += aheight;
}
width /= num;
height /= num;
w = (width+hsp)*hnum+hsp;
if (w > maxwidth) {
hnum = (maxwidth-hsp)/(width+hsp);
w = (width+hsp)*hnum+hsp;
}
queryFigure(title,NULL,NULL,&minwidth,NULL);
queryFigure(exitButton,NULL,NULL,&awidth,NULL);
minwidth += awidth+thsp*2;
queryFigure(helpButton,NULL,NULL,&awidth,NULL);
minwidth += awidth+thsp;
if (w < minwidth) {
hnum = ceil((double)(minwidth-hsp)/(width+hsp));
w = (width+hsp)*hnum+hsp;
}
vnum = 1;
wd = hsp;
for (i = 0; i < num; i++) {
queryFigure(children[i], NULL, NULL, &awidth, &aheight);
if (wd+awidth > w) {
wd = hsp;
vnum++;
}
wd += awidth + hsp;
}
h = (height+tvsp)*vnum+tvsp;
queryFigure(Toplevel, NULL, NULL, &width, &height);
if (w < width)
return;
queryFigure(title,NULL,NULL,NULL,&height);
queryFigure(exitButton, NULL,NULL,NULL,&xheight);
if (height < xheight) height = xheight;
queryFigure(helpButton, NULL,NULL,NULL,&xheight);
if (height < xheight) height = xheight;
XtResizeWidget(Toplevel, w, h+height+1+tvsp*2,
queryBorderWidth(Toplevel));
}
/*
* Main Loop
*/
stay()
{
XtMainLoop();
}
/*
* Destroy all.
*/
static void
exitDisplay(w)
Widget w;
{
AiCleanupLoadFace(XtDisplay(Toplevel));
freeBitmaps(Toplevel);
XtDestroyWidget(Toplevel);
exit(0);
}
static Widget popupInfo;
/*
* Popup Info Window.
*/
static void
popupInformation(w,client_data,event)
Widget w;
caddr_t client_data;
XEvent *event;
{
XButtonEvent *bev = (XButtonEvent*)event;
int dw = DisplayWidth(XtDisplay(w),DefaultScreen(XtDisplay(w)));
int dh = DisplayHeight(XtDisplay(w),DefaultScreen(XtDisplay(w)));
int x,y,i;
static Arg popupInfoArg[2];
XtWidgetGeometry geo;
AiFaceData *facedata;
AiLoadBound *loadbound;
char *label;
XtSetArg(popupInfoArg[0],XtNborderWidth,0);
XtSetArg(popupInfoArg[1],AiNsiteInfo, AiLookupLoad(w));
popupInfo = XtCreateManagedWidget("ZHOSTNAME",
machineInfoWidgetClass,
PopupPane,
popupInfoArg,
XtNumber(popupInfoArg));
XtQueryGeometry(PopupInfo,NULL,&geo);
if (bev->x_root+geo.width < dw)
x = bev->x_root;
else
x = dw-geo.width;
if (bev->y_root+geo.height < dh)
y = bev->y_root;
else
y = dh-geo.height;
XtMoveWidget(PopupInfo, x, y);
XtPopup(PopupInfo, XtGrabExclusive);
facedata = AiGetFaceData(w);
loadbound = AiGetLoadBound(w);
if (facedata != HelpFaces) {
for (i = 0; i < AiFaceNum; i++)
AiChangePixmap(loadBox[i],facedata[i].pixmap);
HelpFaces = facedata;
}
for (i = 0; i < AiFaceNum; i++) {
label = AiGetLabel(loadBox[i]);
if (i < AiLoadBoundNum)
sprintf(label,
loadHelpText[i],
(double)loadbound->value[i]/100);
else
sprintf(label,
loadHelpText[i],
(double)loadbound->value[AiLoadBoundNum-1]/100);
AiChangeLabel(loadBox[i],label);
}
HelpBound = loadbound;
}
/*
* Popdown Info Window.
*/
static void
popdown(w)
Widget w;
{
XtDestroyWidget(popupInfo);
XtPopdown(PopupInfo);
}
/*
* Popup Help Window.
*/
static void
showHelp(w,client_data,event)
Widget w;
caddr_t client_data;
XEvent *event;
{
Widget parent = *(Widget*)client_data;
int dw = DisplayWidth(XtDisplay(w),DefaultScreen(XtDisplay(w)));
int dh = DisplayHeight(XtDisplay(w),DefaultScreen(XtDisplay(w)));
int x,y;
int px,py,cw,ch;
queryFigure(parent,&px,&py,NULL,NULL);
while (parent = XtParent(parent)) {
queryFigure(parent,&x,&y,NULL,NULL);
px += x;
py += y;
}
queryFigure(helpScreen,NULL,NULL,&cw,&ch);
if (px+cw < dw)
x = px;
else
x = dw-cw;
if (py+ch < dh)
y = py;
else
y = dh-ch;
XtMoveWidget(helpScreen, x, y);
XtPopup(helpScreen, XtGrabExclusive);
}
/*
* Popdown Info Window.
*/
static void
popdownHelp(w)
Widget w;
{
XtPopdown(helpScreen);
}
/*
* Create Managed Widget
*
* usage: mkWidget(name, class, parent,
* resource-name, resource, ... , NULL);
*/
Widget
mkWidget(va_alist)
va_dcl
{
va_list arg;
char *name;
WidgetClass class;
Widget parent;
String argname;
XtArgVal argval;
int n = 0;
Arg args[20];
va_start(arg);
name = va_arg(arg,char*);
class = va_arg(arg,WidgetClass);
parent = va_arg(arg,Widget);
while (argname = va_arg(arg,String)) {
argval = va_arg(arg,XtArgVal);
XtSetArg(args[n],argname,argval);
n++;
}
va_end(arg);
if (n)
return XtCreateManagedWidget(name,class,parent,args,n);
else
return XtCreateManagedWidget(name,class,parent,NULL,0);
}
syntax highlighted by Code2HTML, v. 0.9.1