Click here to Skip to main content
Click here to Skip to main content

Programming Xlib with Mono Develop - Part 4: FWF Xt widgets

, 7 Nov 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
How to use Free Widget Foundation Xt compatible widgets from Mono Develop C#

Introduction

This article shows how to access most of the Xfwf/Free Widget Foundation widgets from C# using Mono Develop. A lot of API calls are ready-to-use defined and tested and some challenges are mastered, e.g. setting the right dependencies (to compile the Xfwf/Free Widget Foundation widgets), correction of compilation errors and optimization of the impression. This article is aimed to point out that programming Xfxf/Free Widget Foundation widgets with C# can be easyly achieved and greatly improve the user experience (showcase). It provides a sample application's complete project for 32 bit and 64 bit.

Background

This is the fourth article in a series of articles examining X* API calls from C# using Mono Develop. The first article was Programming Xlib with Mono Develop - Part 1: Low-level (proof of concept) and dealed with Xlib/X11. The second article was Programming Xlib with Mono Develop - Part 2: Athena widgets (proof of concept) and dealed with Xt/Athena. And the third article was Programming Xlib with Mono Develop - Part 3: Motif widgets (proof of concept) and dealed with Xm/Motif. The current article goes ahead to the Xfwf/Free Widget Foundation widgets and shows how to use them from a modern language/IDE like C#/Mono. The focus is on the Xt/Athena compatible Xfwf/Free Widget Foundation widgets.

This article illustrates how easy programming Xfwf/Free Widget Foundation using Xfwf API calls from C# is to achieve. Most of the widgets are Xt/Athena based but there are some Xm/Motif based widgets too. Since Open Motif made Motif available with source code and under a public license, almost every XWindow system can deal with the Motif widgets royalty free. So all Xfwf/Free Widget Foundation widgets are available and an application can utilize any mix of Xt/Athena, Xm/Motif and Xfwf/Free Widget Foundation widgets.

Using the code

The latest known version of Xfwf/Free Widget Foundation widgets is "FWF Version 4.0, 18 Apr 1996" and can be found on many servers for download as fwf-4.0.tar.gz. The project hasn't been maintained since 1996, but the widgets are still very useful and not comparable to any Xt/Athena or Xm/Motif widgets. Neither Free Widget Foundation nor the major programmer Brian K Totty (who wrote a lot of the Free Widget Foundation widgets during his time at Department of Computer Science * University Of Illinois at Urbana-Champaign and maintained the distribution until version 3.671) have a home page. Bert Bos (who also wrote a lot of the Free Widget Foundation widgets during his time at the University of Groningen and maintained the distribution starting with version 3.7) has a home page, where Xfwf/Free Widget Foundation widgets is mentioned briefly.
 
The common way to use the widgets is to compile the source tree as described in the README.BUILD file and to reference the library from the project. But this procedure didn't work. Since the Xfwf/Free Widget Foundation widgets have not been maintained after 1996, some declarations and references are outdated and have to be corrected. Moreover not only that FileComp/getod.c, EzMenu/EzME.c, CMap/Cmap.c, HDial/Hdial.c, Shistogram/Shistogram.c and IconBox/IconBoxT.c have compilation errors to fix, but the sub directories HTML2 and SSGML can't be compiled at all.
That's why this article follows a different approach and incorporates widget by widget into a Mono C project named FWF (targeting the libXfwf.so) of the sample application's solution and modifies the widget sources individually to compile.

The sample application was written with Mono Develop 2.4.1 for Mono 2.8.1 on OPEN SUSE 11.3 Linux 32 bit EN and GNOME desktop. Neither the port to any older nor to any newer version should be a problem. However the software packsges X11, Xt and Xpm must be installed. The sample application's solution consists of five projects (the complete sources are provided for download):
  • FWF containes a large part of the original source code tree of Xfxf/Free Widget Foundation widgets (as far as incorporated into the sample application) and compiles to the libXfwf.so
  • X11Wrapper defines the function prototypes, structures and types for Xlib/X11 calls to the libX11.so (already known from the first article of this series)
  • XawNative contains a very little amount of native C code to access Athena widget class records and to transform managed data into natice structures and compiles to libXawNative.so (already known from the second article of this series)
  • XtWrapper defines the function prototypes, structures and types for Xt calls to the libXt.so (already known from the second article of this series)
  • Xfwf contains the sample application based on Xt/Athena and Xfwf/Free Widget Foundation widgets  

bit solution is the definition of some types, as already described in the first article of this series.
The application hast test code for every Xfwf/Free Widget Foundation widget described below in the FWF Widget hierarchy.



Look & feel on GNOME desktop 2.30.0 (32 bit).

32 bit vs. 64 bit

The sample application is also tested with Mono Develop 3.0.6 for Mono 3.0.4 on OPEN SUSE 12.3 Linux 64 bit DE and GNOME desktop, IceWM, TWM und Xfce. The only difference between the 32 bit and the 64 bit solution is the definition of some types, as already described in the first article of of this series, chapter Using the code/32 bit vs. 64 bit.

FWF Widget hierarchy

Core
  ⌊ XfwfCircPerc
  ⌊ Composite
  | ⌊ XfwfCommon
  | | ⌊ XfwfFrame
  | | | ⌊ XfwfBoard
  | | | | ⌊ XfwfAnimator
  | | | | ⌊ XfwfArrow
  | | | | ⌊ XfwfEnforcer
  | | | | ⌊ XfwfIcon
  | | | | ⌊ XfwfLabel
  | | | | | ⌊ XfwfButton
  | | | | | | ⌊ XfwfPullDown
  | | | | | | | ⌊ XfwfOptionButton
  | | | | | | ⌊ XfwfToggle
  | | | | | ⌊ XfwfSlider2
  | | | | | | ⌊ XfwfSlider4
  | | | | | ⌊ XfwfSpinLabel
  | | | | ⌊ XfwfRowCol
  | | | | | ⌊ XfwfGroup
  | | | | | | ⌊ XfwfRadioGroup
  | | | | ⌊ XfwfRows
  | | | | | ⌊ XfwfMenuBar
  | | | | ⌊ XfwfScrollbar
  | | | | | ⌊ XfwfHScrollbar
  | | | | | ⌊ XfwfVScrollbar
  | | | | ⌊ XfwfScrolledWindow
  | | | | ⌊ XfwfScrolledWindow3
  | | | | ⌊ XfwfTabs
  | | ⌊ Constraint
  | | | ⌊ XfwfStack
  ⌊ Shell
  | ⌊ OverrideShell
  |   ⌊ XfwfTextMenu
  ⌊ Simple
  | ⌊ XfwfMultiList
  ⌊ XfwfPcBar
  ⌊ XfwfThumbWheel
  ⌊ XfwfThumbWheel2 

The Xfwf/Free Widget Foundation widget set is a "a collection of no-cost, freely redistributable X graphical user interface widgets". The next chapters contain descriptions, that are more or less based on the respective widget's man page, included in the Xfwf/Free Widget Foundation distribution, extended by screen shots, sample code and hints.

XfwfCircPerc 

The XfwfCircPerc widget can be used to indicate the progress that is made by an application, for example in a lengthy computation. This is done by displaying a circle, in which a colored pie-slice indicates the amount of work already done, and in which the remainder of the circle, filled in with another color, indicates the amount of work yet to be done. The percentage done can be indicated with a two decimal accuracy. 

Inheritance (↑) 

Core --> XfwfCircPerc

New Resources

NameClass Type Default
XXtNborderColor XtCBorderColor Pixel black 
XfwfNcompletedColor XtCCompletedColor Pixel yellow 
XfwfNinteriorColorXtCInteriorColor Pixelred
XfwfNpercentageCompleted XtCPercentageCompleted int 

Usage

IntPtr circPerc = Xtlib.XtCreateManagedWidget("CircularPercentage",
                    Xfwflib.Xt_XfwfCircularPercentageWidgetClass(), circpercBox,
                    Arg.Zero, (XCardinal)0);
 
...
 
// Add 10 percent (that is to shift by 2 digits).
_circularPercValue += 1000;
Xfwflib.XfwfCircularPercentageSetPercentage (circPerc, _circularPercValue); 

XfwfPcBar

The XfwfPcBarc widget is used to display a horizontal (or vertical) rectangular box in which a percentage from 0% to 100% is indicated by a bar that extends across (or up) the box. The actual percentage value can optionally be displayed in text form, centered in the box. 

Inheritance (↑)

Core --> XfwfPcBar

New Resources

NameClass Type Default
XtNforeground XtCForegroundPixel  Pixel XtDefaultForeground  
XfwfNpercentage  XtCPercentage  int0
XfwfNdisplaypc XtCDisplaypc Boolean False
XfwfNvertical XtNvertical  Boolean False  
XtNfont  XtNfont FontStruct XtDefaultFont  

Usage

Arg[] pcBarArgs = { new Arg (XtNames.XtNwidth,          (XtArgVal)25),
                    new Arg (XtNames.XtNheight,         (XtArgVal)120),
                    new Arg (XfwfNames.XfwfNvertical,   (XtArgVal)1),
                    new Arg (XfwfNames.XfwfNpercentage, (XtArgVal)0),
                    new Arg (XfwfNames.XfwfNdisplaypc,  (XtArgVal)1),
                    new Arg (XfwfNames.XfwfNshowZero,   (XtArgVal)1) };
IntPtr pcboxPerc = Xtlib.XtCreateManagedWidget("PercentageBar1",
                    Xfwflib.Xt_XfwfPcBarWidgetClass(), pcBarBox,
                    pcBarArgs, (XCardinal)6);

 
...
 
Xfwflib.XfwfPcBarSetPercentage (_pcbox1Perc, pcboxPerc);

XfwfThumbWheel

The XfwfThumbWheel widget is a very basic implementation of a vertically placed valuator that can be turned up or down. It can serve as a scroller or valuator. The turning effect is achieved by showing a series of prepared images one after the other.

If Xpm is available, the images are smooth gray scale. Otherwise the fallback images are pixelated. 

Inheritance (↑) 

Core --> XfwfThumbWheel

Code canges

Additional default translations, now these keyboard bindings are supported:
  • < Btn1Down> turn the wheel using step resource value as step width
  • < Btn2Down> turn the wheel using step resource half value as step width
  • < Btn3Down> turn the wheel using step resource quarter value as step width
  • < Key>Up and <Key>Left to turn up using step resource value as step width
  • Shift<Key>Up and Shift<Key>Left to turn up using step resource half value as step width
  • Ctrl<Key>Up and Ctrl<Key>Left to turn up using step resource quarter value as step width
  • < Key>Down and <Key>Right to turn down using step resource value as step width
  • Shift<Key>Down and Shift<Key>Right to turn down using step resource half value as step width
  • Ctrl<Key>Down and Ctrl<Key>Right to turn down using step resource quarter value as step width

New Resources

