How can I make a drawing area occupy the full screen size?
|
8-Dec-00 09:00 GMT
|
Question: How can I make a drawing area occupy the full screen size?
my application contains menubars, other widgets etc. but sometimes
users don't want those and want to use the full monitor area for viewing.
I am running under the assumption here, that what you mean is that the drawing area
occupies all of the space in the current dialog, rather than making the current dialog
the full screen size, the answer to which is
obtained by clicking here.
There is more than one way to achieve this. Basically, it depends on your widget
hierarchy as to the exact mechanism you adopt, but the basic principles are
-
To arrange to hide/show portions of the hierarchy by managing/unmanaging them
-
To ensure that there occurs no explosive geometry management effects as a result.
As an example, consider a dialog which contains a shell, form, menubar, and drawing area.
Presumably the menubar is in the standard place at the top of the dialog, with the drawable
underneath. If we want to make the drawing area cover the space occupied by the menubar,
we can perform the following steps:
-
unmanage the menubar
-
attach the top of the drawing area to the top of the form
To perform the reverse step of showing the menubar again, we simply:
-
manage the menubar
-
attach the top of the drawing area to the bottom of the menubar
This, however, is not a full solution because as we manage/unmanage portions of the hierarchy
there will occur geometry management effects up through the form and shell, and the dialog may well
resize as a result. This may or may not be the desired effect. Personally, I think I'd find it annoying:
I think I'd like the dialog to remain the same size as I do this. In order to make sure this does not
happen, I would set the XmNresizePolicy of the form to XmRESIZE_NONE. This does not mean
that the user cannot resize the dialog using the normal window manager decorations: it is an internal widget
thing which prevents the form from turning round to the parent shell and asking for more/less space in response
to internal widget geometry changes.
As an alternative, we could have a widget hierarchy with a rowcolumn at the top: we do not then have to
bother with form attachments, and a simple manage/unmanage call will do the trick. The price we pay is
less control over the geometry management side effects, and a loss in control over the layout: the rowcolumn
isn't really the best tool for organising widgets of different sizes, as it tends to want to force the
width/height of its children to be the same in a given dimension, depending on its orientation.
Note that the technique is expandible. If you have many widgets, not just the menubar, that you need to
hide/show, then if you place them all in one containing form, the form can be manipulated so that all the
widgets are effected as one. If however, your layout is slightly more complex (a menubar at the top,
drawing area in the middle, and some status or other widgets down the bottom), then the principle still holds -
we need to manage/unmanage portions of the interface, and reset some attachments - only this time we need to
be rather more careful when considering the required attachments to redisplay the objects: it is not
that hard to end up with circular attachments by a careless ordering of the way we go about things, and Motif
doesn't like circular attachments.
The remaining issue is one of mechanism. Once the menubar is hidden, how would we go about redisplaying it -
all we can see is the drawing area, so there's no menu item or other control accessible to do the trick.
The simplest solution is to implement an application action, and apply a translation to call it.
The action simply performs the steps of managing/unmanaging and re-attachment as required. This works
fine, provided that the focus is in the drawing area and this is where we apply the translation. The focus
will be in the drawing area if is the only visible widget. But this is not true if there are other widgets
like the menubar which are visible. We therefore might have to implement a grab so that a particular
key sequence is always directed to the drawing area (and thus invokes our action wherever the focus is).
As an example, the following figure shows a program which is presumably similar in design to yours.
It has a shell, form, menubar, a few other controls, and a drawing area. I place everything except
the drawing area in a form of its own, so that I can manipulate them as a group.
-
Let the shell widget which contains the dialog be called "shell".
-
Let the top level form underneath the shell be called "topform".
-
Let the drawing area be called "drawable". This is a child of topform.
-
Let the form containing the menubar and extra widgets be called "subform". This subform
is a child of the topform.
The dialog should be laid out as follows: the subform should be attached to the left, right, and top
to the containing topform. The drawable should be attached to the left, right, and bottom to the containing
topform. The drawable should also be attached to the top to the subform widget. The following code does this:
XtVaSetValues (subform, XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_NONE,
NULL);
XtVaSetValues (drawable, XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, subform,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNbottomAttachment, XmATTACH_FORM,
NULL);
At this point when we lay out the initial dialog, we make sure that the resize policy is correct
to prevent the explosive geometry management effects:
XtVaSetValues (topform, XmNresizePolicy, XmRESIZE_NONE, NULL);
Now we can start to look at the dynamic behavior. The algorithm for making the drawing area
occupy the whole dialog is as follows:
XtVaSetValues (drawable, XmNtopAttachment, XmATTACH_FORM, NULL);
XtUnmanageChild (subform);
The algorithm for redisplaying the menubar and other widgets is:
XtManageChild (subform);
XtVaSetValues (drawable, XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, subform,
NULL);
Lastly, we need to add some actions, translations, and so forth, to call the above algorithms.
How to do this is really a separate question, but the code to do this for the example figure
can be downloaded from here. The key routines are:
XtAppAddActions() - installs a new action into the application
XtParseTranslations() - parses a translation specification into an internal toolkit form
XtOverrideTranslations() - installs the parsed translations onto the drawing area widget
XtKeysymToKeycode() - a routine to convert a logical Key symbol into internal form (keycode)
XtGrabKey() - a routine to catch a keycode on a widget, and distribute it elsewhere
XtAddEventHandler() - a routine to install interest in an event for a widget
The example installs the translation "Ctrl<Key>R" for the resize action. You should be able to type
this anywhere in the application, and the resize behaviour should take effect, irrespective of where
the focus is currently located. The effect is as given in the following figure; typing the translation again
should revert to the original figure above, without any resize of the containing dialog:
The application has been generated using X-Designer. For this, I apologise: it is not my intention
to use this column as a blatant advertising vehicle. However, writing this piece of code by hand would
have taken me rather long to effect a reply. The design file is included with the sample sources,
in case anyone is interested or has use of this. The sources can be read, however, completely independently
of the GUI builder: it is the code I would have written by hand if I had that amount of time.
The sources consist of:
-
resize.c
- the generated source code for the interface
-
resize_stubs.c
- the event handler, action code for the drawing area
-
resize.h
- a header file with the extern widget declarations
- Makefile
- a general purpose Makefile for the application. It is configured for Solaris,
but at the top of the file are rules for various platforms: simply comment out the Solaris
section, and uncomment your platform as required.
-
resize.xd
- the X-Designer design save file. Feel free to ignore this.
In order to see the source code listings
(in a new window)
click on the file names above,
then to save the code in a file use 'Save As' from the 'File' menu of
that window.
Alternatively download a tar archive,
resize.tar. of all the above source
files.
If you are using Netscape Navigator you may have to hold down
the Shift key when you click on the file name in order to
ensure that you are prompted to save the file.
Sponsored
by X-Designer - The Leading X/Motif GUI Builder
- Click to download a FREE evaluation
Goto top of page
|