mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 20:47:44 +00:00
1178 lines
32 KiB
C
1178 lines
32 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
/*-----------------------------------------*/
|
|
/* */
|
|
/* Name: <Xfe/Label.c> */
|
|
/* Description: XfeLabel widget source. */
|
|
/* Author: Ramiro Estrugo <ramiro@netscape.com> */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
#include <Xfe/LabelP.h>
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Warnings and messages */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
#define MESSAGE1 "Widget is not a XfeLabel."
|
|
#define MESSAGE2 "If XmNtruncateLabel is true, XmNtruncateProc cannot be NULL."
|
|
|
|
|
|
#define INSENSITIVE_OFFSET 1
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Core class methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void ClassPartInit (WidgetClass);
|
|
static void Initialize (Widget,Widget,ArgList,Cardinal *);
|
|
static void Destroy (Widget);
|
|
static Boolean SetValues (Widget,Widget,Widget,ArgList,Cardinal *);
|
|
static void GetValuesHook (Widget,ArgList,Cardinal *);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfePrimitive class methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void PreferredGeometry (Widget,Dimension *,Dimension *);
|
|
static void PrepareComponents (Widget,int);
|
|
static void LayoutComponents (Widget);
|
|
static void DrawComponents (Widget,XEvent *,Region,XRectangle *);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel class methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void LayoutString (Widget);
|
|
static void DrawString (Widget,XEvent *,Region,XRectangle *);
|
|
static void DrawSelection (Widget,XEvent *,Region,XRectangle *);
|
|
static GC GetLabelGC (Widget);
|
|
static GC GetSelectionGC (Widget);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Misc XfeLabel functions */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static XmString CreateTruncatedString (Widget);
|
|
static void InvokeSelectionChangedCallback (Widget,XEvent *);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel Resources */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static XtResource resources[] =
|
|
{
|
|
/* Callback resources */
|
|
{
|
|
XmNselectionChangedCallback,
|
|
XmCCallback,
|
|
XmRCallback,
|
|
sizeof(XtCallbackList),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . selection_changed_callback),
|
|
XmRImmediate,
|
|
(XtPointer) NULL
|
|
},
|
|
|
|
/* Label resources */
|
|
{
|
|
XmNlabelAlignment,
|
|
XmCLabelAlignment,
|
|
XmRAlignment,
|
|
sizeof(unsigned char),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . label_alignment),
|
|
XmRImmediate,
|
|
(XtPointer) XmALIGNMENT_CENTER
|
|
},
|
|
{
|
|
XmNlabelDirection,
|
|
XmCLabelDirection,
|
|
XmRStringDirection,
|
|
sizeof(unsigned char),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . label_direction),
|
|
XmRImmediate,
|
|
(XtPointer) XmSTRING_DIRECTION_L_TO_R
|
|
},
|
|
{
|
|
XmNfontList,
|
|
XmCFontList,
|
|
XmRFontList,
|
|
sizeof(XmFontList),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . font_list),
|
|
XmRImmediate,
|
|
(XtPointer) NULL
|
|
},
|
|
{
|
|
XmNlabelString,
|
|
XmCLabelString,
|
|
XmRXmString,
|
|
sizeof(XmString),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . label_string),
|
|
XmRImmediate,
|
|
(XtPointer) NULL
|
|
},
|
|
|
|
/* Truncation resources */
|
|
{
|
|
XmNtruncateLabel,
|
|
XmCTruncateLabel,
|
|
XmRBoolean,
|
|
sizeof(Boolean),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . truncate_label),
|
|
XmRImmediate,
|
|
(XtPointer) False
|
|
},
|
|
{
|
|
XmNtruncateProc,
|
|
XmCTruncateProc,
|
|
XmRProc,
|
|
sizeof(XtPointer),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . truncate_proc),
|
|
XmRImmediate,
|
|
(XtPointer) NULL
|
|
},
|
|
|
|
/* Selection resources */
|
|
{
|
|
XmNselected,
|
|
XmCSelected,
|
|
XmRBoolean,
|
|
sizeof(Boolean),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . selected),
|
|
XmRImmediate,
|
|
(XtPointer) False
|
|
},
|
|
{
|
|
XmNselectionColor,
|
|
XmCSelectionColor,
|
|
XmRPixel,
|
|
sizeof(Pixel),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . selection_color),
|
|
XmRCallProc,
|
|
(XtPointer) _XfeCallProcSelectPixel
|
|
},
|
|
{
|
|
XmNselectionModifiers,
|
|
XmCSelectionModifiers,
|
|
XmRModifiers,
|
|
sizeof(Modifiers),
|
|
XtOffsetOf(XfeLabelRec , xfe_label . selection_modifiers),
|
|
XmRImmediate,
|
|
(XtPointer) None
|
|
},
|
|
|
|
/* Force buffer type to XmBUFFER_NONE */
|
|
{
|
|
XmNbufferType,
|
|
XmCBufferType,
|
|
XmRBufferType,
|
|
sizeof(unsigned char),
|
|
XtOffsetOf(XfeLabelRec , xfe_primitive . buffer_type),
|
|
XmRImmediate,
|
|
(XtPointer) XmBUFFER_SHARED
|
|
},
|
|
|
|
{
|
|
XmNtraversalOn,
|
|
XmCTraversalOn,
|
|
XmRBoolean,
|
|
sizeof(Boolean),
|
|
XtOffsetOf(XfeLabelRec , primitive . traversal_on),
|
|
XmRImmediate,
|
|
(XtPointer) False
|
|
},
|
|
{
|
|
XmNhighlightThickness,
|
|
XmCHighlightThickness,
|
|
XmRHorizontalDimension,
|
|
sizeof(Dimension),
|
|
XtOffsetOf(XfeLabelRec , primitive . highlight_thickness),
|
|
XmRImmediate,
|
|
(XtPointer) 0
|
|
},
|
|
};
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeButton actions */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static XtActionsRec actions[] =
|
|
{
|
|
{ "Select", _XfeLabelSelect },
|
|
};
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel widget class record initialization */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
_XFE_WIDGET_CLASS_RECORD(label,Label) =
|
|
{
|
|
{
|
|
/* Core Part */
|
|
(WidgetClass) &xfePrimitiveClassRec, /* superclass */
|
|
"XfeLabel", /* class_name */
|
|
sizeof(XfeLabelRec), /* widget_size */
|
|
NULL, /* class_initialize */
|
|
ClassPartInit, /* class_part_initialize*/
|
|
FALSE, /* class_inited */
|
|
Initialize, /* initialize */
|
|
NULL, /* initialize_hook */
|
|
XtInheritRealize, /* realize */
|
|
actions, /* actions */
|
|
XtNumber(actions), /* num_actions */
|
|
resources, /* resources */
|
|
XtNumber(resources), /* num_resources */
|
|
NULLQUARK, /* xrm_class */
|
|
TRUE, /* compress_motion */
|
|
XtExposeCompressMaximal, /* compress_exposure */
|
|
TRUE, /* compress_enterleave */
|
|
FALSE, /* visible_interest */
|
|
Destroy, /* destroy */
|
|
XtInheritResize, /* resize */
|
|
XtInheritExpose, /* expose */
|
|
SetValues, /* set_values */
|
|
NULL, /* set_values_hook */
|
|
XtInheritSetValuesAlmost, /* set_values_almost */
|
|
GetValuesHook, /* get_values_hook */
|
|
NULL, /* accept_focus */
|
|
XtVersion, /* version */
|
|
NULL, /* callback_private */
|
|
_XfeLabelDefaultTranslations, /* tm_table */
|
|
XtInheritQueryGeometry, /* query_geometry */
|
|
XtInheritDisplayAccelerator, /* display accel */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XmPrimitive Part */
|
|
{
|
|
XmInheritBorderHighlight, /* border_highlight */
|
|
XmInheritBorderUnhighlight, /* border_unhighlight */
|
|
XtInheritTranslations, /* translations */
|
|
NULL, /* arm_and_activate */
|
|
NULL, /* syn resources */
|
|
0, /* num syn_resources */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XfePrimitive Part */
|
|
{
|
|
XfeInheritBitGravity, /* bit_gravity */
|
|
PreferredGeometry, /* preferred_geometry */
|
|
XfeInheritMinimumGeometry, /* minimum_geometry */
|
|
XfeInheritUpdateRect, /* update_rect */
|
|
PrepareComponents, /* prepare_components */
|
|
LayoutComponents, /* layout_components */
|
|
XfeInheritDrawBackground, /* draw_background */
|
|
XfeInheritDrawShadow, /* draw_shadow */
|
|
DrawComponents, /* draw_components */
|
|
NULL, /* extension */
|
|
},
|
|
|
|
/* XfeLabel Part */
|
|
{
|
|
LayoutString, /* layout_string */
|
|
DrawString, /* draw_string */
|
|
DrawSelection, /* draw_selection */
|
|
GetLabelGC, /* get_label_gc */
|
|
GetSelectionGC, /* get_selection_gc */
|
|
NULL, /* extension */
|
|
},
|
|
};
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* xfeLabelWidgetClass declaration. */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
_XFE_WIDGET_CLASS(label,Label);
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Core class methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
ClassPartInit(WidgetClass wc)
|
|
{
|
|
XfeLabelWidgetClass cc = (XfeLabelWidgetClass) wc;
|
|
XfeLabelWidgetClass sc = (XfeLabelWidgetClass) wc->core_class.superclass;
|
|
|
|
/* Resolve inheritance of all XfeLabel class methods */
|
|
_XfeResolve(cc,sc,xfe_label_class,layout_string,
|
|
XfeInheritLayoutString);
|
|
|
|
_XfeResolve(cc,sc,xfe_label_class,draw_string,
|
|
XfeInheritDrawString);
|
|
|
|
_XfeResolve(cc,sc,xfe_label_class,draw_selection,
|
|
XfeInheritDrawSelection);
|
|
|
|
_XfeResolve(cc,sc,xfe_label_class,get_label_gc,
|
|
XfeInheritGetLabelGC);
|
|
|
|
_XfeResolve(cc,sc,xfe_label_class,get_selection_gc,
|
|
XfeInheritGetSelectionGC);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
Initialize(Widget rw,Widget nw,ArgList args,Cardinal *nargs)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(nw);
|
|
|
|
/* Make sure rep types are ok */
|
|
XfeRepTypeCheck(nw,XmRAlignment,&lp->label_alignment,
|
|
XmALIGNMENT_CENTER);
|
|
|
|
XfeRepTypeCheck(nw,XmRStringDirection,&lp->label_direction,
|
|
XmSTRING_DIRECTION_L_TO_R);
|
|
|
|
/* Make sure the label is set up properly */
|
|
lp->label_string = XfeXmStringCopy(nw,lp->label_string,XtName(nw));
|
|
|
|
/* Make sure the font list is set up properly */
|
|
lp->font_list = XfeXmFontListCopy(nw,lp->font_list,XmLABEL_FONTLIST);
|
|
|
|
/* Allocate the label GCs */
|
|
lp->label_GC = XfeAllocateStringGc(nw,lp->font_list,
|
|
_XfeForeground(nw),None,True);
|
|
|
|
/* Allocate the label insensitive GCs */
|
|
lp->insensitive_top_GC = XfeAllocateStringGc(nw,lp->font_list,
|
|
_XfeTopShadowColor(nw),
|
|
None,True);
|
|
|
|
lp->insensitive_bottom_GC = XfeAllocateStringGc(nw,lp->font_list,
|
|
_XfeBottomShadowColor(nw),
|
|
None,True);
|
|
|
|
/* Allocate the selection GCs */
|
|
lp->selection_GC = XfeAllocateColorGc(nw,lp->selection_color,None,True);
|
|
|
|
/* Initialize private members */
|
|
lp->misc_offset = 0;
|
|
|
|
/* Finish of initialization */
|
|
_XfePrimitiveChainInitialize(rw,nw,xfeLabelWidgetClass);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
Destroy(Widget w)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
/* Release GCs */
|
|
XtReleaseGC(w,lp->label_GC);
|
|
XtReleaseGC(w,lp->insensitive_top_GC);
|
|
XtReleaseGC(w,lp->insensitive_bottom_GC);
|
|
XtReleaseGC(w,lp->selection_GC);
|
|
|
|
/* Free the label string */
|
|
XmStringFree(lp->label_string);
|
|
|
|
/* Free the font list */
|
|
XmFontListFree(lp->font_list);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static Boolean
|
|
SetValues(Widget ow,Widget rw,Widget nw,ArgList args,Cardinal *nargs)
|
|
{
|
|
XfeLabelPart * np = _XfeLabelPart(nw);
|
|
XfeLabelPart * op = _XfeLabelPart(ow);
|
|
Boolean label_gc_flag = False;
|
|
Boolean selection_gc_flag = False;
|
|
Boolean insensitive_top_gc_flag = False;
|
|
Boolean insensitive_bottom_gc_flag = False;
|
|
|
|
/* font_list */
|
|
if (np->font_list != op->font_list)
|
|
{
|
|
/* Make sure the new font is ok */
|
|
np->font_list = XfeXmFontListCopy(nw,np->font_list,XmLABEL_FONTLIST);
|
|
|
|
/* Free the old fontlist */
|
|
if (op->font_list)
|
|
{
|
|
XmFontListFree(op->font_list);
|
|
}
|
|
|
|
label_gc_flag = True;
|
|
insensitive_bottom_gc_flag = True;
|
|
insensitive_top_gc_flag = True;
|
|
|
|
_XfeConfigFlags(nw) |= XfeConfigGLE;
|
|
|
|
_XfePrepareFlags(nw) |= _XFE_PREPARE_LABEL_STRING;
|
|
}
|
|
|
|
/* label_string */
|
|
if (np->label_string != op->label_string)
|
|
{
|
|
/* Free the old string if needed */
|
|
if (op->label_string)
|
|
{
|
|
XmStringFree(op->label_string);
|
|
}
|
|
|
|
/* Make sure the new string is ok */
|
|
np->label_string = XfeXmStringCopy(nw,np->label_string,XtName(nw));
|
|
|
|
_XfeConfigFlags(nw) |= XfeConfigGLE;
|
|
|
|
_XfePrepareFlags(nw) |= _XFE_PREPARE_LABEL_STRING;
|
|
}
|
|
|
|
/* foreground */
|
|
if (_XfeForeground(nw) != _XfeForeground(ow))
|
|
{
|
|
label_gc_flag = True;
|
|
|
|
_XfeConfigFlags(nw) |= XfeConfigExpose;
|
|
}
|
|
|
|
/* top_shadow_color */
|
|
if (_XfeTopShadowColor(nw) != _XfeTopShadowColor(ow))
|
|
{
|
|
insensitive_top_gc_flag = True;
|
|
|
|
if (!_XfeIsSensitive(nw))
|
|
{
|
|
_XfeConfigFlags(nw) |= XfeConfigExpose;
|
|
}
|
|
}
|
|
|
|
/* bottom_shadow_color */
|
|
if (_XfeBottomShadowColor(nw) != _XfeBottomShadowColor(ow))
|
|
{
|
|
insensitive_bottom_gc_flag = True;
|
|
|
|
if (!_XfeIsSensitive(nw))
|
|
{
|
|
_XfeConfigFlags(nw) |= XfeConfigExpose;
|
|
}
|
|
|
|
}
|
|
|
|
/* label_alignment */
|
|
if (np->label_alignment != op->label_alignment)
|
|
{
|
|
/* Make sure the new label alignment is ok */
|
|
XfeRepTypeCheck(nw,XmRAlignment,&np->label_alignment,
|
|
XmALIGNMENT_CENTER);
|
|
|
|
_XfeConfigFlags(nw) |= XfeConfigLE;
|
|
}
|
|
|
|
/* label_direction */
|
|
if (np->label_direction != op->label_direction)
|
|
{
|
|
/* Make sure the new label direction is ok */
|
|
XfeRepTypeCheck(nw,XmRStringDirection,&np->label_direction,
|
|
XmSTRING_DIRECTION_L_TO_R);
|
|
|
|
_XfeConfigFlags(nw) |= XfeConfigExpose;
|
|
}
|
|
|
|
/* selected */
|
|
if (np->selected != op->selected)
|
|
{
|
|
_XfeConfigFlags(nw) |= XfeConfigExpose;
|
|
}
|
|
|
|
/* selection_color */
|
|
if (np->selection_color != op->selection_color)
|
|
{
|
|
selection_gc_flag = True;
|
|
|
|
_XfeConfigFlags(nw) |= XfeConfigExpose;
|
|
}
|
|
|
|
/* Update the label GC */
|
|
if (label_gc_flag)
|
|
{
|
|
/* Release the old label GC */
|
|
XtReleaseGC(nw,np->label_GC);
|
|
|
|
/* Allocate the new label GC */
|
|
np->label_GC = XfeAllocateStringGc(nw,np->font_list,
|
|
_XfeForeground(nw),None,True);
|
|
}
|
|
|
|
/* Update the selection GC */
|
|
if (selection_gc_flag)
|
|
{
|
|
/* Release the old selection GC */
|
|
XtReleaseGC(nw,np->selection_GC);
|
|
|
|
/* Allocate the new selection GC */
|
|
np->selection_GC = XfeAllocateColorGc(nw,np->selection_color,
|
|
None,True);
|
|
}
|
|
|
|
/* Update the insens top GC */
|
|
if (insensitive_top_gc_flag)
|
|
{
|
|
/* Release the old label GC */
|
|
XtReleaseGC(nw,np->insensitive_top_GC);
|
|
|
|
/* Allocate the new label GC */
|
|
np->insensitive_top_GC =
|
|
XfeAllocateStringGc(nw,np->font_list,
|
|
_XfeTopShadowColor(nw),
|
|
None,True);
|
|
}
|
|
|
|
|
|
/* Update the insens bottom GC */
|
|
if (insensitive_bottom_gc_flag)
|
|
{
|
|
/* Release the old label GC */
|
|
XtReleaseGC(nw,np->insensitive_bottom_GC);
|
|
|
|
/* Allocate the new label GC */
|
|
np->insensitive_bottom_GC =
|
|
XfeAllocateStringGc(nw,np->font_list,
|
|
_XfeBottomShadowColor(nw),
|
|
None,True);
|
|
}
|
|
|
|
|
|
|
|
return _XfePrimitiveChainSetValues(ow,rw,nw,xfeLabelWidgetClass);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
GetValuesHook(Widget w,ArgList args,Cardinal* nargs)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
Cardinal i;
|
|
|
|
for (i = 0; i < *nargs; i++)
|
|
{
|
|
/* label_string */
|
|
if (strcmp(args[i].name,XmNlabelString) == 0)
|
|
{
|
|
*((XtArgVal *) args[i].value) =
|
|
(XtArgVal) XmStringCopy(lp->label_string);
|
|
}
|
|
/* font_list */
|
|
else if (strcmp(args[i].name,XmNfontList) == 0)
|
|
{
|
|
*((XtArgVal *) args[i].value) =
|
|
(XtArgVal) XmFontListCopy(lp->font_list);
|
|
}
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfePrimitive methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
PreferredGeometry(Widget w,Dimension *width,Dimension *height)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
*width = _XfeOffsetLeft(w) + _XfeOffsetRight(w) + lp->label_rect.width;
|
|
*height = _XfeOffsetTop(w) + _XfeOffsetBottom(w) + lp->label_rect.height;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
PrepareComponents(Widget w,int flags)
|
|
{
|
|
if (flags & _XFE_PREPARE_LABEL_STRING)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
/* Obtain the labels's dimensions */
|
|
XmStringExtent(lp->font_list,
|
|
lp->label_string,
|
|
&lp->label_rect.width,
|
|
&lp->label_rect.height);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
LayoutComponents(Widget w)
|
|
/*----------------------------------------------------------------------*/
|
|
{
|
|
/* Invoke layout_string method */
|
|
_XfeLabelLayoutString(w);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
DrawComponents(Widget w,XEvent *event,Region region,XRectangle * clip_rect)
|
|
{
|
|
/* Invoke draw_selection method */
|
|
_XfeLabelDrawSelection(w,event,region,clip_rect);
|
|
|
|
/* Invoke draw_string method */
|
|
_XfeLabelDrawString(w,event,region,clip_rect);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static GC
|
|
GetLabelGC(Widget w)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
return lp->label_GC;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static GC
|
|
GetSelectionGC(Widget w)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
return lp->selection_GC;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
LayoutString(Widget w)
|
|
/*----------------------------------------------------------------------*/
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
/* Layout the label according to the alignment */
|
|
switch(lp->label_alignment)
|
|
{
|
|
case XmALIGNMENT_BEGINNING:
|
|
|
|
lp->label_rect.x = _XfeRectX(w);
|
|
|
|
break;
|
|
|
|
case XmALIGNMENT_CENTER:
|
|
|
|
lp->label_rect.x = (_XfeWidth(w) - lp->label_rect.width) / 2;
|
|
|
|
break;
|
|
|
|
case XmALIGNMENT_END:
|
|
|
|
lp->label_rect.x =
|
|
XfeWidth(w) -
|
|
lp->label_rect.width -
|
|
_XfeOffsetRight(w);
|
|
|
|
break;
|
|
}
|
|
|
|
/* the label is always centered vertically */
|
|
lp->label_rect.y = (_XfeHeight(w) - lp->label_rect.height) / 2;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
DrawString(Widget w,XEvent * event,Region region,XRectangle * clip_rect)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
XRectangle rect;
|
|
XmString string = NULL;
|
|
Boolean need_to_free_string = False;
|
|
|
|
/* Make sure the label has something before drawing */
|
|
if (!lp->label_rect.width || !lp->label_rect.height || !lp->label_string)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* The height and y coordinate are the same regardless of truncation */
|
|
rect.height = lp->label_rect.height;
|
|
rect.y = lp->label_rect.y;
|
|
|
|
/* Determine whether we need to truncate the string */
|
|
if (lp->truncate_label && (lp->label_rect.width > _XfeRectWidth(w)))
|
|
{
|
|
string = CreateTruncatedString(w);
|
|
|
|
rect.width = _XfeRectWidth(w);
|
|
rect.x = _XfeRectX(w);
|
|
|
|
need_to_free_string = True;
|
|
}
|
|
else
|
|
{
|
|
string = lp->label_string;
|
|
|
|
rect.width = lp->label_rect.width;
|
|
rect.x = lp->label_rect.x;
|
|
|
|
need_to_free_string = False;
|
|
}
|
|
|
|
assert( string != NULL );
|
|
|
|
/* Determine which gc to use to render the label */
|
|
if (_XfeIsSensitive(w))
|
|
{
|
|
/* Draw the string once */
|
|
XmStringDraw(XtDisplay(w),
|
|
_XfePrimitiveDrawable(w),
|
|
lp->font_list,
|
|
string,
|
|
_XfeLabelGetLabelGC(w),
|
|
rect.x + lp->misc_offset,
|
|
rect.y + lp->misc_offset,
|
|
rect.width,
|
|
lp->label_alignment,
|
|
lp->label_direction,
|
|
&_XfeWidgetRect(w));
|
|
}
|
|
else
|
|
{
|
|
/* Draw the string twice to achieve that cool insensitve look */
|
|
XmStringDraw(XtDisplay(w),
|
|
_XfePrimitiveDrawable(w),
|
|
lp->font_list,
|
|
string,
|
|
lp->insensitive_top_GC,
|
|
rect.x + INSENSITIVE_OFFSET + lp->misc_offset,
|
|
rect.y + INSENSITIVE_OFFSET + lp->misc_offset,
|
|
rect.width,
|
|
lp->label_alignment,
|
|
lp->label_direction,
|
|
&_XfeWidgetRect(w));
|
|
|
|
XmStringDraw(XtDisplay(w),
|
|
_XfePrimitiveDrawable(w),
|
|
lp->font_list,
|
|
string,
|
|
lp->insensitive_bottom_GC,
|
|
rect.x + lp->misc_offset,
|
|
rect.y + lp->misc_offset,
|
|
rect.width,
|
|
lp->label_alignment,
|
|
lp->label_direction,
|
|
&_XfeWidgetRect(w));
|
|
}
|
|
|
|
/* Free the string if needed */
|
|
if (need_to_free_string)
|
|
{
|
|
XmStringFree(string);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
DrawSelection(Widget w,XEvent * event,Region region,XRectangle * clip_rect)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
Dimension dx;
|
|
Dimension dy;
|
|
|
|
/* Make sure the widget is selected */
|
|
if (!lp->selected)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Make sure the label has something before drawing */
|
|
if (!lp->label_rect.width || !lp->label_rect.height || !lp->label_string)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Compute the extra offset for the selection */
|
|
dx = XfeMin(_XfeMarginLeft(w),_XfeMarginRight(w));
|
|
dx = XfeMin(dx,1);
|
|
|
|
dy = XfeMin(_XfeMarginTop(w),_XfeMarginBottom(w));
|
|
dy = XfeMin(dy,1);
|
|
|
|
XFillRectangle(XtDisplay(w),
|
|
_XfePrimitiveDrawable(w),
|
|
_XfeLabelGetSelectionGC(w),
|
|
lp->label_rect.x - dx,
|
|
lp->label_rect.y - dy,
|
|
lp->label_rect.width + 2 * dx,
|
|
lp->label_rect.height + 2 * dy);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel Method invocation functions */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
_XfeLabelLayoutString(Widget w)
|
|
{
|
|
XfeLabelWidgetClass lc = (XfeLabelWidgetClass) XtClass(w);
|
|
|
|
if (lc->xfe_label_class.layout_string)
|
|
{
|
|
(*lc->xfe_label_class.layout_string)(w);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
_XfeLabelDrawString(Widget w,
|
|
XEvent * event,
|
|
Region region,
|
|
XRectangle * clip_rect)
|
|
{
|
|
XfeLabelWidgetClass lc = (XfeLabelWidgetClass) XtClass(w);
|
|
|
|
if (lc->xfe_label_class.draw_string)
|
|
{
|
|
(*lc->xfe_label_class.draw_string)(w,event,region,clip_rect);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
_XfeLabelDrawSelection(Widget w,
|
|
XEvent * event,
|
|
Region region,
|
|
XRectangle * clip_rect)
|
|
{
|
|
XfeLabelWidgetClass lc = (XfeLabelWidgetClass) XtClass(w);
|
|
|
|
if (lc->xfe_label_class.draw_selection)
|
|
{
|
|
(*lc->xfe_label_class.draw_selection)(w,event,region,clip_rect);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ GC
|
|
_XfeLabelGetLabelGC(Widget w)
|
|
{
|
|
XfeLabelWidgetClass lc = (XfeLabelWidgetClass) XtClass(w);
|
|
|
|
assert( lc->xfe_label_class.get_label_gc != NULL );
|
|
|
|
return (*lc->xfe_label_class.get_label_gc)(w);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ GC
|
|
_XfeLabelGetSelectionGC(Widget w)
|
|
{
|
|
XfeLabelWidgetClass lc = (XfeLabelWidgetClass) XtClass(w);
|
|
|
|
assert( lc->xfe_label_class.get_selection_gc != NULL );
|
|
|
|
return (*lc->xfe_label_class.get_selection_gc)(w);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* Misc XfeLabel functions */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
static XmString
|
|
CreateTruncatedString(Widget w)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
XmString result = NULL;
|
|
|
|
/* Make sure the truncate proc is good */
|
|
if (lp->truncate_proc)
|
|
{
|
|
String psz_tmp;
|
|
|
|
/* Access the label as a psz String */
|
|
XmStringGetLtoR(lp->label_string,XmFONTLIST_DEFAULT_TAG,&psz_tmp);
|
|
|
|
if (psz_tmp)
|
|
{
|
|
Dimension max_width = _XfeRectWidth(w) - lp->misc_offset;
|
|
|
|
if (!_XfeIsSensitive(w))
|
|
{
|
|
max_width -= 1;
|
|
}
|
|
|
|
/* Create a truncated string */
|
|
result = (*lp->truncate_proc)(psz_tmp,
|
|
XmFONTLIST_DEFAULT_TAG,
|
|
lp->font_list,
|
|
max_width);
|
|
|
|
/* Free the psz String */
|
|
XtFree(psz_tmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_XfeWarning(w,MESSAGE2);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void
|
|
InvokeSelectionChangedCallback(Widget w,XEvent * event)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
/* Invoke the callbacks only if needed */
|
|
if (lp->selection_changed_callback)
|
|
{
|
|
XfeLabelSelectionChangedCallbackStruct cbs;
|
|
|
|
cbs.event = event;
|
|
cbs.reason = XmCR_SELECTION_CHANGED;
|
|
cbs.selected = lp->selected;
|
|
|
|
/* Flush the display */
|
|
XFlush(XtDisplay(w));
|
|
|
|
/* Invoke the Callback List */
|
|
XtCallCallbackList(w,lp->selection_changed_callback,&cbs);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel action procedures */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
_XfeLabelSelect(Widget w,XEvent * event,char ** params,Cardinal * nparams)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
/* Make sure we are not pretending to be insensitive */
|
|
if (!_XfeIsSensitive(w))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Look for modifiers that matches the selection modifiers */
|
|
if (_XfeLabelAcceptSelectionEvent(w,event,True))
|
|
{
|
|
_XfeLabelSetSelected(w,event,!lp->selected,True);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel private functions */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ Boolean
|
|
_XfeLabelAcceptSelectionEvent(Widget w,XEvent * event,Boolean inside_label)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
Boolean result = False;
|
|
|
|
/* Look for modifiers that matches the selection modifiers */
|
|
if ((XfeEventGetModifiers(event) & lp->selection_modifiers) ||
|
|
(lp->selection_modifiers == AnyModifier))
|
|
{
|
|
/* Make sure the event's x,y occured inside the label if needed */
|
|
if (inside_label)
|
|
{
|
|
int x;
|
|
int y;
|
|
|
|
/* Determine if the pointer is in the label */
|
|
result = (XfeEventGetXY(event,&x,&y) &&
|
|
XfePointInRect(&lp->label_rect,x,y));
|
|
}
|
|
else
|
|
{
|
|
result = True;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
_XfeLabelSetSelected(Widget w,
|
|
XEvent * event,
|
|
Boolean selected,
|
|
Boolean invoke_callbacks)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
assert( XfeIsLabel(w) );
|
|
|
|
/* Make sure the selection has changed */
|
|
if (lp->selected == selected)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Assign the new selection */
|
|
lp->selected = selected;
|
|
|
|
/* Make sure the widget is alive and kicking before drawing */
|
|
if (_XfeIsRealized(w) && _XfeIsManaged(w))
|
|
{
|
|
/* Erase the old stuff */
|
|
_XfePrimitiveClearBackground(w);
|
|
|
|
/* Redraw the buffer */
|
|
_XfePrimitiveDrawEverything(w,NULL,NULL);
|
|
|
|
/* Draw the buffer onto the window */
|
|
XfeExpose(w,NULL,NULL);
|
|
}
|
|
|
|
/* Invoke the selection callbacks if needed */
|
|
if (invoke_callbacks)
|
|
{
|
|
InvokeSelectionChangedCallback(w,event);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
/* */
|
|
/* XfeLabel Public Methods */
|
|
/* */
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ Widget
|
|
XfeCreateLabel(Widget pw,char * name,ArgList av,Cardinal ac)
|
|
{
|
|
return XtCreateWidget(name,xfeLabelWidgetClass,pw,av,ac);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
XfeLabelSetString(Widget w,XmString xm_label)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
assert( _XfeIsAlive(w) );
|
|
|
|
/* Make sure the label is different */
|
|
if (XmStringByteCompare(xm_label,lp->label_string))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Free the old string */
|
|
XmStringFree(lp->label_string);
|
|
|
|
/* Make a copy of the given string or set it to "" if null */
|
|
if (xm_label)
|
|
{
|
|
lp->label_string = XfeXmStringCopy(w,xm_label,XtName(w));
|
|
}
|
|
else
|
|
{
|
|
lp->label_string = XmStringCreate("",XmFONTLIST_DEFAULT_TAG);
|
|
}
|
|
|
|
|
|
/* Prepare the label */
|
|
_XfePrimitivePrepareComponents(w,_XFE_PREPARE_LABEL_STRING);
|
|
|
|
/* Relayout the widget */
|
|
_XfePrimitiveLayoutComponents(w);
|
|
|
|
/* Make sure the widget is realized before drawing anything */
|
|
if (!XtIsRealized(w))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Erase the old stuff */
|
|
_XfePrimitiveClearBackground(w);
|
|
|
|
/* Redraw the buffer */
|
|
_XfePrimitiveDrawEverything(w,NULL,NULL);
|
|
|
|
/* Draw the buffer onto the window */
|
|
XfeExpose(w,NULL,NULL);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
XfeLabelSetStringPSZ(Widget w,String psz_label)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
XmString xm_new_label;
|
|
|
|
assert( _XfeIsAlive(w) );
|
|
|
|
/* Set the new string */
|
|
if (psz_label)
|
|
{
|
|
xm_new_label = XmStringCreate(psz_label,XmFONTLIST_DEFAULT_TAG);
|
|
}
|
|
else
|
|
{
|
|
xm_new_label = XmStringCreate("",XmFONTLIST_DEFAULT_TAG);
|
|
}
|
|
|
|
/* Make sure the label is different */
|
|
if (XmStringByteCompare(xm_new_label,lp->label_string))
|
|
{
|
|
XmStringFree(xm_new_label);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Free the old string */
|
|
XmStringFree(lp->label_string);
|
|
|
|
lp->label_string = xm_new_label;
|
|
|
|
/* Prepare the label */
|
|
_XfePrimitivePrepareComponents(w,_XFE_PREPARE_LABEL_STRING);
|
|
|
|
/* Relayout the widget */
|
|
_XfePrimitiveLayoutComponents(w);
|
|
|
|
/* Make sure the widget is realized before drawing anything */
|
|
if (!XtIsRealized(w))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Erase the old stuff */
|
|
_XfePrimitiveClearBackground(w);
|
|
|
|
/* Redraw the buffer */
|
|
_XfePrimitiveDrawEverything(w,NULL,NULL);
|
|
|
|
/* Draw the buffer onto the window */
|
|
XfeExpose(w,NULL,NULL);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
/* extern */ void
|
|
XfeLabelSetSelected(Widget w,Boolean selected)
|
|
{
|
|
XfeLabelPart * lp = _XfeLabelPart(w);
|
|
|
|
assert( XfeIsLabel(w) );
|
|
|
|
_XfeLabelSetSelected(w,NULL,selected,False);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|