Name ClassTypeDefault 
XfwfNnumberOfPictures XtCNumberOfPictures int 
XfwfNpictures XtCPictures ImageList NULL
XfwfNvertical XtCVertical Boolean True
XfwfNclickArea XtCClickArea Dimension
XfwfNmaxValueXtCMaxValu int100
XfwfNminValueXtCMinValueint0
XtNvalueXtCValueint0
XfwfNstepXtSCtepint1
XfwfNinitialDelayXtCInitialDelayint500
XfwfNrepeatDelayXtCRepeatDelayint50
XfwfNsensitivityXtCSensitivityint
XfwfNscrollCallbackXtCScrollCallbackCallbackNULL
XfwfNscrollResponse XtNscrollResponseCallbackscroll_response

Usage

Arg[] thwheelArgs  = { new Arg(XfwfNames.XfwfNvertical,    (XtArgVal)0) };
IntPtr thWheel     = Xtlib.XtCreateManagedWidget("ThumbWheel3",
                        Xfwflib.Xt_XfwfThumbWheelWidgetClass(), thwheelBox,
                        thwheelArgs, (XCardinal)1); 

Callback usage 

Connect the callback via XfwfNames.XfwfNscrollCallback.
/// <summary> The callback for any thumb wheel scroll event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void ThumbWheelScrollCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    //XfwfScrollInfo scrollInfo = (callData != IntPtr.Zero ? (XfwfScrollInfo)
    //    Marshal.PtrToStructure (callData, typeof(XfwfScrollInfo)) : new XfwfScrollInfo());

    TInt val = Xtlib.XtGetValueOfInt (widget, XtNames.XtNvalue);
    Console.WriteLine ("ThumbWheel position {0}", val);
}

XfwfThumbWheel2

The XfwfThumbWheel2 is almost the same as the XfwfThumbWheel widget, but Xpm is not required, the images are always pixelated, and a horizontal orientation is not supported.  

Inheritance (↑)

Core --> XfwfThumbWheel2

New Resources

Name ClassTypeDefault 
XfwfNnumberOfPictures XtCNumberOfPictures int 
XfwfNpictures XtCPictures ImageList NULL
XfwfNclickArea XtCClickArea Dimension
XfwfNmaxValueXtCMaxValu int100
XfwfNminValueXtCMinValueint0
XtNvalueXtCValueint0
XfwfNstepXtSCtepint1
XfwfNinitialDelayXtCInitialDelayint500
XfwfNrepeatDelayXtCRepeatDelayint50
XfwfNsensitivityXtCSensitivityint
XfwfNscrollCallbackXtCScrollCallbackCallbackNULL
XfwfNscrollResponse XtNscrollResponseCallbackscroll_response

Usage

See XfwfThumbWheel.

Callback usage

See XfwfThumbWheel.

XfwfCommon

The XfwfCommon widget serves as superclass for many other widgets. It defines some resources, types, converters, etc. and implements keyboard traversal.

Inheritance (↑)

Core --> Composite --> XfwfCommon

New Resources

Name ClassTypeDefault 
XfwfNuseXCC XtCUseXCC Boolean True 
XfwfNusePrivateColormap XtCUsePrivateColormap Boolean False 
XfwfNuseStandardColormaps XtCUseStandardColormaps Boolean True 
XfwfNstandardColormap XtCStandardColormap Atom 0
XfwfNxcc XtCXcc XCC create_xcc 
XfwfNtraversalOn XtCTraversalOn Boolean True 
XfwfNhighlightThickness XtCHighlightThickness Dimension 2
XfwfNhighlightColor XtCHighlightColor Color XtDefaultForeground  
XtNbackground XtNbackground Color XtDefaultBackground 
XfwfNhighlightPixmap XtCHighlightPixmap Pixmap None
XfwfNnextTop XtCNextTop Callback NULL
XfwfNuserData XtCUserData Pointer NULL

Usage

Do not instantiate XfwfCommon.

XfwfMultiList

The XfwfMultiList widget is a string list widget, similar to the Xt/Athena List widget, but with the following significant differences:
  • Multiple items can be selected at one time.
  • Colors can be specified for highlighting.  

In addition to setting and unsetting items with the Set() and Unset() actions, XfwfMultiList also supports toggling (selected item becomes unselected, unselected item becomes selected) with Toggle() and opening of objects (e.g. might be used with a double-click) with Open().

The return structure is now more complicated, listing what type of operation generated the callback (highlighting an item, unhighlighting an item, opening an item, requesting the current status), what item was clicked on to produce this callback, and the list of what items are currently selected. Items can be individually disabled, by setting the sensitivity array. internalWidth and internalHeight resources have been removed. 

Inheritance (↑)

Core --> Simple --> XfwfMultiList

New Resources

Name ClassTypeDefault 
XfwfNborder  XtCBorder Pixel XtDefaultForeground
XtNcallback XtCCallback Callback NULL
XfwfNcolumnWidth XtCColumnWidth Dimension
XfwfNcolumnSpacing XtCColumnSpacing Dimension 8
XfwfNcursor XtCCursor Cursor left_ptr
XfwfNdefaultColumns XtCDefaultColumns int 1
XtNfont XtCFont XFontStruct XtDefaultFont
XfwfNforceColumns XtCForceColumns Boolean False 
XtNforeground XtCForeground Pixel XtDefaultForeground
XfwfNhighlightBackground XtCHighlightBackground Pixel XtDefaultForeground
XfwfNhighlightForeground XtCHighlightForeground Pixel XtDefaultBackground
XfwfNinsensitiveBorder XtCInsensitiveBorder Pixmap Gray
XfwfNlist XtCList String NULL 
XfwfNlongest XtCLongest int 0
XfwfNmaxSelectable XtCMaxSelectable int 1
XfwfNnumberStrings XtCNumberStrings int 0
XfwfNpasteBuffer XtCPasteBuffer Boolean False
XfwfNrowHeightXtCRowHeightDimension0
XfwfNrowSpacingXtCRowSpacingDimension2
XfwfNsensitiveArrayXtCSensitiveArrayBooleanFalse
XfwfNtabListXtCTabList StringNULL
XfwfNtabsXtCTabsint0
XfwfNverticalListXtCVerticalListBooleanFalse

Usage

string[] mlText    = { "Happy New Year",   "To You",
                       "Your Family",      "And Friends",
                       "Peace And Joy",    "Best wishes 2013!",
                       "(insensitive)",    null};
TBoolean[] mlSensi = { (TBoolean)1,        (TBoolean)1,
                       (TBoolean)1,        (TBoolean)1,
                       (TBoolean)1,        (TBoolean)1,        (TBoolean)0};
Arg[] mlistT1Args  = { new Arg(XfwfNames.XfwfNlist,            mlText),
                       new Arg(XfwfNames.XfwfNsensitiveArray, mlSensi),
                       new Arg(XfwfNames.XfwfNmaxSelectable,  (XtArgVal)3),
                       new Arg(XfwfNames.XfwfNdefaultColumns, (XtArgVal)2),
                       new Arg(XfwfNames.XfwfNnumberStrings,  (XtArgVal)7),
                       new Arg(XtNames.XtNbackground,         (XtArgVal)_backgroundPixel),
                       new Arg(XtNames.XtNborderWidth,        (XtArgVal)2),
                       new Arg(XtNames.XtNborderColor,        (XtArgVal)_lightborderPixel) }; 

Callback usage

Connect the callback via XtNames.XtNcallback.
/// <summary> The callback for any multi list selection event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void MultiListCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    if (callData == IntPtr.Zero)
    {
        Console.WriteLine ("Multilist selected.");
        return;
    }
 
    XfwfMultiListReturnStruct mlrs = (callData != IntPtr.Zero ? (XfwfMultiListReturnStruct)
                    Marshal.PtrToStructure (callData, typeof(XfwfMultiListReturnStruct)) :
                    new XfwfMultiListReturnStruct());
 
    string[] MultiListActionNames =
    {
        "NOTHING",
        "HIGHLIGHT",
        "UNHIGHLIGHT",
        "OPEN",
        "STATUS"
    };
 
    string recentEntry = (mlrs.text != IntPtr.Zero ? Marshal.PtrToStringAuto (mlrs.text) :
                    "NULL");
    string completeSelection = "";
 
    for (int index = 0; index < (int)mlrs.num_selected; index++)
    {
        if (completeSelection != "")
            completeSelection += "; ";
        completeSelection += Marshal.ReadInt32 (mlrs.selected_items,
                    index * sizeof (TInt)).ToString ();
    }
 
    Console.WriteLine ("MultiList action: {0}; {1} string(s) selected; " +
                       "Recent entry: {2}; Complete selection: {3}",
                       MultiListActionNames[(int)mlrs.action],
                       (int)mlrs.num_selected, recentEntry, completeSelection);
}

XfwfFrame

The XfwfFrame widget is a composite widget that accepts just one child. Its only purpose is to draw a frame around widgets that do not have a frame of their own. It always uses the size of its child, with a
little extra for the frame. There are several types of frames available, selectable with a resource.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame

New Resources

Name ClassTypeDefault 
XfwfNcursor XtCCursor Corsor None
XfwfNframeType XtCFrameType FrameType XfwfRaised
XfwfNframeWidth XtCFrameWidth Dimension 0
XfwfNouterOffset XtCOuterOffset Dimension 0
XfwfNinnerOffset XtCInnerOffset Dimension 0
XfwfNshadowScheme XtCShadowScheme ShadowScheme XfwfAuto
XfwfNtopShadowColor XtCTopShadowColor Color compute_topcolor 
XfwfNbottomShadowColor XtCBottomShadowColor Color compute_bottomcolor
XfwfNtopShadowStipple XtCTopShadowStipple Bitmap NULL  
XfwfNbottomShadowStipple XtCBottomShadowStipple Bitmap NULL

Usage

Typically the XfwfFrame widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfFrame widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.
IntPtr cursor   = X11lib.XCreateFontCursor (Xtlib.XtDisplay (_shell),
                                            X11lib.CursorFontShape.XC_pencil);
Arg[] frameArgs = { new Arg(XtNames.XtNborderColor,     (XtArgVal)_darkborderPixel),
                    new Arg(XtNames.XtNforeground,      (XtArgVal)_lightborderPixel),
                    new Arg(XfwfNames.XfwfNcursor,      (XtArgVal)cursor),
                    new Arg(XfwfNames.XfwfNframeWidth,  (XtArgVal)6),
                    new Arg(XfwfNames.XfwfNframeType,   (XtArgVal)XfwfFrameType.XfwfRaised),
                    new Arg(XfwfNames.XfwfNinnerOffset, (XtArgVal)4),
                    new Arg(XfwfNames.XfwfNouterOffset, (XtArgVal)2)  };
IntPtr frame    =  Xtlib.XtCreateManagedWidget("FrameT1",
                    Xfwflib.Xt_XfwfFrameWidgetClass(), frameBox,
                    frameArgs, (XCardinal)7);

