/*
* 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[] = "$XConsortium: TearOffB.c /main/12 1996/03/06 17:09:22 pascale $"
#endif
#endif
/* (c) Copyright 1989, 1990 DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
/* (c) Copyright 1988 MASSACHUSETTS INSTITUTE OF TECHNOLOGY */
/* (c) Copyright 1988 MICROSOFT CORPORATION */
/*
* Include files & Static Routine Definitions
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <Xm/DrawP.h>
#include <Xm/RowColumnP.h>
#include <Xm/TearOffBP.h>
#include <Xm/TraitP.h>
#include <Xm/MenuT.h>
#include <Xm/TransltnsP.h>
#include "MapEventsI.h"
#include "MessagesI.h"
#include "RCMenuI.h"
#include "RepTypeI.h"
#include "TearOffI.h"
#include "XmI.h"
/******** Static Function Declarations ********/
static void HeightDefault(
Widget widget,
int offset,
XrmValue *value) ;
static void GetSeparatorGC(
XmTearOffButtonWidget tob) ;
static void Initialize(
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static Boolean SetValues(
Widget cw,
Widget rw,
Widget nw,
ArgList args,
Cardinal *num_args) ;
static void Destroy(
Widget w) ;
static void Redisplay(
Widget wid,
XEvent *event,
Region region) ;
static void BDrag(
Widget wid,
XEvent *event,
String *param,
Cardinal *num_param) ;
static void BActivate(
Widget wid,
XEvent *event,
String *param,
Cardinal *num_param) ;
static void KActivate(
Widget wid,
XEvent *event,
String *param,
Cardinal *num_param) ;
static void ClassInitialize( void );
static void ClassPartInitialize(
WidgetClass wc) ;
/******** End Static Function Declarations ********/
#define DEFAULT_HEIGHT 10
/* Definition for resources that need special processing in get values */
static XmSyntheticResource syn_resources[] =
{
{
XmNmargin,
sizeof (Dimension),
XtOffsetOf( struct _XmTearOffButtonRec, tear_off_button.margin),
XmeFromHorizontalPixels,
XmeToHorizontalPixels
},
};
/* Resource list for Separator */
static XtResource resources[] =
{
{
XmNseparatorType, XmCSeparatorType, XmRSeparatorType, sizeof (unsigned char),
XtOffsetOf( struct _XmTearOffButtonRec, tear_off_button.separator_type),
XmRImmediate, (XtPointer) XmSHADOW_ETCHED_OUT_DASH
},
{
XmNmargin,
XmCMargin,
XmRHorizontalDimension,
sizeof (Dimension),
XtOffsetOf( struct _XmTearOffButtonRec, tear_off_button.margin),
XmRImmediate, (XtPointer) 0
},
/* The magic value will signal recomputeSize setting */
{
"pri.vate", "Pri.vate", XmRBoolean, sizeof(Boolean),
XtOffsetOf(XmTearOffButtonRec, tear_off_button.set_recompute_size),
XmRImmediate, (XtPointer) False
},
{
XmNheight, XmCDimension, XmRVerticalDimension, sizeof(Dimension),
XtOffsetOf( struct _WidgetRec, core.height), XmRCallProc,
(XtPointer) HeightDefault
},
};
/*************************************<->*************************************
*
*
* Description: translation tables for class: PushButton
* -----------
*
* Matches events with string descriptors for internal routines.
*
*************************************<->***********************************/
#define overrideTranslations _XmTearOffB_overrideTranslations
/*************************************<->*************************************
*
*
* Description: action list for class: TearOffButton
* -----------
*
* Matches string descriptors with internal routines.
* Note that Primitive will register additional event handlers
* for traversal.
*
*************************************<->***********************************/
static XtActionsRec actionsList[] =
{
{"BDrag", BDrag },
{"BActivate", BActivate },
{"KActivate", KActivate },
};
externaldef(xmtearoffbuttonclassrec)
XmTearOffButtonClassRec xmTearOffButtonClassRec = {
{
/* core_class record */
/* superclass */ (WidgetClass) &xmPushButtonClassRec,
/* class_name */ "XmTearOffButton",
/* widget_size */ sizeof(XmTearOffButtonRec),
/* class_initialize */ ClassInitialize,
/* class_part_init */ ClassPartInitialize,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ actionsList,
/* num_actions */ XtNumber(actionsList),
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ XtExposeCompressMaximal,
/* compress_enterlv */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
/* 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_private */ NULL,
/* tm_table */ NULL,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ NULL,
/* extension */ NULL,
},
{ /* primitive_class record */
/* Primitive border_highlight */ XmInheritBorderHighlight,
/* Primitive border_unhighlight */ XmInheritBorderUnhighlight,
/* translations */ XtInheritTranslations,
/* arm_and_activate */ XmInheritArmAndActivate,
/* get resources */ syn_resources,
/* num get_resources */ XtNumber(syn_resources),
/* extension */ NULL,
},
{ /* label_class record */
/* setOverrideCallback */ XmInheritWidgetProc,
/* menu procedures */ XmInheritMenuProc,
/* menu traversal xlation */ XtInheritTranslations,
/* extension */ (XtPointer) NULL,
},
{ /* pushbutton_class record */
/* extension */ (XtPointer) NULL,
},
{ /* tearoffbutton_class record */
/* Button override xlation */ XtInheritTranslations,
}
};
externaldef(xmtearoffbuttonwidgetclass)
WidgetClass xmTearOffButtonWidgetClass = (WidgetClass)&xmTearOffButtonClassRec;
/*********************************************************************
*
* HeightDefault
* This procedure provides the dynamic default behavior for
* the height. It the height is not explicitly set by the user
* then, a default is given and recomputeSize will be set True in
* Initialize, which will have RC probably change it to suit it needs.
* If this is not called, recomputeSize will be False
*
*********************************************************************/
/*ARGSUSED*/
static void
HeightDefault(
Widget widget,
int offset, /* unused */
XrmValue *value )
{
static Dimension default_height = DEFAULT_HEIGHT ;
XmTearOffButtonWidget tob = (XmTearOffButtonWidget)widget;
value->addr = (XPointer) &default_height;
tob->tear_off_button.set_recompute_size = True;
}
/************************************************************************
*
* GetSeparatorGC
* Get the graphics context used for drawing the separator.
*
************************************************************************/
static void
GetSeparatorGC(
XmTearOffButtonWidget tob )
{
XGCValues values;
XtGCMask valueMask;
valueMask = GCForeground | GCBackground;
values.foreground = tob->primitive.foreground;
values.background = tob->core.background_pixel;
if (tob -> tear_off_button.separator_type == XmSINGLE_DASHED_LINE ||
tob -> tear_off_button.separator_type == XmDOUBLE_DASHED_LINE)
{
valueMask = valueMask | GCLineStyle;
values.line_style = LineDoubleDash;
}
tob->tear_off_button.separator_GC =
XtGetGC ((Widget) tob, valueMask, &values);
}
/************************************************************************
*
* ClassInitialize
*
************************************************************************/
static void
ClassInitialize( void )
{
xmTearOffButtonClassRec.tearoffbutton_class.translations =
(String)XtParseTranslationTable(overrideTranslations);
}
/************************************************************************
*
* ClassPartInitialize
* Set up the fast subclassing for the widget
*
************************************************************************/
static void
ClassPartInitialize(
WidgetClass wc )
{
_XmFastSubclassInit (wc, XmTEAROFF_BUTTON_BIT);
}
/************************************************************************
*
* Initialize
* The main widget instance initialization routine.
*
************************************************************************/
/*ARGSUSED*/
static void
Initialize(
Widget rw, /* unused */
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmTearOffButtonWidget new_w = (XmTearOffButtonWidget) nw ;
XtTranslations trans;
GetSeparatorGC((XmTearOffButtonWidget)nw);
_XmProcessLock();
trans = (XtTranslations) ((XmTearOffButtonClassRec *)
XtClass(nw))->tearoffbutton_class.translations;
_XmProcessUnlock();
XtOverrideTranslations(nw, trans);
if(!XmRepTypeValidValue(XmRID_SEPARATOR_TYPE,
new_w->tear_off_button.separator_type,
(Widget) new_w)) {
new_w -> tear_off_button.separator_type = XmSHADOW_ETCHED_OUT_DASH;
}
/* force the orientation */
new_w->tear_off_button.orientation = XmHORIZONTAL ;
/* if set_recompute_size is True, this widget didn't have a
specific height, so set its recompute_size to True, so that
RCLayout can override it. if set_recompute_size is False, a
specific height was given, so force recompute_size to False */
if (new_w->tear_off_button.set_recompute_size) {
new_w->label.recompute_size = True;
new_w->tear_off_button.set_recompute_size = False ;
} else
new_w->label.recompute_size = False;
}
/************************************************************************
*
* Redisplay (tob, event, region)
* Description:
* -----------
* Cause the widget, identified by tob, to be redisplayed.
*
************************************************************************/
/*ARGSUSED*/
static void
Redisplay(
Widget wid,
XEvent *event,
Region region )
{
XmTearOffButtonWidget tob = (XmTearOffButtonWidget) wid ;
/*
* Where do we check for dependency on MenyType ??
*/
if (XtIsRealized((Widget)tob)) {
XtExposeProc expose;
XmeDrawSeparator(XtDisplay(tob), XtWindow(tob),
tob->primitive.top_shadow_GC,
tob->primitive.bottom_shadow_GC,
tob->tear_off_button.separator_GC,
tob->primitive.highlight_thickness,
tob->primitive.highlight_thickness,
tob->core.width -
2*tob->primitive.highlight_thickness,
tob->core.height -
2*tob->primitive.highlight_thickness,
tob->primitive.shadow_thickness,
tob->tear_off_button.margin,
tob->tear_off_button.orientation,
tob->tear_off_button.separator_type);
/* envelop primitive expose method for highlight */
_XmProcessLock();
expose = xmPrimitiveClassRec.core_class.expose;
_XmProcessUnlock();
(*expose)(wid,event, region) ;
}
}
/************************************************************************
*
* Destroy
* Remove the callback lists.
*
************************************************************************/
static void
Destroy(
Widget wid )
{
XtReleaseGC (wid,
((XmTearOffButtonWidget) wid)->tear_off_button.separator_GC);
}
/************************************************************************
*
* SetValues
*
************************************************************************/
/*ARGSUSED*/
static Boolean
SetValues(
Widget cw,
Widget rw, /* unused */
Widget nw,
ArgList args, /* unused */
Cardinal *num_args ) /* unused */
{
XmTearOffButtonWidget current = (XmTearOffButtonWidget) cw ;
XmTearOffButtonWidget new_w = (XmTearOffButtonWidget) nw ;
Boolean flag = FALSE;
if(!XmRepTypeValidValue(XmRID_SEPARATOR_TYPE,
new_w->tear_off_button.separator_type, (Widget) new_w))
{
new_w -> tear_off_button.separator_type = XmSHADOW_ETCHED_OUT_DASH;
}
/* force the orientation */
new_w -> tear_off_button.orientation = XmHORIZONTAL;
if ((new_w->core.background_pixel != current->core.background_pixel) ||
(new_w->tear_off_button.separator_type !=
current->tear_off_button.separator_type) ||
(new_w->primitive.foreground != current->primitive.foreground))
{
XtReleaseGC ((Widget) new_w, new_w->tear_off_button.separator_GC);
GetSeparatorGC (new_w);
flag = TRUE;
}
if ((new_w->tear_off_button.margin != current->tear_off_button.margin) ||
(new_w->primitive.shadow_thickness !=
current->primitive.shadow_thickness))
{
flag = TRUE;
}
return (flag);
}
/************************************************************************
*
* BDrag
* On button 2 down, tear off the menu
*
************************************************************************/
/*ARGSUSED*/
static void
BDrag( Widget wid,
XEvent *event,
String *param, /* unused */
Cardinal *num_param ) /* unused */
{
_XmTearOffInitiate(XtParent(wid), event);
}
/************************************************************************
*
* BActivate
* On either a button down or a button up, tear off the menu
*
************************************************************************/
/*ARGSUSED*/
static void
BActivate( Widget wid,
XEvent *event,
String *param, /* unused */
Cardinal *num_param ) /* unused */
{
Widget parent = XtParent(wid);
XmMenuSystemTrait menuSTrait;
menuSTrait = (XmMenuSystemTrait)
XmeTraitGet((XtPointer) XtClass(XtParent(wid)), XmQTmenuSystem);
if (menuSTrait -> verifyButton(XtParent(wid), event))
{
_XmTearOffInitiate(parent, event);
}
}
/************************************************************************
*
* KActivate
* Initiate Tear Off on a keypress
************************************************************************/
/*ARGSUSED*/
static void
KActivate( Widget wid,
XEvent *event,
String *param, /* unused */
Cardinal *num_param ) /* unused */
{
XButtonEvent xb_ev ;
Widget parent = XtParent(wid);
Position x, y;
/* stick the tear off at the same location as the submenu */
XtTranslateCoords(parent, XtX(parent), XtY(parent),
&x, &y);
xb_ev = event->xbutton;
xb_ev.x_root = x;
xb_ev.y_root = y;
_XmTearOffInitiate(parent, (XEvent *) &xb_ev);
}