/*
* Motif
*
* Copyright (c) 1987-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* HISTORY
*/
#ifdef REV_INFO
#ifndef lint
static char rcsid[] = "$TOG: DrawingA.c /main/16 1999/10/13 16:16:41 mgreess $"
#endif
#endif
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Xm/TransltnsP.h>
#include <Xm/VaSimpleP.h>
#include "DrawingAI.h"
#include "GadgetUtiI.h"
#include "GMUtilsI.h"
#include "RepTypeI.h"
#include "TraversalI.h"
#include "XmI.h"
#define MARGIN_DEFAULT 10
#define defaultTranslations _XmDrawingA_defaultTranslations
#define traversalTranslations _XmDrawingA_traversalTranslations
/******** Static Function Declarations ********/
static void ClassInitialize( void ) ;
static void ClassPartInitialize(
WidgetClass w_class) ;
static void Initialize(
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static void Redisplay(
Widget wid,
XEvent *event,
Region region) ;
static void Resize(
Widget wid) ;
static XtGeometryResult GeometryManager(
Widget w,
XtWidgetGeometry *request,
XtWidgetGeometry *reply) ;
static void ChangeManaged(
Widget wid) ;
static Boolean SetValues(
Widget cw,
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static XtGeometryResult QueryGeometry(
Widget wid,
XtWidgetGeometry *intended,
XtWidgetGeometry *desired) ;
static XmNavigability WidgetNavigable(
Widget wid) ;
/******** End Static Function Declarations ********/
static XtActionsRec actionsList[] =
{
{ "DrawingAreaInput", _XmDrawingAreaInput },
};
/* Resource definitions for DrawingArea
*/
static XtResource resources[] =
{
{ XmNmarginWidth,
XmCMarginWidth, XmRHorizontalDimension, sizeof (Dimension),
XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_width),
XmRImmediate, (XtPointer) MARGIN_DEFAULT
},
{ XmNmarginHeight,
XmCMarginHeight, XmRVerticalDimension, sizeof (Dimension),
XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_height),
XmRImmediate, (XtPointer) MARGIN_DEFAULT
},
{ XmNresizeCallback,
XmCCallback, XmRCallback, sizeof (XtCallbackList),
XtOffsetOf(XmDrawingAreaRec, drawing_area.resize_callback),
XmRImmediate, (XtPointer) NULL
},
{ XmNexposeCallback,
XmCCallback, XmRCallback, sizeof (XtCallbackList),
XtOffsetOf(XmDrawingAreaRec, drawing_area.expose_callback),
XmRImmediate, (XtPointer) NULL
},
{ XmNinputCallback,
XmCCallback, XmRCallback, sizeof (XtCallbackList),
XtOffsetOf(XmDrawingAreaRec, drawing_area.input_callback),
XmRImmediate, (XtPointer) NULL
},
#ifndef XM_PART_BC
{ XmNconvertCallback,
XmCCallback, XmRCallback, sizeof (XtCallbackList),
XtOffsetOf(XmDrawingAreaRec, drawing_area.convert_callback),
XmRImmediate, (XtPointer) NULL
},
{ XmNdestinationCallback,
XmCCallback, XmRCallback, sizeof (XtCallbackList),
XtOffsetOf(XmDrawingAreaRec, drawing_area.destination_callback),
XmRImmediate, (XtPointer) NULL
},
#endif
{ XmNresizePolicy,
XmCResizePolicy, XmRResizePolicy, sizeof (unsigned char),
XtOffsetOf(XmDrawingAreaRec, drawing_area.resize_policy),
XmRImmediate, (XtPointer) XmRESIZE_ANY
},
};
static XmSyntheticResource syn_resources[] =
{
{ XmNmarginWidth,
sizeof (Dimension),
XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_width),
XmeFromHorizontalPixels, XmeToHorizontalPixels
},
{ XmNmarginHeight,
sizeof (Dimension),
XtOffsetOf(XmDrawingAreaRec, drawing_area.margin_height),
XmeFromVerticalPixels, XmeToVerticalPixels
},
};
/****************************************************************
*
* Full class record constant
*
****************************************************************/
static XmBaseClassExtRec baseClassExtRec = {
NULL,
NULLQUARK,
XmBaseClassExtVersion,
sizeof(XmBaseClassExtRec),
NULL, /* InitializePrehook */
NULL, /* SetValuesPrehook */
NULL, /* InitializePosthook */
NULL, /* SetValuesPosthook */
NULL, /* secondaryObjectClass */
NULL, /* secondaryCreate */
NULL, /* getSecRes data */
{ 0 }, /* fastSubclass flags */
NULL, /* getValuesPrehook */
NULL, /* getValuesPosthook */
NULL, /* classPartInitPrehook */
NULL, /* classPartInitPosthook*/
NULL, /* ext_resources */
NULL, /* compiled_ext_resources*/
0, /* num_ext_resources */
FALSE, /* use_sub_resources */
WidgetNavigable, /* widgetNavigable */
NULL /* focusChange */
};
externaldef( xmdrawingareaclassrec) XmDrawingAreaClassRec
xmDrawingAreaClassRec =
{
{ /* core_class fields */
(WidgetClass) &xmManagerClassRec, /* superclass */
"XmDrawingArea", /* class_name */
sizeof(XmDrawingAreaRec), /* widget_size */
ClassInitialize, /* class_initialize */
ClassPartInitialize, /* class_part_init */
FALSE, /* class_inited */
Initialize, /* initialize */
NULL, /* initialize_hook */
XtInheritRealize, /* realize */
actionsList, /* actions */
XtNumber(actionsList), /* num_actions */
resources, /* resources */
XtNumber(resources), /* num_resources */
NULLQUARK, /* xrm_class */
TRUE, /* compress_motion */
FALSE, /* compress_exposure */
TRUE, /* compress_enterlv */
FALSE, /* visible_interest */
NULL, /* destroy */
Resize, /* resize */
Redisplay, /* expose */
SetValues, /* set_values */
NULL, /* set_values_hook */
XtInheritSetValuesAlmost, /* set_values_almost */
NULL, /* get_values_hook */
NULL, /* accept_focus */
XtVersion, /* version */
NULL, /* callback_private */
defaultTranslations, /* tm_table */
QueryGeometry, /* query_geometry */
NULL, /* display_accelerator*/
(XtPointer)&baseClassExtRec, /* extension */
},
{ /* composite_class fields */
GeometryManager, /* geometry_manager */
ChangeManaged, /* change_managed */
XtInheritInsertChild, /* insert_child */
XtInheritDeleteChild, /* delete_child */
NULL, /* extension */
},
{ /* constraint_class fields */
NULL, /* resource list */
0, /* num resources */
sizeof(XmManagerConstraintRec), /* constraint size */
NULL, /* init proc */
NULL, /* destroy proc */
NULL, /* set values proc */
NULL, /* extension */
},
{ /* manager_class fields */
traversalTranslations, /* translations */
syn_resources, /* syn_resources */
XtNumber (syn_resources), /* num_get_resources */
NULL, /* syn_cont_resources */
0, /* num_get_cont_resources */
XmInheritParentProcess, /* parent_process */
NULL, /* extension */
},
{ /* drawingArea class */
(XtPointer) NULL, /* extension pointer */
}
};
externaldef( xmdrawingareawidgetclass) WidgetClass xmDrawingAreaWidgetClass
= (WidgetClass) &xmDrawingAreaClassRec ;
/****************************************************************/
static void
ClassInitialize( void )
{
baseClassExtRec.record_type = XmQmotif ;
}
/****************************************************************/
static void
ClassPartInitialize(
WidgetClass w_class )
{
_XmFastSubclassInit( w_class, XmDRAWING_AREA_BIT) ;
}
/****************************************************************
* Initialize. Check resizePolicy resource value
****************/
/*ARGSUSED*/
static void
Initialize(
Widget rw, /* unused */
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmDrawingAreaWidget new_w = (XmDrawingAreaWidget) nw ;
if(new_w->drawing_area.resize_policy != XmRESIZE_SWINDOW
&& !XmRepTypeValidValue(XmRID_RESIZE_POLICY,
new_w->drawing_area.resize_policy,
(Widget) new_w) ) {
new_w->drawing_area.resize_policy = XmRESIZE_ANY ;
}
}
/****************************************************************
* General redisplay function called on exposure events.
****************/
static void
Redisplay(
Widget wid,
XEvent *event,
Region region )
{
XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
XmDrawingAreaCallbackStruct cb;
/****************/
cb.reason = XmCR_EXPOSE;
cb.event = event;
cb.window = XtWindow (da);
XtCallCallbackList ((Widget) da, da->drawing_area.expose_callback, &cb);
XmeRedisplayGadgets( (Widget) da, event, region);
}
/****************************************************************
* Invoke the application resize callbacks.
****************/
static void
Resize(
Widget wid )
{
XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
XmDrawingAreaCallbackStruct cb;
cb.reason = XmCR_RESIZE;
cb.event = NULL;
cb.window = XtWindow (da);
XtCallCallbackList ((Widget) da, da->drawing_area.resize_callback, &cb);
}
static Widget
ObjectAtPoint(
Widget wid,
Position x,
Position y )
{
CompositeWidget cw = (CompositeWidget) wid ;
register int i;
register Widget widget;
i = cw->composite.num_children ;
while( i-- ) {
widget = cw->composite.children[i];
/* do not care for gadget only for the DA input */
if (XmIsGadget(widget) && XtIsManaged (widget)) {
if (x >= widget->core.x && y >= widget->core.y &&
x < widget->core.x + widget->core.width &&
y < widget->core.y + widget->core.height)
return (widget);
}
}
return (NULL);
}
/****************************************************************
* This function processes key and button presses and releases
* belonging to the DrawingArea.
****************/
/*ARGSUSED*/
void
_XmDrawingAreaInput(
Widget wid,
XEvent *event,
String *params, /* unused */
Cardinal *num_params ) /* unused */
{
XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
XmDrawingAreaCallbackStruct cb ;
int x, y ;
Boolean button_event = True, input_on_gadget ;
if ((event->type == ButtonPress) ||
(event->type == ButtonRelease)) {
x = event->xbutton.x ;
y = event->xbutton.y ;
} else
if (event->type == MotionNotify) {
x = event->xmotion.x ;
y = event->xmotion.y ;
} else
if ((event->type == KeyPress) ||
(event->type == KeyRelease)) {
x = event->xkey.x ;
y = event->xkey.y ;
button_event = False ;
} else return ;
/* Unrecognized event (cannot determine x, y of pointer).*/
input_on_gadget = (ObjectAtPoint((Widget)da, x, y) != NULL);
if (!input_on_gadget && (!da->manager.active_child || button_event)) {
cb.reason = XmCR_INPUT ;
cb.event = event ;
cb.window = XtWindow( da) ;
XtCallCallbackList ((Widget) da,
da->drawing_area.input_callback, &cb) ;
}
}
/****************************************************************/
static XtGeometryResult
GeometryManager(
Widget w,
XtWidgetGeometry *request,
XtWidgetGeometry *reply )
{
XmDrawingAreaWidget da;
/* XtGeometryHandler manager ; */
/****************/
da = (XmDrawingAreaWidget) w->core.parent;
/* function shared with Bulletin Board */
return(_XmGMHandleGeometryManager((Widget)da, w, request, reply,
da->drawing_area.margin_width,
da->drawing_area.margin_height,
da->drawing_area.resize_policy,
True)); /* no overlap checking */
}
/****************************************************************
* Re-layout children.
****************/
static void
ChangeManaged(
Widget wid )
{
XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
/* function shared with Bulletin Board */
_XmGMEnforceMargin((XmManagerWidget)da,
da->drawing_area.margin_width,
da->drawing_area.margin_height,
False); /* use movewidget, not setvalue */
/* The first time, reconfigure only if explicit size were not given */
if (XtIsRealized((Widget)da) || (!XtWidth(da)) || (!XtHeight(da))) {
/* function shared with Bulletin Board */
(void)_XmGMDoLayout((XmManagerWidget)da,
da->drawing_area.margin_width,
da->drawing_area.margin_height,
da->drawing_area.resize_policy,
False); /* queryonly not specified */
}
XmeNavigChangeManaged((Widget) da) ;
}
/****************************************************************/
/*ARGSUSED*/
static Boolean
SetValues(
Widget cw,
Widget rw, /* unused */
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmDrawingAreaWidget current = (XmDrawingAreaWidget) cw ;
XmDrawingAreaWidget new_w = (XmDrawingAreaWidget) nw ;
if(new_w->drawing_area.resize_policy != XmRESIZE_SWINDOW
&& !XmRepTypeValidValue(XmRID_RESIZE_POLICY,
new_w->drawing_area.resize_policy,
(Widget) new_w) ) {
new_w->drawing_area.resize_policy =
current->drawing_area.resize_policy ;
}
/* If new margins, re-enforce them using movewidget,
then update the width and height so that XtSetValues does
the geometry request */
if (XtIsRealized((Widget) new_w) &&
(((new_w->drawing_area.margin_width !=
current->drawing_area.margin_width) ||
(new_w->drawing_area.margin_height !=
current->drawing_area.margin_height)))) {
/* move the child around if necessary */
_XmGMEnforceMargin((XmManagerWidget)new_w,
new_w->drawing_area.margin_width,
new_w->drawing_area.margin_height,
False); /* use movewidget, no request */
_XmGMCalcSize ((XmManagerWidget)new_w,
new_w->drawing_area.margin_width,
new_w->drawing_area.margin_height,
&new_w->core.width, &new_w->core.height);
}
return( False) ;
}
/****************************************************************
* Handle query geometry requests
****************/
static XtGeometryResult
QueryGeometry(
Widget wid,
XtWidgetGeometry *intended,
XtWidgetGeometry *desired )
{
XmDrawingAreaWidget da = (XmDrawingAreaWidget) wid ;
/* function shared with Bulletin Board */
return(_XmGMHandleQueryGeometry(wid, intended, desired,
da->drawing_area.margin_width,
da->drawing_area.margin_height,
da->drawing_area.resize_policy));
}
/****************************************************************
* Xm private class method
****************/
static XmNavigability
WidgetNavigable(
Widget wid)
{
if( XtIsSensitive(wid)
&& ((XmManagerWidget) wid)->manager.traversal_on )
{
XmNavigationType nav_type = ((XmManagerWidget) wid)
->manager.navigation_type ;
Widget *children = ((XmManagerWidget) wid)->composite.children ;
unsigned idx = 0 ;
/* If a Drawing Area has a navigable child, and initial focus
is either NULL or point to this child, allow navigation to it.
*/
while(idx < ((XmManagerWidget) wid)->composite.num_children) {
if (_XmGetNavigability(children[idx]) &&
((((XmManagerWidget) wid)->manager.initial_focus == NULL) ||
(((XmManagerWidget) wid)->manager.initial_focus ==
children[idx]))){
if( (nav_type == XmSTICKY_TAB_GROUP)
|| (nav_type == XmEXCLUSIVE_TAB_GROUP)
|| ( (nav_type == XmTAB_GROUP)
&& !_XmShellIsExclusive( wid))) {
return XmDESCENDANTS_TAB_NAVIGABLE ;
}
return XmDESCENDANTS_NAVIGABLE ;
}
++idx ;
}
/* else just return the DA itself */
if( (nav_type == XmSTICKY_TAB_GROUP)
|| (nav_type == XmEXCLUSIVE_TAB_GROUP)
|| ( (nav_type == XmTAB_GROUP)
&& !_XmShellIsExclusive( wid)) )
{
return XmTAB_NAVIGABLE ;
}
return XmCONTROL_NAVIGABLE ;
}
return XmNOT_NAVIGABLE ;
}
/****************************************************************
* This function creates and returns a DrawingArea widget.
****************/
Widget
XmCreateDrawingArea(
Widget p,
String name,
ArgList args,
Cardinal n )
{
/****************/
return( XtCreateWidget( name, xmDrawingAreaWidgetClass, p, args, n)) ;
}
Widget
XmVaCreateDrawingArea(
Widget parent,
char *name,
...)
{
register Widget w;
va_list var;
int count;
Va_start(var,name);
count = XmeCountVaListSimple(var);
va_end(var);
Va_start(var, name);
w = XmeVLCreateWidget(name,
xmDrawingAreaWidgetClass,
parent, False,
var, count);
va_end(var);
return w;
}
Widget
XmVaCreateManagedDrawingArea(
Widget parent,
char *name,
...)
{
Widget w = NULL;
va_list var;
int count;
Va_start(var, name);
count = XmeCountVaListSimple(var);
va_end(var);
Va_start(var, name);
w = XmeVLCreateWidget(name,
xmDrawingAreaWidgetClass,
parent, True,
var, count);
va_end(var);
return w;
}