XfwfTextOut

The XfwfTextOut widget is a multi-color, multi-font text display widget. Chunks of text can be added in upto 8 colors and 4 fonts, each selecatble by resources.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfTextOut

New Resources

Name ClassTypeDefault 
XfwfNinternalOffset XtCInternalOffset Dimension 2
XfwfNfont1 XtCFont1 FontStruct XtDefaultFont 
XfwfNfont2 XtCFont2 FontStruct XtDefaultFont 
XfwfNfont3 XtCFont3 FontStruct XtDefaultFont 
XfwfNfont4 XtCFont4 FontStruct XtDefaultFont 
XfwfNcolor1 XtCColor1 Pixel XtDefaultForeground  
XfwfNcolor2 XtCColor2 Pixel XtDefaultForeground  
XfwfNcolor3 XtCColor3 Pixel XtDefaultForeground  
XfwfNcolor4 XtCColor4 Pixel XtDefaultForeground  
XfwfNcolor5 XtCColor5 Pixel XtDefaultForeground  
XfwfNcolor6 XtCColor6 Pixel XtDefaultForeground  
XfwfNcolor7 XtCColor7 Pixel XtDefaultForeground  
XfwfNcolor8 XtCColor8 Pixel XtDefaultForeground  

Usage

Typically the XfwfTextOut widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfTextOut widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.
fallbackResources.Add (AppShellName + "*" + TextOutName +
    ".font1:  -adobe-times-medium-r-normal--12-*-*-*-p-*-iso8859-1");
fallbackResources.Add (AppShellName + "*" + TextOutName +
    ".font2:  -adobe-times-medium-i-normal--12-*-*-*-p-*-iso8859-1");
fallbackResources.Add (AppShellName + "*" + TextOutName +
    ".font3:  -adobe-helvetica-medium-r-normal--12-*-*-*-p-*-iso8859-1");
fallbackResources.Add (AppShellName + "*" + TextOutName +
    ".font4:  -adobe-helvetica-bold-r-normal--12-*-*-*-p-*-iso8859-1");
fallbackResources.Add (AppShellName + "*" + TextOutName + ".color1: black");
fallbackResources.Add (AppShellName + "*" + TextOutName + ".color2: red");
fallbackResources.Add (AppShellName + "*" + TextOutName + ".color3: blue");
fallbackResources.Add (AppShellName + "*" + TextOutName + ".color4: darkgreen");
 
...
 
Arg[] textoutArgs = { new Arg(XtNames.XtNwidth,        (XtArgVal)120),
                      new Arg(XtNames.XtNheight,        (XtArgVal)60) };
IntPtr textOut    = Xtlib.XtCreateManagedWidget(TextOutName,
                      Xfwflib.Xt_XfwfTextOutWidgetClass(), textoutBox,
                      textoutArgs, (XCardinal)2);
Xfwflib.XfwfAddText(textOut, "fred ", 1, 1, 0);
Xfwflib.XfwfAddText(textOut, "fred ", 2, 2, 0);
Xfwflib.XfwfAddText(textOut, "fred ", 3, 3, 0);
Xfwflib.XfwfAddText(textOut, "fred", 4, 4, 1);
Xfwflib.XfwfAddText(textOut, "Second line.", 2, 0, 1);
Xfwflib.XfwfAddText(textOut, "Big long text to see if line sizing is OK.", 4, 4, 1);
Xfwflib.XfwfAddText(textOut, null, 0, 0, 0);

XfwfStack

The XfwfStack widget is an X toolkit (and Motif if compiled with MOTIF flag) compatible widget that is a subclass of constraint. The stack widget allows only one child to be managed at a time. These two XfwfButtons realize the switching between the XfwfStack child widgets.

Inheritance (↑)

Core --> Composite --> Constraint --> XfwfStack

New Resources

Name ClassTypeDefault 
XfwfNdata XfwfCData XtPointer NULL 
XfwfNmargin XfwfCMargin Dimension 2
XfwfNsameSize XfwfCSameSize BooleanFalse
XfwfNfill XfwfCFill Boolean False 
XfwfNstackWidget XfwfCStackWidget Widget NULL
XfwfNstackType XfwfCStackTyp XfwfStackTypeXfwfSTACK_END_TO_END 

Usage

Arg[] stackArgs   = { new Arg(XtNames.XtNfromVert,  menuBoard) };
IntPtr stack      = Xtlib.XtCreateManagedWidget("Stack",
                      Xfwflib.Xt_XfwfStackWidgetClass(), rootForm,
                      stackArgs, (XCardinal)1);
IntPtr stackPage2 = Xtlib.XtCreateManagedWidget("Page2ForStack",
                      Xtlib.XawFormWidgetClass(), stack,
                      Arg.Zero, (XCardinal)0);
IntPtr stackPage1 = Xtlib.XtCreateManagedWidget("Page1ForStack",
                      Xtlib.XawFormWidgetClass(), stack,
                      Arg.Zero, (XCardinal)0);
 
...
 
if (_currentStackPage == 0)
{
    _currentStackPage ++;
    Xfwflib.XfwfStackNextWidget (stack);
}
else
{
    _currentStackPage --;
    Xfwflib.XfwfStackPreviousWidget (stack);
}

XfwfBoard 

The XfwfBoard widget can be used as the parent for other widgets.
Children can be any size and anywhere.
The location resource also provides a more powerful way of specifying size and position than the geometry management based on Xt/Athena Core's x, y, width and height. 

