home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
x
/
volume10
/
xt-examples
/
part05
/
Pushbutton.c
< prev
Wrap
C/C++ Source or Header
|
1990-11-04
|
13KB
|
445 lines
/***********************************************************
Copyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute these examples for any
purpose and without fee is hereby granted, provided that the above
copyright notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting documentation,
and that the name of Digital not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
DIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include <string.h> /* Needed for string manipulation */
#include <X11/IntrinsicP.h> /* Intrinsics header file */
#include <X11/StringDefs.h> /* Resource string definitions */
#include "PushbuttoP.h" /* Pushbutton private header file */
static void InsPixel(), InsPixmap();
#define Offset(field) XtOffsetOf(PushbuttonRec, pushbutton.field)
static XtResource resources[] = {
{XtNcallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
Offset(callback), XtRCallback, (XtPointer) NULL},
{"pri.vate", "Pri.vate", XtRBoolean, sizeof(Boolean),
Offset(use_insens_pixel), XtRImmediate, (XtPointer) TRUE},
{XtNinsensitiveForeground, XtCForeground, XtRPixel, sizeof(Pixel),
Offset(insensitive_foreground),
XtRCallProc, (XtPointer) InsPixel},
{XtNinsensitivePixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
Offset(insensitive_pixmap),
XtRCallProc, (XtPointer) InsPixmap},
{XtNhighlightBorder, XtCBorderWidth,
XtRDimension, sizeof(Dimension),
Offset(highlight_border), XtRImmediate, (XtPointer) 1},
{XtNaccelString, XtCAccelString, XtRString, sizeof(String),
XtOffsetOf(PushbuttonRec, label.accel_string),
XtRString, NULL},
{XtNacceleratorString, XtCAcceleratorString,
XtRString, sizeof(String),
Offset(accelerator_string), XtRString, NULL},
{XtNborderWidth, XtCBorderWidth,
XtRDimension, sizeof(Dimension),
XtOffsetOf(PushbuttonRec, core.border_width),
XtRImmediate, (XtPointer) 1},
};
#undef Offset
static void InsPixel(w, offset, value)
Widget w;
int offset; /* Not used */
XrmValue *value;
{
PushbuttonWidget p = (PushbuttonWidget) w;
/* Any value will work; it won't be used */
value->addr = (caddr_t) &p->label.foreground;
p->pushbutton.use_insens_pixel = FALSE;
}
/* Return a 2x2 pixmap with the foreground at 50% */
static Pixmap GetPixmap(pw)
PushbuttonWidget pw;
{
static char bits[] = {0x01, 0x02};
return XCreatePixmapFromBitmapData(XtDisplay(pw),
RootWindowOfScreen(XtScreen(pw)), bits, 2, 2,
pw->label.foreground, pw->core.background_pixel,
pw->core.depth);
}
static void InsPixmap(w, offset, value)
Widget w;
int offset; /* Not used */
XrmValue *value;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
static Pixmap pixmap;
if (pw->pushbutton.use_insens_pixel) pixmap = None;
else pixmap = GetPixmap(pw);
value->addr = (caddr_t) &pixmap;
}
static char defaultTranslations[] =
"<EnterWindow> : highlight() \n\
<LeaveWindow> : unhighlight() \n\
<Btn1Down> : invert() \n\
<Btn1Up> : notify() uninvert()";
static void Highlight(), Unhighlight(), Invert(), Uninvert(), Notify();
static XtActionsRec actions[] = {
{"highlight", Highlight},
{"unhighlight", Unhighlight},
{"invert", Invert},
{"uninvert", Uninvert},
{"notify", Notify},
};
/* Forward declarations */
static void Initialize(), DisplayAccelerator(), Destroy(), Redisplay();
static Boolean SetValues();
/* Class record declaration */
PushbuttonClassRec pushbuttonClassRec = {
/* Core class part */
{
/* superclass */ (WidgetClass) &labelClassRec,
/* class_name */ "Pushbutton",
/* widget_size */ sizeof(PushbuttonRec),
/* class_initialize */ NULL,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ actions,
/* num_actions */ XtNumber(actions),
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ XtExposeCompressMultiple,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ NULL,
/* resize */ XtInheritResize,
/* expose */ Redisplay,
/* set_values */ SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback offsets */ NULL,
/* tm_table */ defaultTranslations,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ DisplayAccelerator,
/* extension */ NULL
},
/* Label class part */
{
/* select_text */ InheritSelectText,
/* extension */ NULL
},
/* Pushbutton class part */
{
/* extension */ NULL
}
};
/* Class record pointer */
WidgetClass pushbuttonWidgetClass = (WidgetClass) &pushbuttonClassRec;
static void Highlight(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
if (!pw->pushbutton.highlighted) {
pw->pushbutton.highlighted = TRUE;
if (XtIsRealized(w)) {
XClearWindow(XtDisplay(w), XtWindow(w));
(*(XtClass(w)->core_class.expose))(w, event, NULL);
}
}
}
static void Unhighlight(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
if (pw->pushbutton.highlighted) {
pw->pushbutton.highlighted = FALSE;
if (XtIsRealized(w)) {
XClearWindow(XtDisplay(w), XtWindow(w));
(*(XtClass(w)->core_class.expose))(w, event, NULL);
}
}
}
static void Invert(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
if (!pw->pushbutton.inverted) {
pw->pushbutton.inverted = TRUE;
pw->label.current_gc = pw->pushbutton.inverted_gc;
if (XtIsRealized(w)) {
XClearWindow(XtDisplay(w), XtWindow(w));
(*(XtClass(w)->core_class.expose))(w, event, NULL);
}
}
}
static void Uninvert(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
if (pw->pushbutton.inverted) {
pw->pushbutton.inverted = FALSE;
if (XtIsSensitive(w)) {
pw->label.current_gc = pw->label.gc;
} else pw->label.current_gc = pw->pushbutton.insensitive_gc;
if (XtIsRealized(w)) {
XClearWindow(XtDisplay(w), XtWindow(w));
(*(XtClass(w)->core_class.expose))(w, event, NULL);
}
}
}
static void Notify(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
/* If event is a button event, and the event's window is the
widget's window, we were invoked normally. Make sure
the pointer is really in the window */
if (event != NULL && event->type == ButtonRelease &&
event->xany.window == XtWindow(w)) {
XButtonEvent *b = &event->xbutton;
if (b->x < 0 || b->y < 0 ||
b->x >= w->core.width || b->y >= w->core.height) return;
}
XtCallCallbackList(pw, pw->pushbutton.callback, NULL);
}
static GC GetInvertedGC(pw)
PushbuttonWidget pw;
{
XGCValues values;
values.foreground = pw->core.background_pixel;
values.font = pw->label.font->fid;
return XtGetGC((Widget) pw, GCForeground | GCFont, &values);
}
static GC GetInsensitiveGC(pw)
PushbuttonWidget pw;
{
XGCValues values;
values.font = pw->label.font->fid;
if (pw->pushbutton.use_insens_pixel) {
values.foreground = pw->pushbutton.insensitive_foreground;
return XtGetGC((Widget) pw, GCForeground | GCFont, &values);
} else {
values.tile = pw->pushbutton.insensitive_pixmap;
values.fill_style = FillTiled;
return XtGetGC((Widget) pw,
GCTile | GCFont | GCFillStyle, &values);
}
}
static void Initialize(req, new)
Widget req, new;
{
PushbuttonWidget pw = (PushbuttonWidget) new;
pw->pushbutton.insensitive_gc = GetInsensitiveGC(pw);
pw->pushbutton.inverted_gc = GetInvertedGC(pw);
pw->pushbutton.accelerator_string =
XtNewString(pw->pushbutton.accelerator_string);
pw->pushbutton.highlighted = pw->pushbutton.inverted = FALSE;
if (!XtIsSensitive(pw)) {
pw->label.current_gc = pw->pushbutton.insensitive_gc;
}
}
static Boolean SetValues(old, req, new, args, num_args)
Widget old, req, new;
ArgList args;
Cardinal *num_args;
{
PushbuttonWidget oldpw = (PushbuttonWidget) old;
PushbuttonWidget newpw = (PushbuttonWidget) new;
#define NE(field) (oldpw->field != newpw->field)
/* If insensitive fields or button's font has changed,
update insensitive GC */
if (NE(pushbutton.insensitive_foreground)) {
newpw->pushbutton.use_insens_pixel = TRUE;
}
if (NE(pushbutton.insensitive_pixmap)) {
if (newpw->pushbutton.insensitive_pixmap == None) {
newpw->pushbutton.insensitive_pixmap = GetPixmap(newpw);
}
newpw->pushbutton.use_insens_pixel = FALSE;
}
if (NE(pushbutton.insensitive_foreground) ||
NE(pushbutton.insensitive_pixmap) || NE(label.font->fid)) {
XtReleaseGC(newpw, oldpw->pushbutton.insensitive_gc);
newpw->pushbutton.insensitive_gc = GetInsensitiveGC(newpw);
if (newpw->label.current_gc ==
oldpw->pushbutton.insensitive_gc) {
newpw->label.current_gc = newpw->pushbutton.insensitive_gc;
}
}
/* If background or font has changed, update inverted GC */
if (NE(core.background_pixel) || NE(label.font->fid)) {
XtReleaseGC(newpw, oldpw->pushbutton.inverted_gc);
newpw->pushbutton.inverted_gc = GetInvertedGC(newpw);
if (newpw->pushbutton.inverted) {
newpw->label.current_gc = newpw->pushbutton.inverted_gc;
}
}
/* If sensitivity changing, adjust appearance */
if (NE(core.sensitive) || NE(core.ancestor_sensitive)) {
if (XtIsSensitive(newpw)) { /* Just made sensitive */
newpw->label.current_gc = newpw->label.gc;
} else { /* Just made insensitive */
newpw->label.current_gc =
newpw->pushbutton.insensitive_gc;
/* If currently highlighted, will never receive
leave event to unhighlight, so unhighlight */
newpw->pushbutton.highlighted = FALSE;
}
}
/* If current graphics context has changed, inverted
and foreground has changed, or highlighted and highlight
width has changed, redisplay */
return NE(label.current_gc) ||
(NE(label.foreground) && newpw->pushbutton.inverted) ||
(NE(pushbutton.highlight_border) &&
newpw->pushbutton.highlighted);
#undef NE
}
static void Destroy(w)
Widget w;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
/* Release the GCs */
XtReleaseGC(w, pw->pushbutton.insensitive_gc);
XtReleaseGC(w, pw->pushbutton.inverted_gc);
XtFree(pw->pushbutton.accelerator_string);
XtFree(pw->label.accel_string);
}
static void Redisplay(w, event, region)
Widget w;
XEvent *event;
Region region;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
int offset;
/* If inverted, fill background with the foreground color */
if (pw->pushbutton.inverted) {
XFillRectangle(XtDisplay(w), XtWindow(w), pw->label.gc,
0, 0, pw->core.width, pw->core.height);
}
/* If highlighted, draw highlighting border */
if (pw->pushbutton.highlighted) {
offset = pw->pushbutton.highlight_border / 2;
XDrawRectangle(XtDisplay(w), XtWindow(w), pw->label.current_gc,
offset, offset,
pw->core.width - pw->pushbutton.highlight_border,
pw->core.height - pw->pushbutton.highlight_border);
}
/* Make Label redisplay the string */
(*pushbuttonWidgetClass->core_class.superclass->core_class.expose)
(w, event, region);
}
static void DisplayAccelerator(w, string)
Widget w;
String string;
{
PushbuttonWidget pw = (PushbuttonWidget) w;
Arg args[1];
if (pw->pushbutton.accelerator_string != NULL) {
XtSetArg(args[0], XtNaccelString,
pw->pushbutton.accelerator_string);
XtSetValues(w, args, 1);
}
}