The following code fragment creates a canvas with a fixed-size paint window that is not
affected by resizing:
Canvas canvas;
canvas = (Canvas)xv_create(frame, CANVAS,
CANVAS_AUTO_SHRINK, FALSE,
CANVAS_AUTO_EXPAND, FALSE,
CANVAS_WIDTH, 1000,
CANVAS_HEIGHT, 1000,
NULL);
This call sets the initial size of the paint window to 1000 by 1000 pixels. The origin of the
paint window’s coordinate system is the upper-left corner (0,0) and the lower-right corner
(CANVAS_WIDTH-1, CANVAS_HEIGHT-1). Note that we did not set the size of the
canvas subwindow. Instead, we allowed it to be determined by the frame size. The size of
the paint window remains constant regardless of how the frame and canvas subwindow is
resized. If the frame or the canvas subwindow resizes, the subwindow merely changes its
view of the underlying paint window, which remains constant.
In the following code fragment, we set the size of the canvas subwindow, using generic attri-
butes:
Canvas canvas;
canvas = (Canvas)xv_create(frame, CANVAS,
CANVAS_AUTO_SHRINK, FALSE,
CANVAS_AUTO_EXPAND, FALSE,
CANVAS_WIDTH, 1000,
CANVAS_HEIGHT, 1000,
XV_WIDTH, 200,
XV_HEIGHT, 100,
NULL);
Here, a canvas subwindow is created that is 200 pixels wide and 100 pixels high. All other
attributes about this canvas object are the same as the previous example: the paint window is
going to be 1000x1000 in width and height. The problem with this canvas is that the user has
no way to view different parts of the paint window. To handle that, scrollbars should be atta-
ched to the canvas to provide scrolling. See Section 5.5, “Scrolling Canvases.”
5.4.3 Tracking Changes in the Canvas Size
In the event that the canvas paint window has been resized, the program has the opportunity
to track this event by installing a callback routine. This routine is installed using CANVAS_
RESIZE_PROC
. The client’s resize procedure is called only when the width or height of the
canvas’s paint window changes. Its form is:
void
sample_resize_proc(canvas, width, height)
Canvas canvas;
int width;
int height;
100 XView Programming Manual
The parameters to the resize procedure are the canvas, and the width and height of the
canvas.
If you need to handle resize events for the canvas or the view windows, provide an event
handler for those windows, using the attributes WIN_EVENT_PROC and WIN_CON-
SUME_EVENTS
(see Section 5.7, “Handling Input in the Canvas Package,” for more informa-
tion).
5.5 Scrolling Canvases
Many applications need to view and manipulate a large object through a smaller viewing
window. To facilitate this, packages that are subclassed from the openwin class may have
scrollbars attached to their subwindows.
The following code fragment creates a canvas that can be scrolled in both directions:
Canvas canvas;
Scrollbar h_scrollbar, v_scrollbar;
canvas = (Canvas)xv_create(frame, CANVAS,
CANVAS_AUTO_EXPAND, FALSE,
CANVAS_AUTO_SHRINK, FALSE,
CANVAS_WIDTH, 1000,
CANVAS_HEIGHT, 1000,
NULL);
h_scrollbar = (Scrollbar)xv_create(canvas, SCROLLBAR,
SCROLLBAR_DIRECTION, SCROLLBAR_HORIZONTAL,
NULL);
v_scrollbar = (Scrollbar)xv_create(canvas, SCROLLBAR,
SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL,
NULL);
Because the SCROLLBAR package is being used here, the header file <xview/scrollbar.h> must
be included. Chapter 10, Scrollbars, discusses scrollbars more completely and also gives fur-
ther examples of how to scroll canvases.
The owner of the scrollbars is the canvas so that the scrollbars are automatically attached to
the canvas’s view. If the user scrolls the canvas, your canvas’s repaint procedure will be
called provided that the canvas’s
WIN_RETAINED attribute is set to FALSE. This is important
because setting WIN_RETAINED to TRUE assumes that you are not interested in handling
repainting for scrolling. In other words, as long as the user does not do anything that changes
the contents of the image, you do not need to be informed when the user scrolls the image. If
you want to be informed of scrolling, set
WIN_RETAINED to FALSE and your repaint routine
will be called with the exposed area parameter describing the new area that just scrolled into
view.* If there are many views in the canvas, the paint window associated with the view that
scrolled is in the second parameter to the repaint function: the paint_window.
*The exposed area passed to the repaint procedure is of type Xv_xrectlist if CANVAS_X_PAINT_WINDOW is
set to TRUE or Rectlist if CANVAS_X_PAINT_WINDOW is set to FALSE.
Canvases and
Openwin
Canvases and Openwin 101
5.6 Splitting Canvas Views
There are two methods by which the application may split the views of a canvas (or any
openwin-classed object). The first method is for the user to use the scrollbars to split views.
This method is more common and complies with the OPEN LOOK specification. The alternate
method is for the application to make calls to xv_set() with attribute-value pairs that tell
where and how a view should be split.
Whenever views are split, the following attributes are propagated from the split paint win-
dow to the new paint window:
WIN_BACKGROUND_COLOR
WIN_FOREGROUND_COLOR
WIN_CMS
WIN_COLUMN_GAP
WIN_COLUMN_WIDTH
WIN_CURSOR
WIN_EVENT_PROC
WIN_ROW_GAP
WIN_ROW_HEIGHT
WIN_X_EVENT_MASK
5.6.1 Splitting Views Using Scrollbars
To set up the canvas so that the user can split it using scrollbars, the canvas should have
scrollbars attached as shown in the previous example with the additional attribute
SCROLLBAR_SPLITTABLE set to TRUE:
h_scrollbar = (Scrollbar)xv_create(canvas, SCROLLBAR,
SCROLLBAR_DIRECTION, SCROLLBAR_HORIZONTAL,
SCROLLBAR_SPLITTABLE, TRUE,
NULL);
v_scrollbar = (Scrollbar)xv_create(canvas, SCROLLBAR,
SCROLLBAR_DIRECTION, SCROLLBAR_VERTICAL,
SCROLLBAR_SPLITTABLE, TRUE,
NULL);
With this attribute set, the scrollbars have the ability to split view windows in two. The user
splits the view by selecting the cable anchors at the endpoints of the scrollbars and dragging
them towards the center of the scrollbar. A pop-up menu provided with the scrollbars also
provides this functionality. The entire view will be split at the point the mouse button is
released, provided there is enough room for a new view at that point. Each view can scroll its
own underlying paint window independently of other views.
102 XView Programming Manual
5.6.2 Splitting Views Using xv_set()
Splitting a view by setting attribute-value pairs in the view is a less common method since
the scrollbar already provides this functionality. However, there is a programmatic interface
for splitting views whether or not those views have scrollbars attached to them.
The attribute OPENWIN_SPLIT is followed by a list of attribute-value pairs that indicate
specifically how a view is to be split. Only attributes that are prefixed with OPENWIN_SPLIT
may be used in this NULL-terminated list. Other attributes are ignored. The following dem-
onstrates how an arbitrary view window can be split into two parts:
Xv_Window view;
view = (Xv_Window)xv_get(canvas, OPENWIN_NTH_VIEW, 0);
xv_set(canvas,
OPENWIN_SPLIT,
OPENWIN_SPLIT_VIEW, view,
OPENWIN_SPLIT_DIRECTION, OPENWIN_SPLIT_HORIZONTAL,
NULL,
NULL);
This very simple example shows that the first view window in the canvas will be split hori-
zontally. The place in which the split takes place is, by default, the position of the scrollbar
in the view. Assuming the code fragment above, the window is split so that the new view is
the same width as the original view but the height is split at the position of the scrollbar. The
original view is the remaining height and is on top of the new view.
5.6.3 Getting View Windows
If a canvas has been split several times, resulting in multiple view and paint windows, it is
possible to get a handle to a particular view or paint window. This can be done either at the
time the view was split or by using xv_get().
5.6.3.1 Getting the newest view
If you want to be notified when the user splits or joins views, you can specify the attribute
OPENWIN_SPLIT_INIT_PROC for when the user splits a view, and OPENWIN_SPLIT_
DESTROY_PROC
when the user joins a view. These attributes are set in the canvas (or any
openwin object). Set these functions by using xv_create() or xv_set() in the follow-
ing manner:
extern void init_split(), join_view();
xv_create(frame, CANVAS,
...
OPENWIN_SPLIT,
OPENWIN_SPLIT_INIT_PROC, init_split,
OPENWIN_SPLIT_DESTROY_PROC, join_view,
NULL,
...
NULL);
Canvases and
Openwin
Canvases and Openwin 103
Write the split and join functions, which take the following parameters:
void
init_split(origview, newview, pos)
Xv_Window origview, newview;
int pos;
void
join_view(view)
Xv_Window view;
The pos parameter above represents the split position, in pixels, of the view. The
origview and the newview parameters represent the view that was originally split and the
new resulting view, respectively. These are not the paint windows; they are the views them-
selves. To get a handle to the associated paint window from these views, you can use:
Xv_Window paint_window;
paint_window = (Xv_Window)xv_get(view, CANVAS_VIEW_PAINT_WINDOW);
Example 6-1 in Chapter 6, Handling Input, shows how to handle input in different views.
5.6.3.2 Getting arbitrary views
For each view in an
OPENWIN object, you can get either the view window or the paint win-
dow by choosing either the CANVAS_NTH_PAINT_WINDOW or the OPENWIN_NTH_VIEW attri-
bute and an integer value for the view window. The first window is 0 and the last window is
n-1, where n is the number of view windows. For instance, to get the second paint window in
the canvas, you can use:
xv_get(canvas, CANVAS_NTH_PAINT_WINDOW, 1, NULL);
You can get the number of available views by calling:
int nviews = (int)xv_get(canvas, OPENWIN_NVIEWS);
Remember that the number of views corresponds directly to the number of paint windows.
Each paint window can be accessed in order, using a simple loop like the following:
Xv_Window window;
Canvas canvas;
int i = 0;
while (window = (Xv_Window)xv_get(canvas, CANVAS_NTH_PAINT_WINDOW, i)) {
draw_into_window(window);
i++;
}
The call to xv_get() returns NULL if you try to get a window number that does not exist
(XView does the error checking). Thus, the loop terminates when xv_get() returns NULL.
The value of i represents the number of views in the canvas subwindow.
XView provides a pair of macros that facilitate looping through a set of views in a canvas:
CANVAS_EACH_PAINT_WINDOW and CANVAS_END_EACH. The previous loop could be written
as:
104 XView Programming Manual

Get Volume 7A: XView Programming Manual now with the O’Reilly learning platform.

O’Reilly members experience live online training, plus books, videos, and digital content from nearly 200 publishers.