Inheritance(↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard

New Resources

Name ClassTypeDefault 
XfwfNabs_x XtCAbs_x Position 0
XfwfNrel_x XtCRel_x float0.0
XfwfNabs_y XfwfNabs_y Position 0
XfwfNrel_y XtCRel_y float0.0
XfwfNabs_width XtCAbs_width Position 0
XfwfNrel_width XtCRel_width float 0.0 
XfwfNabs_height XtCAbs_heightPosition 0
XfwfNrel_heightXtCRel_heightfloat 0.0
XfwfNhunit XtCHunit float 0.0 
XfwfNvunit XtCVunit float 0.0 
XfwfNlocation XtCLocation String NULL 

Usage

Typically the XfwfBoard widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfBoard widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.
Arg[] boardArgs = { new Arg(XfwfNames.XfwfNframeWidth, (XtArgVal)2),
                    new Arg(XfwfNames.XfwfNframeType,  (XtArgVal)XfwfFrameType.XfwfRaised),
                    // Use location or width/height
                    // new Arg (XfwfNames.XfwfNlocation,
                    //          X11.X11Utils.StringToSByteArray ("0 0 406 300\0")) };
                    new Arg(XtNames.XtNwidth,          (XtArgVal)400),
                    new Arg(XtNames.XtNheight,         (XtArgVal)300) };
IntPtr board    = Xtlib.XtCreateManagedWidget("SliderViewport",
                    Xfwflib.Xt_XfwfBoardWidgetClass(), slider4Box,
                    boardArgs, (XCardinal)4);

XfwfTextMenu

The XfwfTextMenu widget implements a simple menu, consisting of a series of labels. It is called XfwfTextMenu because it has no support for anything other than simple strings to be displayed. 

When a menu item is selected, the XfwfNactivate callback function is called with the number of the item and the label as call_data argument (numbering starts at 0).
 
When the user moves from one menu item to another, the XfwfNchangeSelection callback is called. This callback is called even for inactive (grayed out) items. It can be used, for example, to display an explanation of the selected item while the mouse is on it.

Inheritance (↑)

Core --> Composite --> Shell --> OverrideShell --> XfwfTextMenu

New Resources

Name ClassTypeDefault 
XtNfont XtCFont FontStruct XtDefaultFont 
XtNforeground XtCForeground Pixel XtDefaultForeground 
XfwfNtabList XtCTablist String NULL 
XfwfNmenu XtCMenu String "empty" 
XfwfNactive XtCActive long 0xFFFFFFFF 
XfwfNselection XfwfNselection int-1
XfwfNcursor XtCCursor Cursor arrow 
XfwfNactivate XtCActivate Callback NULL
XfwfNchangeSelection XtCChangeSelection Callback NULL  

Usage

Arg[] textMenuArgs = { new Arg(XfwfNames.XfwfNmenu,
                           X11.X11Utils.StringToSByteArray ("A _Zeroth item\nA Firs_t item\n" +
                           "A _Second item\nA _Third item\n-----------\nA _Close\0")) };
IntPtr textMenu    = Xtlib.XtCreatePopupShell (TextMenuName,
                       Xfwflib.Xt_XfwfTextMenuWidgetClass(), _shell,
                       textMenuArgs, (XCardinal)1);

XfwfAnimator

The XfwfAnimator widget cycles through a set of images at a fixed rate. The images are usually read from XPM files.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfAnimator

New Resources

Name ClassTypeDefault 
XtNimages XtCImages ImageList NULL  

XtNintervals

XtCIntervals CardinalList NULL  
XtNdefaultInterval  XtCDefaultInterval Cardinal 500  
XtNcycle XtCCycle Boolean True 

Usage

The easiest way to assign the animated images is to use the application's fallback resources. Currently there is no way to create images dynamically. See the Alert widget for a prototyp to create images dynamically.

The images must be accessible for the compiled application. Typically the XfwfAnimator widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfAnimator widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.

fallbackResources.Add (AppShellName + "*" + Animator1Name +
                       ".images: Anim00.xpm Anim05.xpm Anim10.xpm Anim15.xpm Anim20.xpm " +
                       "Anim25.xpm Anim30.xpm Anim35.xpm Anim40.xpm Anim45.xpm Anim50.xpm " +
                       "Anim55.xpm Anim60.xpm Anim65.xpm Anim70.xpm Anim75.xpm");

...

IntPtr amination1 = Xtlib.XtCreateManagedWidget(Animator1Name,
                     Xfwflib.Xt_XfwfAnimatorWidgetClass(), animatorBox,
                     Arg.Zero, (XCardinal)0);

XfwfArrow

The XfwfArrow widget displays a triangle, pointing in one of four directions. It is usually part of a XfwfScrollbar. It calls a callback repeatedly while a mouse is kept pressed.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfArrow

New Resources

Name ClassTypeDefault 
XfwfNdirection XtCDirection Alignment XfwfTop  
XtNforeground XtCForeground Color XtDefaultBackground  
XfwfNarrowShadow XtCArrowShadow Dimension 2
XfwfNinitialDelay XtCInitialDelay Cardinal 500
XfewfNrepeatDelay XtCRepeatDelay Cardinal 50
XtNcallback XtCCallback Callback NULL  

Usage

Typically the XfwfArrow widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfArrow widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.
Arg[] arrowArgs = { new Arg (XtNames.XtNborderColor,   (XtArgVal)_darkborderPixel),
                    new Arg (XtNames.XtNwidth,         (XtArgVal)20),
                    new Arg (XtNames.XtNheight,        (XtArgVal)20),
                    new Arg (XfwfNames.XfwfNdirection, (XtArgVal)XfwfAlignment.XfwfLeft) };
IntPtr arrow    = Xtlib.XtCreateManagedWidget("Arrow1",
                    Xfwflib.Xt_XfwfArrowWidgetClass(), arrowBox,
                    arrowArgs, (XCardinal)4);

Callback usage

Connect the callback via XtNames.XtNcallback.

XfwfEnforcer

The XfwfEnforcer widget can be used to apply location resources to a widget that is not a subclass of XfwfBoard.

 The Widget accepts a single child and forces that child to the same size as itself (minus the frame).  

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfEnforcer

New Resources

None.

Usage

Typically the XfwfEnforcer widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfEnforcer widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.
// Enforcer.
Arg[] enforcerArgs = { new Arg(XfwfNames.XfwfNframeWidth,  (XtArgVal)2),
                       new Arg(XfwfNames.XfwfNframeType,   (XtArgVal)XfwfFrameType.XfwfRaised),
                       new Arg(XfwfNames.XfwfNinnerOffset, (XtArgVal)4),
                       new Arg(XtNames.XtNwidth,           (XtArgVal)400),
                       new Arg(XtNames.XtNheight,          (XtArgVal)40) };
IntPtr enforcer    = Xtlib.XtCreateManagedWidget("Enforcer",
                            Xfwflib.Xt_XfwfEnforcerWidgetClass(), enforcerBox,
                            enforcerArgs, (XCardinal)5);
// Enforced//Label
Arg[] enforcedArgs = { new Arg(XtNames.XtNlabel,           X11.X11Utils.StringToSByteArray
                                                               ("Enforced label.\0")),
                       new Arg(XtNames.XtNbackground,      (XtArgVal)_backgroundPixel),
                       new Arg(XtNames.XtNborderWidth,     (XtArgVal)0) };
                     Xtlib.XtCreateManagedWidget("EnforcedLabel",
                       Xtlib.XawCommandWidgetClass(), enforcerBoard,
                       enforcedArgs, (XCardinal)3);

XfwfIcon

The XfwfIcon widget is used to display an icon, which is normally read from an XPM file. There are also a few built-in icons. The widget uses the shape extension to create icons that are non-rectangular or
transparent.  

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfIcon

New Resources

Name ClassTypeDefault 
XfwfNimage XtCImage Icon NULL
XfwfNactivate XtCActivate Callback NULL  

Usage

The easiest way to assign the icon image is to use the application's fallback resources. Currently there is no way to create images dynamically. See the Alert widget for a prototyp to create images dynamically.

The images must be accessible for the compiled application. Typically the XfwfIcon widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfIcon widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.
fallbackResources.Add (AppShellName + "*" + Icon1Name + "*image: FATAL");

...

Xtlib.XtCreateManagedWidget(Icon1Name, Xfwflib.Xt_XfwfIconWidgetClass(),
                            iconBox, Arg.Zero, (XCardinal)0); 

Callback usage

Connect the callback via XfwfNames.XfwfNactivate.

XfwfLabel

The XfwfLabel widget displays a text of one or more lines, optionally tabed and aligned with one of the sides. In addition it is possible to reverse (the text and background color on) one portion of the text using the XfwfNrvStart and XfwfNrvLength resources and to highlight one portion of the text using the XfwfNhlStart and XfwfNhlLength resources.  

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel

New Resources

Name ClassTypeDefault 
XtNlabel XtCLabel String NULL 
XfwfNtabList XtCTablist String NULL 
XtNfont XtCFont FontStruct XtDefaultFont 
XtNforeground XtCForeground Color XtDefaultForeground  
XfwfNhlForeground XtCHlForeground Color XtDefaultForeground  
XfwfNalignment XtCAlignment Alignment 0
XfwfNtopMargin XtCTopMargin Dimension 2
XfwfNbottomMargin XtCBottomMargin Dimension 2
XfwfNleftMargin XtCLeftMargin Dimension 2
XfwfNrightMargin XtCRightMargin Dimension 2
XfwfNshrinkToFit XtCShrinkToFit Boolean False
XfwfNrvStart XtCRvStart int0
XfwfNrvLength XtCRvLength int
XfwfNhlStart XtCHlStart int
XfwfNhlLength XtCHlLength int

Usage 

The XfwfLabel widget provides a lot of resources to define the appearance. Typically the XfwfLabel widget has a border of 2 pixels width, drawn with the label's background color. To embed a XfwfLabel widget seamlessly into it's surroundings, the XfwfCommon's XfwfNhighlightThickness resource has to be set to 0.
IntPtr cursor = X11lib.XCreateFontCursor (Xtlib.XtDisplay (_shell),
                                          X11lib.CursorFontShape.XC_question_arrow);
Arg[] lblArgs = { new Arg(XtNames.XtNlabel,
                          X11.X11Utils.StringToSByteArray ("Label test\0")),
                  new Arg(XfwfNames.XfwfNtabList,
                          X11.X11Utils.StringToSByteArray ("20 60\0")),
                  new Arg(XtNames.XtNwidth,           (XtArgVal)120),
                  new Arg(XtNames.XtNheight,          (XtArgVal)50),
                  new Arg(XfwfNames.XfwfNcursor,      (XtArgVal)cursor),
                  new Arg(XfwfNames.XfwfNhlStart,     (XtArgVal)0),
                  new Arg(XfwfNames.XfwfNhlLength,    (XtArgVal)3),
                  new Arg(XfwfNames.XfwfNrvStart,     (XtArgVal)5),
                  new Arg(XfwfNames.XfwfNrvLength,    (XtArgVal)3),
                  new Arg(XfwfNames.XfwfNframeWidth,  (XtArgVal)6),
                  new Arg(XfwfNames.XfwfNframeType,   (XtArgVal)XfwfFrameType.XfwfSunken),
                  new Arg(XfwfNames.XfwfNinnerOffset, (XtArgVal)0),
                  new Arg(XfwfNames.XfwfNouterOffset, (XtArgVal)(-2)) };        
                Xtlib.XtCreateManagedWidget("Label",
                  Xfwflib.Xt_XfwfLabelWidgetClass(), labelBox,
                  labelT2Args, (XCardinal)13);

XfwfRowCol

The XfwfRowCol widget forces all its children into rows and columns. The children keep their preferred size, but the preferred position is ignored. Resources determine how many rows or columns there should be (or as many as will fit) and if the children should be layed out in rows or in columns. In both methods, the children are placed on a grid, the size of which is determined by the width (height) of the widest (tallest) child.
The children can be aligned in several ways: they can be placed in the center of their grid cell or against the edges. This is controlled by a resource alignment.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfRowCol

New Resources

Name ClassTypeDefault 
XfwfNstoreByRow XtCStoreByRow Boolean True 
XfwfNrows XtCRows int0
XfwfNcolumns XtCColumn int0
XfwfNalignment XtCAlignment Alignment XfwfTopLeft 
XfwfNshrinkToFit XtCShrinkToFit Boolean False 

Usage

Arg[] rowcolArgs = { new Arg (XtNames.XtNlabel,      X11.X11Utils.StringToSByteArray ("Rowlol\0")),
                     new Arg (XtNames.XtNwidth,      (XtArgVal)250),
                     new Arg (XtNames.XtNheight,     (XtArgVal)250),
                     new Arg (XfwfNames.XfwfNalignment,   (XtArgVal)XfwfAlignment.XfwfBottomRight),
                     new Arg (XfwfNames.XfwfNstoreByRow,  (XtArgVal)1),
                     new Arg (XfwfNames.XfwfNcolumns,     (XtArgVal)4),
                     new Arg (XfwfNames.XfwfNframeWidth,  (XtArgVal)2),
                     new Arg (XfwfNames.XfwfNframeType,   (XtArgVal)XfwfFrameType.XfwfRaised),
                     new Arg (XfwfNames.XfwfNinnerOffset, (XtArgVal)2),
                     new Arg (XfwfNames.XfwfNouterOffset, (XtArgVal)(-2)) };                
IntPtr rowcol   = Xtlib.XtCreateManagedWidget(RowcolOrientationName,
                     Xfwflib.Xt_XfwfRowColWidgetClass(), rowcolBox,
                     rowcolT1Args, (XCardinal)10); 
To toggle the orientation of the children's arrangement, change the resources XfwfNcolumns and XfwfNstoreByRows.
new Arg(XfwfNames.XfwfNcolumns,     (XtArgVal)((_rowcolOrientationIsRow) != true ? 2 : 4))
new Arg (XfwfNames.XfwfNstoreByRow, (XtArgVal)((_rowcolOrientationIsRow) != true ? 0 : 1))

XfwfRows 

The XfwfRows widget forces all its children into tightly packed rows, where they can be aligned top or bottom. The children keep their preferred size, but the preferred position is ignored.

Inheritance (↑) 

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfRows

New Resources

Name ClassTypeDefault 
XfwfNalignTop XtCAlignTop Boolean True 

Usage

Arg[] rowsArgs  = { new Arg(XtNames.XtNwidth,        (XtArgVal)260),
                    new Arg(XtNames.XtNheight,       (XtArgVal)55),
                    new Arg(XfwfNames.XfwfNalignTop, (XtArgVal)1) };
IntPtr rows     = Xtlib.XtCreateManagedWidget(TestRowsName,
                    Xfwflib.Xt_XfwfRowsWidgetClass(), rowBox,
                    rowsArgs, (XCardinal)3);

XfwfScrollbar

The XfwfScrollbar widget has four parts: a trough in which a XfwfSlider2 moves up and down (or left and right) and two XfwfArrow widgets. Clicking and dragging on the different parts causes a callback to be invoked with different arguments, which presumably causes another widget to scroll. The scrollbar has the same callback list as the XfwfSlider2.

Clicking an arrow moves the data in that direction. Pressing the mouse button on an arrow and holding it, moves the data by small increments as long as the mouse button is down. Dragging the slider moves the data proportionally with the slider, either along with the movement of the mouse, or all at once when the mouse button is released. Pressing the mouse button on the rectangle outside the slider moves the data in larger increments.

 The XfwfScrollbar serves as superclass for XfwfHScrollbar and XfwfVScrollbar

Inheritance (↑) 

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfScrollbar

Code canges

The Scroll() method was rewritten and supports keyboard srolling regardles the XfwfNvertical resource is True or False now. The XfwfGetScrollbarSlider() method has been added to support the XfwfSlider2 methods like XfwfMoveThumb() or XfwfResizeThumb().

New Resources

Name ClassTypeDefault 
XfwfNvertical XtCVertical Boolean True 
XfwfNscrollCallback XtCScrollCallback Callback NULL 
XfwftNscrollResponse XtCScrollResponse XtCallbackProc scroll_response 
XfwfNinitialDelay XtCInitialDelay Cardinal 500
XfwfNrepeatDelay XtCRepeatDelay Cardinal 50
XfwfNincrement XtCIncrement float0.05
XfwfNscrollbarForeground XtCScrollbarForeground Color copy_background 
XfwfNshadow XtCShadow Dimension 2
XfwfNminSize XtCMinSize Dimension 20

Usage

Instanciate XfwfHScrollbar or XfwfVScrollbar instead.

XfwfScrolledWindow

The XfwfScrolledWindow widget is a composite widget composed of two XfwfScrollbars and a XfwfBoard within a XfwfFrame, and presumably a grandgrandchild which is a child of the XfwfBoard. The grandgrandchild is called the controlled widget (CW). Usually, the controlled widget is larger than the XfwfBoard, and its origin will have negative x and y coordinates. 

The controlled widget is moved about inside the XfwfBoard by the XfwfScrolledWindow, in reaction to the user clicking on the scrollbars. It is therefore clipped by the XfwfBoard

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfScrolledWindow

New Resources

Name ClassTypeDefault 
XfwfNspacing XtCSpacing Dimension 4
XfwfNscrollbarWidth XtCScrollbarWidth Dimension 22
XfwfNshadowWidth XtCShadowWidth Dimension 2
XfwfNhideHScrollbar XtCHideHScrollbar Boolean False  
XfwfNhideVScrollbar XtCHideVScrollbar Boolean False
XfwfNhScrollAmount XtCHScrollAmount int 20
XfwfNvScrollAmount XtCVScrollAmount intcopy_vScrollAmount 
XfwfNinitialX XtCInitialX Position 0
XfwfNinitialY XtCInitialY Position 0
XfwfNscrollCallback XtSCcrollCallback Callback NULL  
XfwfNscrollResponse XtCScrollResponse XtCallbackProc NULL  

Usage

Arg[] scollWinArgs = { new Arg    (XfwfNames.XfwfNlocation,
                           X11.X11Utils.StringToSByteArray ("0 20 1.0 1.0-20\0")),
                       new Arg    (XtNames.XtNbackground,   (XtArgVal)_backgroundPixel) };
IntPtr scrollWin   = Xtlib.XtCreateManagedWidget("ScrollWin",
                       Xfwflib.Xt_XfwfScrolledWindowWidgetClass(), scrollWinBox,
                       scollWinArgs, (XCardinal)2);

Callback usage

Connect the callback via XfwfNames.XfwfNscrollCallback.
/// <summary> The callback for step button activate event. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void ScrolledWindowScrollCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    XfwfScrollInfo scrollInfo = (callData != IntPtr.Zero ? (XfwfScrollInfo)
                                Marshal.PtrToStructure (callData, typeof(XfwfScrollInfo)) :
                                new XfwfScrollInfo());
 
    if (callData != IntPtr.Zero)
    {
        if (scrollInfo.flags == (XfwfSFlags.XFWF_HPOS | XfwfSFlags.XFWF_VPOS))
        {    
            ; // Evaluate
        }
    }
}

XfwfScrolledWindow3

The XfwfScrolledWindow3 widget is a composite widget that contains 4 XfwfBoards and two XfwfScrollbars. The first board is a small area in the top left corner, where a label widget can be put. One board along the top and one along the left side are used for column and row titles (usually XfwfLabel widgets). The two scroll bars are along the right side and the bottom. In the middle is the largest board, in which the main data will be displayed.

The widget that is added as the child of the large XfwfBoard is called the controlled widget (CW), the widget that is put in the top board is called the column controlled widget (CCW), the widget that is put in the left board is the row controlled widget (RCW).

Usually, the controlled widgets are larger than the boards, and their origins will have negative x and y coordinates. They are moved about inside the XfwfBoards by the XfwfScrolledWindow3, in reaction to the user clicking on the scroll bars. The CCW moves left/right, the RCW moves up/down, the CW moves in all directions. The controlled widgets are therefore clipped by the boards.
 
The first child widget attached to XfwfScrolledWindow3 becomes the child of the top left board. The second child widget becomes the CCW, the third the RCW, and the fourth the CW.
 
The CCW is typically a XfwfLabel widget with a tablist to provide column headers, and only scrolls horizontally. The CW is typically a single column XfwfMultiList widget with a tablist, and scrolls boths
horizontally and vertically.
 
The XfwfScrolledWindow3 provides a callback, but most application will not need it, since it already moves the CW. The callback is invoked after the CW is moved.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfScrolledWindow3

New Resources

Name ClassTypeDefault 
XfwfNspacing XtCSpacing Dimension 4
XfwfNscrollbarWidth XtCScrollbarWidth Dimension 22
XfwfNcolHdrHeight XtNcolHdrHeight Dimension 22
XfwfNrowHdrWidthXtNrowHdrWidth Dimension 22
XfwfNshadowWidth XtCShadowWidth Dimension 2
XfwfNhideHScrollbar XtCHideHScrollbar Boolean False  
XfwfNhideVScrollbar XtCHideVScrollbar Boolean False
XfwfNhScrollAmount XtCHScrollAmount int 20
XfwfNvScrollAmount XtCVScrollAmount intcopy_vScrollAmount 
XfwfNinitialX XtCInitialX Position 0
XfwfNinitialY XtCInitialY Position 0
XfwfNscrollCallback XtSCcrollCallback Callback NULL  
XfwfNscrollResponse XtCScrollResponse XtCallbackProc NULL  

Usage

// ScrollWin3.
Arg[] scollWin3Args     = { new Arg (XfwfNames.XfwfNlocation,
                                     new XtString ("0 20 1.0 1.0-20\0")),
                            new Arg (XtNames.XtNbackground,
                                     (XtArgVal)_backgroundPixel),
                            new Arg (XfwfNames.XfwfNcolHdrHeight,   (XtArgVal)22),
                            new Arg (XfwfNames.XfwfNrowHdrWidth,    (XtArgVal)50) };
IntPtr scrollWin3        = Xtlib.XtCreateManagedWidget("ScrollWin3",
                            Xfwflib.Xt_XfwfScrolledWindow3WidgetClass(), scrollWin3Box,
                            scollWin3Args, (XCardinal)4);
// Corner label.
Arg[] conerLabelArgs    = { new Arg (XtNames.XtNlabel,              new XtString ("login")),
                            new Arg (XtNames.XtNbackground,
                                     (XtArgVal)_backgroundPixel),
                            new Arg (XfwfNames.XfwfNalignment,
                                     (XtArgVal)XfwfAlignment.XfwfTopLeft),
                            new Arg (XtNames.XtNx,                  (XtArgVal)0),
                            new Arg (XtNames.XtNy,                  (XtArgVal)0) };
                          Xtlib.XtCreateManagedWidget("ScrollWin3_Corner",
                            Xfwflib.Xt_XfwfLabelWidgetClass(), scrollWin3,
                            conerLabelArgs, (XCardinal)5);
// ColumnHeader label.
Arg[] colhdrLabelArgs   = { new Arg (XtNames.XtNlabel,
                                     new XtString ("uid\tgid\tname\tshell\0")),
                            new Arg (XtNames.XtNbackground,
                                     (XtArgVal)_backgroundPixel),
                            new Arg (XfwfNames.XfwfNalignment,
                                     (XtArgVal)XfwfAlignment.XfwfTopLeft),
                            new Arg (XfwfNames.XfwfNtabList,
                                     new XtString ("50 100 280")) };
                          Xtlib.XtCreateManagedWidget("ScrollWin3_ColumnHeader",
                            Xfwflib.Xt_XfwfLabelWidgetClass(), scrollWin3,
                            colhdrLabelArgs, (XCardinal)4);
// Array preparation.
XtStringArray  rowHrd    = new XtStringArray("root|rick|bert|brian|fwf|gene|steve|" +
                                             "gone|erik|joe|herman", '|');                
XtStringArray contentTxt= new XtStringArray("  0\t0\tSystem Administrator\t/bin/sh|" +
                                            "400\t1\tRick Richardson\t/bin/ksh|" +
                                            "367\t4\tBert Bos\t/bin/ksh|" +
                                            "368\t5\tBrian Totty\t/bin/ksh|" +
                                            "369\t6\tFree Widget Foundation\t/bin/ksh|" +
                                            "364\t2\tGene Olson\t/bin/bash|" +
                                            "365\t3\tSteve Wahl\t/bin/ksh|" +
                                            "370\t7\tDeleted User\t/bin/csh|" +
                                            "371\t7\tDeleted User\t/bin/sh|" +
                                            "372\t7\tDeleted User\t/bin/rsh|" +
                                            "373\t7\tHerman Hermans\t/bin/ksh", '|');
XtByteArray    rowSens    = new XtByteArray("1 1 1 1 1 1 1 0 0 0 1");
// RowHeader label.
Arg[] rowhdrLabelArgs   = { new Arg (XfwfNames.XfwfNlist,           rowHrd.Data),
                            // Omit this to show all list entries sensitive.
                            new Arg (XfwfNames.XfwfNsensitiveArray, rowSens.Data),
                             // The number of visible list entries, 0 for all.
                            new Arg (XfwfNames.XfwfNnumberStrings,  (XtArgVal)0),
                            new Arg (XfwfNames.XfwfNdefaultColumns, (XtArgVal)1),
                            new Arg (XtNames.XtNborderWidth,        (XtArgVal)0),
                            new Arg (XtNames.XtNx,                  (XtArgVal)0),
                            new Arg (XtNames.XtNy,                  (XtArgVal)0) };
                          Xtlib.XtCreateManagedWidget("ScrollWin3_RowHeader",
                            Xfwflib.Xt_XfwfMultiListWidgetClass(), scrollWin3,
                            rowhdrLabelArgs, (XCardinal)7);
// Content label.
Arg[] contentLabelArgs  = { new Arg (XfwfNames.XfwfNlist,           contentTxt.Data),
                            // Omit this to show all list entries sensitive.
                            new Arg (XfwfNames.XfwfNsensitiveArray, rowSens.Data),
                            // The number of visible list entries, 0 for all.
                            new Arg (XfwfNames.XfwfNnumberStrings,  (XtArgVal)0),
                            new Arg (XfwfNames.XfwfNtabList,
                                     new XtString ("50 100 280")),
                            new Arg (XfwfNames.XfwfNdefaultColumns, (XtArgVal)1),
                            new Arg (XtNames.XtNborderWidth,        (XtArgVal)0),
                            new Arg (XtNames.XtNx,                  (XtArgVal)1),
                            new Arg (XtNames.XtNy,                  (XtArgVal)1) };
                          Xtlib.XtCreateManagedWidget("ScrollWin3_Content",
                            Xfwflib.Xt_XfwfMultiListWidgetClass(), scrollWin3,
                            contentLabelArgs, (XCardinal)8);
// Array disposal.
rowSens.Dispose();
contentTxt.Dispose();
rowHrd.Dispose(); 

Callback usage

Connect the callback via XfwfNames.XfwfNscrollCallback.

XfwfTabs

The XfwfTabs widget displays a series of tabs, similar to the alphabet tabs along the top of index cards. One tab, the front one, is completely visible, the others are partially hidden behind it. Each of the tabs can be clicked on with the mouse. This implementation does not take part in keyboard traversal, and it has no 3D frame.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfTabs

New Resources

Name ClassTypeDefault 
XtNforeground XtCForeground Pixel XtDefaultForeground 
XtNorientation XtCOrientationTabs Orientation XfwfUpTabs 
XfwfNlefttabs XtCLefttabs int0
XfwfNrighttabs XtCRighttabs int0
XfwfNlabels XtCLabels StringArray NULL
XfwfNcornerHeight XtCCornerHeight int3
XfwfNcornerWidth XtCCornerWidth int3
XfwfNtextMargin XtCTextmargin int3
XfwfNtabColor XtCTabcolor Pixel copy_bg 
XtNfont XtCFont FontStruct XtDefaultFont  
XfwfNactivate XtCActivate Callback NULL 

Usage

string[] tabs = { "Introduction", "Top" };
Arg[] tabArgs = { new Arg (XtNames.XtNborderColor,             (XtArgVal)_darkborderPixel),
                  new Arg (XfwfNames.XfwfNlocation,
                      X11.X11Utils.StringToSByteArray ("35 25 1.0-70 30\0")),
                  new Arg (XfwfNames.XfwfNorientation,
                     (XtArgVal)XfwfTabsOrientation.XfwfUpTabs),
                  new Arg (XfwfNames.XfwfNlabels,              tabs),
                  new Arg (XfwfNames.XfwfNtextMargin,          (XtArgVal)4),
                  new Arg (XfwfNames.XfwfNtabColor,            (XtArgVal)_lightborderPixel),
                  new Arg (XtNames.XtNforeground,              (XtArgVal)_darkborderPixel),
                  //new Arg (XfwfNames.XfwfNtabWidthPercentage, (XtArgVal)40),
                  new Arg (XfwfNames.XfwfNframeWidth,          (XtArgVal)1),
                  // Use default corner width.
                  //new Arg (XfwfNames.XfwfNcornerWidth,       (XtArgVal)4),
                  // Use default corner height.
                  //new Arg (XfwfNames.XfwfNcornerHeight,      (XtArgVal)4),
                  // Visible tabs left from currently activated tab.
                  new Arg (XfwfNames.XfwfNlefttabs,            (XtArgVal)0),
                  // Visible tabs right from currently activated tab.
                  new Arg (XfwfNames.XfwfNrighttabs,           (XtArgVal)1) };
IntPtr tab    = Xtlib.XtCreateManagedWidget(Tab1Name,
                  Xfwflib.Xt_XfwfTabsWidgetClass(), tabBox,
                  tab1Args, (XCardinal)10);

Callback usage

Connect the callback via XfwfNames.XfwfNactivate.
/// <summary> The callback for any crollbar scroll event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void TabActivateCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    string sWidgetName = Xtlib.XtNameAsString (widget);
    int relativeTabIndex = (int)callData;
 
    Console.WriteLine ("Tab index of {0} is {1}", sWidgetName, relativeTabIndex);
 
    if (relativeTabIndex < 0)
    {
        Arg[] tabArgs = {   // Visible tabs left from currently activated tab.
                            new Arg (XfwfNames.XfwfNlefttabs,        (XtArgVal)0),
                            // Visible tabs right from currently activated tab.
                            new Arg (XfwfNames.XfwfNrighttabs,        (XtArgVal)1) };
        Xtlib.XtSetValues (widget, tabArgs, (XCardinal)2);
    }
    else if (relativeTabIndex > 0)
    {
        Arg[] tabArgs = {   // Visible tabs left from currently activated tab.
                            new Arg (XfwfNames.XfwfNlefttabs,        (XtArgVal)1),
                            // Visible tabs right from currently activated tab.
                            new Arg (XfwfNames.XfwfNrighttabs,        (XtArgVal)0) };
        Xtlib.XtSetValues (widget, tabArgs, (XCardinal)2);
    }
}

XfwfButton

The XfwfButton widget is simply an XfwfLabel with a callback for mouse clicks.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel --> XfwfButton

New Resources

Name ClassTypeDefault 
XfwfNactivate XtCActivate Callback NULL  
XfwfNenter XtCEnter Callback NULL  
XfwfNleave XtCLeave Callback NULL  

Callback usage

Connect callbacks via XfwfNames.XfwfNactivate, XfwfNames.XfwfNenter or XfwfNames.XfwfNleave.
/// <summary> The callback for any button press event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void ButtonPressCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    string sWidgetName = Xtlib.XtNameAsString (widget);
    Console.WriteLine ("Button pressed {0}", sWidgetName);
}

XfwfSlider2

The XfwfSlider2 widget displays a thumb (with two degrees of freedom: horizontal and vertical position), that can be moved with the mouse.

Applications can use this to move or scroll other objects via callbacks.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel --> XfwfSlider2

New Resources

Name ClassTypeDefault 
XfwfNthumbColor XtCThumbColor Color XtDefaultBackground 
XfwfNthumbPixmap XtCThumbPixmap Pixmap NULL 
XfwfNminSize XtCMinsize Dimension 20
XfwfNthumbFrameWidth XtCThumbFrameWidth Dimension 2
XfwfNthumbFrameType XtCThumbFrameType FrameType XfwfRaised 
XfwfNscrollCallback XtCScrollCallback Callback NULL 
XfwfNscrollResponse XtCScrollResponse XtCallbackProc scroll_response

Usage 

Resize the thumb using XfwfResizeThumb() and connect the thumb with a widget to be moved using XfwfConnectScrollingWidgets().

Callback usage

Connect the callback via XfwfNames.XfwfNscrollCallback.
/// <summary> The callback for slider2 move event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void Slider2ThumbCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    if (callData != IntPtr.Zero)
    {
        XfwfScrollInfo scrollInfo = (XfwfScrollInfo)
            Marshal.PtrToStructure (callData, typeof(XfwfScrollInfo));
 
        // Don't update during move.
        // if (scrollInfo.reason != XfwfSReason.XfwfSDrag)
        {
            float x = 0.0F;
            float y = 0.0F;
 
            if (((int)(scrollInfo.flags) & (int)(XfwfSFlags.XFWF_HPOS))  != 0)
                x = scrollInfo.hpos;
            if (((int)(scrollInfo.flags) & (int)(XfwfSFlags.XFWF_VPOS))  != 0)
                y = scrollInfo.vpos;
 
            string position = string.Format ("x = {0}\ny = {1}\0", x, y);
            Arg[] newText = { new Arg (XtNames.XtNlabel,
                X11.X11Utils.StringToSByteArray (position)) };
            Xtlib.XtSetValues(_slider2LocationLabel, newText, (XCardinal)1);
        }
    }
}

XfwfSpinLabel

The XfwfSpinLabel widget provides nearly the same features as its superclass XfwfLabel but additionally it is possible to manipulate the labels using two arrow buttons. With these the user is able to increase/decrease a numerical value or scroll trough a list of strings.

Every time one of the arrows is pressed, the XfwfNactivate callback is invoked. The XfwfSpinLabel widget provides a keyboard interface too. Using a callback the programmer is free to decide trough what he let the user scroll. 

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel --> XfwfSpinLabel

New Resources

Name ClassTypeDefault 
XfwfNarrowForeground XtCArrowForeground Color copy_background 
XtNcallback XtCCallback Callback NULL  
XfwfNlabelFrameWidth XtCLabelframeWidth Dimension 0
XfwfNlabelFrameType XtCLabelframeType XfwfFrameType XfwfSunken 
XfwfNhorizontal XtCHorizontal Boolean True  

Usage 

/// <summary> The strings to be displayed in a spin label XfwfTabs. </summary>
private string[] _spin1Texts = { "0\0",
                                "1\0",
                                "2\0",
                                "3\0",
                                "4\0",
                                "5\0",
                                "6\0",
                                "7\0"};

...

Arg[] spinArgs = { new Arg (XtNames.XtNlabel,
                       X11.X11Utils.StringToSByteArray (_spinTexts[(int)_spinIndex])),
                   new Arg (XtNames.XtNwidth,              (XtArgVal)25),
                   new Arg (XtNames.XtNheight,             (XtArgVal)75),
                   new Arg (XfwfNames.XfwfNhorizontal,     (XtArgVal)0),
                   new Arg (XfwfNames.XfwfNarrowForeground,(XtArgVal)_lightborderPixel) };
IntPtr spin    = Xtlib.XtCreateManagedWidget("SpinTest",
                   Xfwflib.Xt_XfwfSpinLabelWidgetClass(), spinBox,
                   spinArgs, (XCardinal)5); 

Callback usage 

Connect the callback via XtNames.XtNcallback.
/// <summary> The callback for any spin label event within the canvas. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void SpinLabelCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    IntPtr spinWidget  = IntPtr.Zero;
    // The widget might be one of the arrows.
    if (Xtlib.XtIsSubclass (widget, Xfwflib.Xt_XfwfArrowWidgetClass()) != 0)
        spinWidget = Xtlib.XtParent (widget);
    else if (Xtlib.XtIsSubclass (widget, Xfwflib.Xt_XfwfSpinLabelWidgetClass()) != 0)
        spinWidget  = widget;
    else
        return;
 
    string sWidgetName = Xtlib.XtNameAsString (spinWidget);
    XfwfSpinType diff  = (XfwfSpinType) callData;
 
    if (diff == XfwfSpinType.XfwfFirst)
    {
        if (sWidgetName.EndsWith("1"))
        {
            _spinIndex = (TInt)0;
            Arg[] spinArgs = { new Arg(XtNames.XtNlabel,
                X11.X11Utils.StringToSByteArray (_spinTexts[(int)_spinIndex])) };
            Xtlib.XtSetValues (spinWidget, spinArgs, (XCardinal)1);
        }
        else if (sWidgetName.EndsWith("2"))
        {
            ...
        }
    }
    else if (diff == XfwfSpinType.XfwfLast)
    {
        if (sWidgetName.EndsWith("1"))
        {
            _spinIndex = (TInt)_spinTexts.Length - 1;
            Arg[] spinArgs = { new Arg(XtNames.XtNlabel,
                X11.X11Utils.StringToSByteArray (_spinTexts[(int)_spinIndex])) };
            Xtlib.XtSetValues (spinWidget, spinArgs, (XCardinal)1);
        }
        else if (sWidgetName.EndsWith("2"))
        {
            ...
        }
    }
    else if (diff == XfwfSpinType.XfwfNext)
    {
        if (sWidgetName.EndsWith("1"))
        {
            _spinIndex = (TInt)(_spinIndex + 1);
            _spinIndex = ((int)_spinIndex <= _spinTexts.Length - 1 ?
                _spinIndex : (TInt)(_spinTexts.Length - 1));
            Arg[] spinArgs = { new Arg(XtNames.XtNlabel,
                X11.X11Utils.StringToSByteArray (_spinTexts[(int)_spinIndex])) };
            Xtlib.XtSetValues (spinWidget, spinArgs, (XCardinal)1);
        }
        else if (sWidgetName.EndsWith("2"))
        {
            ...
        }
    }
    else if (diff == XfwfSpinType.XfwfPrev)
    {
        if (sWidgetName.EndsWith("1"))
        {
            _spinIndex = (TInt)(_spinIndex - 1);
            _spinIndex = ((int)_spinIndex >= 0 ? _spinIndex : (TInt)0);
            Arg[] spinArgs = { new Arg(XtNames.XtNlabel,
                X11.X11Utils.StringToSByteArray (_spinTexts[(int)_spinIndex])) };
            Xtlib.XtSetValues (spinWidget, spinArgs, (XCardinal)1);
        }
        else if (sWidgetName.EndsWith("2"))
        {
            ...
        }
    }
}

XfwfGroup

The XfwfGroup widget adds two things to the capabilities already present in XfwfRowCol, a label
in the upper left hand corner and the ability to make a number of XfwfToggle buttons act as radio buttons.

The label is a short, one line piece of text, that is displayed over the border in the top left corner. The border is interupted at that point. Since this works best with XfwfLedged or XfwfChiseled border types, the default border is XfwfChiseled.
 
The special support for radio buttons works as follows: When a child is added, the XfwfGroup widget checks if it is of class XfwfToggle or a subclass thereof. If so, the XfwfGroup widget installs a callback in it. When the XfwfToggle button is then activated, the XfwfGroup widget determines which other buttons need to be turned off. All XfwfToggle buttons are given an implicit number. The first one is number 0.
 
The selectionStyle resource supports the modes XfwfSingleSelection (none or one of the toggles is on), XfwfOneSelection (all times exactly one toggle is on) and XfwfMultipleSelection (any number of toggles is on).

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfRowCol --> XfwfGroup

New Resources

Name ClassTypeDefault 
XtNlabel XtCLabel String NULL  
XtNfont XtCFont FontStruct XtDefaultFont  
XtNforeground XtCForeground Color  XtDefaultForeground  
XfwfNselectionStyle XtCSelectionStyle SelectionType XfwfSingleSelection  
XfwfNselection XtCSelection long 0
XfwfNactivate XtCActivate Callback NULL 

Usage

Create a XfwfGroup widget and add children of class XfwfToggle or any subclass.
Arg[] groupArgs = { new Arg(XtNames.XtNlabel,
                        X11.X11Utils.StringToSByteArray ("XfwfGroup with toggles:\0")),
                    new Arg(XfwfNames.XfwfNlocation,
                        X11.X11Utils.StringToSByteArray ("5 5 140 50\0")),
                    new Arg(XfwfNames.XfwfNcolumns,     (XtArgVal)2),
                    new Arg(XfwfNames.XfwfNshrinkToFit, (XtArgVal)1),
                    new Arg(XfwfNames.XfwfNframeWidth,  (XtArgVal)2),
                    new Arg(XfwfNames.XfwfNframeType,   (XtArgVal)XfwfFrameType.XfwfRaised),
                    new Arg(XfwfNames.XfwfNinnerOffset, (XtArgVal)2),
                    /* Allocate enough space for group title.*/
                    new Arg(XfwfNames.XfwfNouterOffset, (XtArgVal)5) };
IntPtr group    = Xtlib.XtCreateManagedWidget(SimpleGroupName,
                    Xfwflib.Xt_XfwfGroupWidgetClass(), radiogrpBox,
                    groupArgs, (XCardinal)8); 

Callback usage

The XfwfGroup widget doesn't need a callback to be registered. Optionally the toggles can be connect to a callback via XfwfNames.XfwfNonCallback for immediate feedback.
 
The XfwfNselection resource holds at any time the state of the toggle buttons (if any). If XfwfNselectionType = XfwfSingleSelection or XfwfOneSelection, it holds the index of the button that is currently on, or -1 if they are all off. If XfwfNselectionType = XfwfMultipleSelection, it is a bitmap with one bit set for each button that is on.

XfwfMenuBar

The XfwfMenuBar widget displays buttons in a horizontal row. It assumes the buttons control drop-down menus and it makes it possible to drag the mouse from one menu to another.

The MenuBar attaches itself to the XtNpopdownCallback callback of the menu shell that is popped up by the children, and inserts itself in the list of pointer grabs that Xt maintains. This is necessary to be able to drag the mouse from one menu into another, popping down the first one and popping up the second. If you use a XfwfRowCol widget instead of a XfwfMenuBar, you will find that switching from one menu to the next involves releasing the mouse and then pressing it again.

To find the menu shell, the children are asked for their XtNpopup resource. XfwfPullDown buttons have this resource, others may not.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfRows --> XfwfMenuBar

New Resources 

None.

Usage

Just create XfwfPullDown widget(s) als child(ren).

XfwfHScrollbar

The XfwfHScrollbar widget is almost the same as the XfwfScrollbar widget, except that it has default translations for scroll up/down, page up/down and home/end and the default value of the XfwfNvertical resource is False.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfScrollbar --> XfwfHScrollbar

New Resources  

None.

Code canges

Correction of the default translation parameters (capitalization). Additional default translations, now these keyboard bindings are supported:
  • < Key>Left to scroll one step left
  • < Key>Right to scroll one step right
  • Ctrl<Key>Left and <Key>Prior to scroll one page left
  • Ctrl<Key>Right and <Key>Next to scroll one page right
  • < Key>Home, Shift<Key>End and Ctrl<Key>Prior to scroll to the start (left side)
  • Shift<Key>Home, <Key>End and Ctrl<Key>Next to scroll to the end (right side)

Usage

Arg[] scrollArgs = { new Arg (XtNames.XtNborderColor,            (XtArgVal)_darkborderPixel),
                     new Arg (XtNames.XtNwidth,                  (XtArgVal)98),
                     new Arg (XtNames.XtNheight,                 (XtArgVal)20),
                     new Arg (XfwfNames.XfwfNscrollbarForeground,(XtArgVal)_darkgreenPixel),
                     new Arg (XfwfNames.XfwfNincrement,          0.02F),
                     new Arg (XfwfNames.XfwfNvertical,           (XtArgVal)0) };
 IntPtr scrollBar = Xtlib.XtCreateManagedWidget("Scroll",
                     Xfwflib.Xt_XfwfHScrollbarWidgetClass(), scrollBox,
                     scrollArgs, (XCardinal)6);
 Xfwflib.XfwfSetScrollbar (scrollBar3, 0.4, 0.2); 

Callback usage

Connect the callback via XfwfNames.XfwfNscrollCallback.
/// <summary> The callback for any scrollbar scroll event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void ScrollbarScrollCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    XfwfScrollInfo scrollInfo = (callData != IntPtr.Zero ? (XfwfScrollInfo)
                                Marshal.PtrToStructure (callData, typeof(XfwfScrollInfo)) :
                                new XfwfScrollInfo());
 
    TInt val              = Xtlib.XtGetValueOfInt (widget, XtNames.XtNvalue);
 
    if (callData != IntPtr.Zero)
    {
        if (scrollInfo.flags == XfwfSFlags.XFWF_VPOS)
        {
            IntPtr slider = Xfwflib.XfwfGetScrollbarSlider (widget);
            Xfwflib.XfwfMoveThumb (slider, scrollInfo.hpos, scrollInfo.vpos);
            val = (TInt)(1000.0 * scrollInfo.vpos);
        }
        else if (scrollInfo.flags == XfwfSFlags.XFWF_HPOS)
        {
            IntPtr slider = Xfwflib.XfwfGetScrollbarSlider (widget);
            Xfwflib.XfwfMoveThumb (slider, scrollInfo.hpos, scrollInfo.vpos);
            val = (TInt)(1000.0 *scrollInfo.hpos);
        }
    }
    Console.WriteLine ("Scrollbar position {0}", val);
}

XfwfVScrollbar

The XfwfVScrollbar widget is almost the same as the XfwfScrollbar widget, except that it has default translations for scroll left/right, page left/right and home/end and the default value of the XfwfNvertical resource is True.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfScrollbar --> XfwfVScrollbar

New Resources

None.

Code canges

Correction of the default translation parameters (capitalization). Additional default translations, now these keyboard bindings are supported:
  • < Key>Up to scroll one step up
  • < Key>Down to scroll one step down
  • Ctrl<Key>Up and <Key>Prior to scroll one page up
  • Ctrl<Key>Down and <Key>Next to scroll one page down
  • < Key>Home, Shift<Key>End and Ctrl<Key>Prior to scroll to the start (top)
  • Shift<Key>Home, <Key>End and Ctrl<Key>Next to scroll to the end (bottom)

Usage

See XfwfHScrollbar.

Callback usage

See XfwfHScrollbar.

XfwfPullDown

The XfwfPullDown widget is a button with a pull-down menu. The menu can be specified in two ways: as a string or as a widget.

If a string is given, it must be in the correct syntax for the XfwfTextMenu widget and a widget will be created automatically. If a widget is given instead, it must be a widget that is able to pop up: in other words: a Shell widget or a subclass of Shell. There is also support for a hotkey, but it doesn't work yet.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel --> XfwfButton --> XfwfPullDown

New Resources

Name ClassTypeDefault 
XfwfNpopup XtCPopup Widget NULL  
XfwfNmenu XtCMenu String NULL  
XfwfNcascaded XtCCascaded Boolean False 
XfwfNhotkey XtCHotkey String NULL 
XfwfNmenuCursor XtCMenuCursor Cursor arrow 
XfwfNprepareXtCPrepare Callback NULL 
XfwfNchangeSelectionXtCChangeSelection Callback NULL 

Usage

Arg[] pdArgs = { new Arg (XtNames.XtNlabel,      X11.X11Utils.StringToSByteArray ("Menu 2\0")),
                 new Arg (XfwfNames.XfwfNhotkey, X11.X11Utils.StringToSByteArray ("Alt<Key>2\0")),
                 new Arg (XfwfNames.XfwfNmenu,   X11.X11Utils.StringToSByteArray ("_first item" +
                                                 "\ns_econd item\nth_ird item\nfou_rth item\0")) };
IntPtr pulld = Xtlib.XtCreateManagedWidget("PullDown2",
                 Xfwflib.Xt_XfwfPullDownWidgetClass(), menuRowCol,
                 pdArgs, (XCardinal)3);

Callback usage

Connect callbacks via XfwfNames.XfwfNactivate, XfwfNames.XfwfNprepare or XfwfNames.XfwfNchangeSelection.
/// <summary> The callback for any pulldown select event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void PullDownSelectCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    string sWidgetName = Xtlib.XtNameAsString (widget);
 
    XfwfTextMenuData textMenuData = (callData != IntPtr.Zero ? (XfwfTextMenuData)
                                     Marshal.PtrToStructure (callData, typeof(XfwfTextMenuData)) :
                                     new XfwfTextMenuData());
    if (callData != IntPtr.Zero && textMenuData.n >= 0)
    {
        string sMenuEntry  = Marshal.PtrToStringAuto (textMenuData.label);
 
        Console.WriteLine ("Pulldown {0} selected {1}", sWidgetName, sMenuEntry);
    }
    else
    {
        Console.WriteLine ("Pulldown {0} selected", sWidgetName);
    }
}

XfwfToggle

The XfwfToggle widget switches states with every activation (which is by default with every mouse click). The states are named on and off. The states can be indicated with an icon before label.

Two callbacks report the changed state to the application: XfwfNonCallback is called when the button switches to on, XfwfNoffCallback is called when the button switches back to off.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel --> XfwfButton --> XfwfToggle

New Resources

Name ClassTypeDefault 
XfwfNonCallback  XtCOnCallback Callback NULL  
XfwfNoffCallback XtCOffCallback Callback NULL  
XfwfNon XtCOn Boolean False
XfwfNonIcon XtCOnIcon Icon filledsquare  
XfwfNoffIcon XtCOffIcon Icon emptysquare  

Usage

Arg[] toggleArgs = { new Arg(XtNames.XtNlabel,      X11.X11Utils.StringToSByteArray ("Toggle\0")),
                     new Arg(XtNames.XtNwidth,      (XtArgVal)90),
                     new Arg(XtNames.XtNheight,     (XtArgVal)50),
                     new Arg(XtNames.XtNforeground, (XtArgVal)_lightborderPixel),
                     new Arg(XfwfNames.XfwfNframeWidth,  (XtArgVal)2),
                     new Arg(XfwfNames.XfwfNframeType,   (XtArgVal)XfwfFrameType.XfwfRaised),
                     new Arg(XfwfNames.XfwfNinnerOffset, (XtArgVal)2),
                     new Arg(XfwfNames.XfwfNouterOffset, (XtArgVal)(-2)) };                
IntPtr toggleBtn = Xtlib.XtCreateManagedWidget(Toggle1Name,
                     Xfwflib.Xt_XfwfToggleWidgetClass(), toggleBox,
                     toggleArgs, (XCardinal)8); 

Callback usage

Connect callbacks via XfwfNames.XfwfNonCallback and XfwfNames.XfwfNoffCallback

/// <summary> The callback for any toggle press event within the dialog. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void TogglePressCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    Arg[] toggleArgs = { new Arg (XtNames.XtNforeground,     (XtArgVal)
            (((int)clientData) == 0 ? _lightborderPixel : _blackPixel)),
                         new Arg (XfwfNames.XfwfNon,         (XtArgVal)clientData),
                         new Arg (XfwfNames.XfwfNframeType,  (XtArgVal)
            (((int)clientData) == 0 ? XfwfFrameType.XfwfRaised  : XfwfFrameType.XfwfChiseled)),
                         new Arg (XfwfNames.XfwfNframeWidth, (XtArgVal)
            2 + (((int)clientData) == 0 ? 0 : 2)) };
    Xtlib.XtSetValues (widget, toggleArgs, (XCardinal)4);
 
    string sWidgetName = Xtlib.XtNameAsString (widget);
 
    Console.WriteLine ("Toggle switched {0}", sWidgetName);
}

XfwfSlider4 

The XfwfSlider4 widget is almost the same as the XfwfSlider2 widget (with four derees of freedom: horizontal and vertical position as well as width and height), except for the addition of a sash in the lower right corner of the thumb, with which the thumb can be resized. 

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel --> XfwfSlider2 --> XfwfSlider4

New Resources

Name ClassTypeDefault 
XfwfNsashColor XtCSashColor Color XtDefaultBackground  
XfwfNsashPixmap XtCSashPixmap Pixmap NULL 
XfwfNsashFrameType XtCSashFrameType FrameType XfwfRaised
XfwfNsashFrameWidth XtCSashFrameWidth Dimension 2

Callback usage

See XfwfSlider2.

XfwfRadioGroup

The XfwfRadioGroup widget is a more convenient simple specialization of the XfwfGroup widget for the case that the group contains only XfwfToggle buttons. It has an extra resource, labels, which holds the labels of the XfwfToggle  buttons that are created automatically. It is also much less flexible and it is very difficult to change resources (defaults are XfwfNshrinkToFit = True, XtNborderWidth = 0, XfwfNframeWidth = 0) of the radio buttons, when the defaults are not satisfactory.

Inheritance (↑) 

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfRowCol --> XfwfGroup --> XfwfRadioGroup

New Resources

Name ClassTypeDefault 
XfwfNlabels XtCLabels StringArray NULL  

Usage

The XfwfRadioGroup widget creates it's children automatically.
 
String[] items  = { "plum", "cranberry", "cherry", "banana", string.Empty };
Arg[] radioArgs = { new Arg(XtNames.XtNlabel,
                        X11.X11Utils.StringToSByteArray ("XfwfRadioGroup:\0")),
                    new Arg(XfwfNames.XfwfNlocation,
                        X11.X11Utils.StringToSByteArray ("5 5 260 75\0")),
                    new Arg(XfwfNames.XfwfNcolumns,        (XtArgVal)2),
                    new Arg(XfwfNames.XfwfNlabels,         items),
                    new Arg(XfwfNames.XfwfNselection,      (XtArgVal)1),
                    new Arg(XfwfNames.XfwfNselectionStyle,
                        (XtArgVal)XfwfSelectionType.XfwfSingleSelection),
                    new Arg(XfwfNames.XfwfNshrinkToFit,    (XtArgVal)0),
                    new Arg(XfwfNames.XfwfNframeWidth,     (XtArgVal)2),
                    new Arg(XfwfNames.XfwfNframeType,      (XtArgVal)XfwfFrameType.XfwfRaised),
                    new Arg(XfwfNames.XfwfNinnerOffset,    (XtArgVal)8),
                    /* Allocate enough space for group title.*/
                    new Arg(XfwfNames.XfwfNouterOffset,        (XtArgVal)5) };
IntPtr radiogrp = Xtlib.XtCreateManagedWidget(RadioGroup1Name,
                            Xfwflib.Xt_XfwfRadioGroupWidgetClass(), radiogrpBox,
                            radioArgs, (XCardinal)11); 

Callback usage

See XfwfGroup widget.

XfwfOptionButton

The XfwfOptionButton widget is a button with a drop-down menu that displays options from which only one can be chosen. The most recently chosen option remains visible after the menu is closed. 

It is very much like a XfwfPullDown button, except that the label of the button is automatically set to the label of the last selected menu item.

Inheritance (↑)

Core --> Composite --> XfwfCommon --> XfwfFrame --> XfwfBoard --> XfwfLabel --> XfwfButton --> XfwfPullDown --> XfwfOptionButton

New Resources 

None.

Callback usage

Connect the callback via XfwfNames.XfwfNactivate.
/// <summary> The callback for any option button press event within the canvas. </summary>
/// <param name="widget"> The widget, that initiated the callback procedure.
/// <see cref="System.IntPtr"/> </param>
/// <param name="clientData"> Additional callback data from the client.
/// <see cref="System.IntPtr"/> </param>
/// <param name="callData"> Additional data defined for the call.
/// <see cref="System.IntPtr"/> </param>
public void OptionButtonPressCallback (IntPtr widget, IntPtr clientData, IntPtr callData)
{
    string sWidgetName = Xtlib.XtNameAsString (widget);
 
    XfwfTextMenuData textMenuData = (callData != IntPtr.Zero ? (XfwfTextMenuData)
                                     Marshal.PtrToStructure (callData, typeof(XfwfTextMenuData)) :
                                     new XfwfTextMenuData());
 
    if (callData != IntPtr.Zero && textMenuData.n >= 0)
    {
        Console.WriteLine ("OptionButton {0} changed to {1}.", sWidgetName, textMenuData.n);
    }
    else
    {
        Console.WriteLine ("OptionButton {0} changed.", sWidgetName);
    }
}

Points of Interest

Beside the challenges to set the right dependencies (to compile the Xfwf/Free Widget Foundation widgets), correct the compilation errors and optimize the impression is to mention:

Widget initialization and resource names

The C# Arg struct is available since the second article of this series . This project added some options, providing the struct member intValue and floatValue alternatively. Furthermore the new helper classes XtString, XtStringArray, XtByteArray and XtIntegerArray simplify the Arg creation. 

To avoid confusion, all Xfwf/Free Widget Foundation widget resource names are prefixed XfwfN, e. g. XfwfNames.XfwfNactivate.

Alert widget

It was inpossible to get the XfwfAlert widget from scr/Alert/Alert.c running. Instead the scr/Alert/AlertModal.c implements the alternative XfwfAlertModal widget and shows how easy it is to program Xfwf/Free Widget Foundation widgets in plain C too. 

The XfwfAlertModal widget contains the CreateIconFromData() method, that dynamically creates an icon. This method can be a prototype for a dynamic icon creation and can be useful for XfwfIcon and XfwfAnimator too.

History  

  • 28. October 2013, This is the fourth article about native calls from C# and Mono Develop to X11 API. It deals with the Xfwf/Free Widget Foundation widgets. The focus is on the Xt/Athena compatible Xfwf/Free Widget Foundation widgets. The first article of this series was about the Xlib only. The second article was about the Xt only. The third atricle was about the Xm/Motif only. Further articles are planned, that dive deeper into Xlib, Xt/Athena or Xm/Motif.  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Steffen Ploetz
CEO Ploetz + Zeller GmbH
Germany Germany
I am CEO at Ploetz + Zeller GmbH, Munich Germany (www.p-und-z.com)
 
Ploetz + Zeller GmbH is a consulting and software services company committed to pro-active and professional governance and optimization of our clients' company processes. Furthermore it offers Symbio (www.symbioworld.com) software, a very powerful and easy to use business process management suite.
 
My responsibilities range from product ownership of Symbio via responsibility for the architecture of some Symbio software components to implementation of software core parts (e. g. automatic layout).
 
I started programming 1986 with C64 BASIC and came via Pascal, Turbo Pascal, C, Turbo C, C++ and Java to C#. I like the potential of C++ very much, but now my favorite language is C#.
 
I believe a lot in free knowledge sharing. I'm author at German Wikipedia and, after 10 years of passive membership, author at CODE PROJECT.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.141022.2 | Last Updated 7 Nov 2013
Article Copyright 2013 by Steffen Ploetz
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid