[Home] [Prev] [Next] [Up]
XGView class
The core view class. This provides a mechanism for managing the geometry of the different drawing regions.
Usage:
#include <XView.h>
class XGView;
Description
This class provides for partitioning a window into separate smaller views. This is a fairly complex class, but at it's core, the XGView is a mechanism for managing a series of imbedded rectangles, and performs hit detection and drawing support against those rectangles.
On Windows, a child window is created and associated with each XGView. But otherwise, the Windows version is identical.
Inheritance
The XGView class inherits functionality from the XGDispatch class. This means that the focus routines and dispatch routines of the XGDispatch class are also inherited by the XGView class.
Class Overview
The XGView class is sufficiently complex that I have included a table of contents to the following descriptions.
How to construct and destruct this view.
These virtual methods are overriden when you wish to construct a custom view. Normally you would not call these routines.
The XGDispatch method is overridden for housekeeping purposes.
Support routines for determining the state of a view and getting additional information about a view.
These additional attribute methods provide information about this view in the context of the view hierarchy, the hierarchy of parent and child views.
These methods provide for scrolling the bits in a view.
Coordinate system manipulation
These methods provide a way to get the location and size of view, set the view's location and size, and handle coordinate system conversions.
These methods provide for validating or invalidating a view, or for forcing a view to be updated if it's invalid.
XGView::XGView(XGView *parent, XGArgStream &args, bool nowin = false);
XGView::XGView(XGView *parent, XGSViewInitRecord &init, bool nowin = false);
These two constructors are the two normal ways to build a view. The first argument specifies the parent view in the view hierarchy. The second argument specifies the parameters used to initialize the view. If the second parameter is an XGArgStream object, this indicates the arguments are read from a resource. That form of the constructor is normally called from the view factory object XGViewFactory.
The third optional argument is only used on the Windows OS: if true, the nowin argument won't construct a child window when building the view. This is useful if you are using an XGView object to encapsulate the functionality of a window control.
If you do construct a view using the nowin flag set, you must immediately set the view window associated with this view using the internal routine XGView::_SetHWND(HWND w);
The initialization parameters in the XGSViewInitRecord (and their equivalent stored in the 'VRes' stream) are:
fViewType The type of the view. Typically this is a four-letter field which identifies the view for the 'VRes' resource and the constructor factory. Note: YAAF reserves all view types which are comprised of all lowercase letters. fViewID The view ID of this view fRefNum The 32-bit reference ID in this view. (See GetRefNum/SetRefNum for more info.) fLockLeft True if the left side of this should be fixed with the left boarder of the parent view. If false, the left side will float relative to the right border, and should be specified as a negative number--the distance left of the right boarder of the parent view. fLockTop Locks the top edge of this view to the top of the parent. If false, this should be specified relative to the bottom edge. fLockRight Lock the right side. If true, this should be set to a negative offset from the right side of the parent view; if false, this should be the distance from the left side. fLockBottom Locks the bottom. Like the right, if true, this should be relative to the bottom; if false, relative to the top. fAutoLeft The amount off the left or right the left edge of this view should be from the parent. fAutoTop The relative amount off the top or bottom of the parent the top of this view should be. fAutoRight The relative amount off the right or left the right side of this child view should be fAutoBottom The relative amount off the botom or top the bottom of this view should be fVisible True if this should be initially visible fEnabled True if this should be initially enabled fTabStop (Used by the XGDialog class) to determine if the tab buttom should switch focus to thsi view. Need to fix this to work correctly on both the Macintosh and Microsoft Windows. XGView::~XGView()
This destructs both this view and all the views that are contained in this view. This also releases the window object associated with this view.
These methods are called when certain events occur which require the view to respond. For example, the 'DoDrawView' method is called when the view needs to be drawn.
If you are adding a custom view, you need to override the following methods (and in some cases, call the XGView method) to add your custom functionality.
void XGView::DoDrawView(Rect invalid)
This method is called when it is time to redraw your view, in responce to an update event from the host OS.
The rectangle provided is the bounding rectangle (in the view's local coordinates) of the area that needs to be redrawn.
By default, the XGView::DoDrawView method draws status information, useful in debugging an incomplete view specification. You should not call the XGView::DoDrawView method from your overridden method.
Normally, to draw your view, you need to create a stack-based XGDraw object with your view to open a drawing context. Further, as drawing routines are not encapsulated, you normally write two versions of your drawing routines: one for the Macintosh (using QuickDraw), and one for Windows (using the Windows GDI).
For example:
void XGMyView::DoDrawView(Rect /*ignored*/) { XGDraw draw(this); #if OPT_MACOS == 1 ::MoveTo(10,10); ::DrawString("\pHello world!"); #endif #if OPT_WINOS == 1 Rect r; r = GetContentRect(); /* Get size of my bounding */ ::DrawText(draw.GetDC(), "Hello world!",-1, &r,DT_SINGLELINE | DT_TOP); #endif }void XGView::DoActivate(bool active)
This method is called when the window containing this view is either activated or deactivated. This gives this view the chance to respond. You can either redraw the view in this method, or simply invalidate the view (see InvalView) and rely on the DoDrawView (above) to draw the view correctly.
To find out if your view is currently active, use the IsActive method (below).
By default this does nothing. You should not call the XGView::DoActive method from your overridden method.
bool XGView::DoMouseDown(Point where, short flags)
This method is called when the mouse is clicked in your view. The location is specified in the view's local coordinates. The flags parameter contains an OR'ed of the following flags. (Note they are the same as the flags passed in the KEventKey event, they are defined in the <XEvent.h> header. Italic flags are specific to the mouse events)
KKeyShift Shift key pressed KKeyControl Control key pressed KKeyCommand (Mac) Apple key pressed KKeyOption (Mac) Option key pressed KKeyMenu (Windows) Alt key pressed KKeyButton Mouse button pressed KKeyRButton (Windows) Right button pressed KKeyMButton (Windows) Middle button pressed KSpecialKey Special keyboard code KDoubleClick The mouse was double-clicked here KCapturedMouse The mouse was captured (in DoMouseMove and DoMouseUp only, see below) The KDoubleClick flag indicates that the mouse was double-clicked at this location.
There are two semantics you can use to do mouse drag tracking. The first is more often used, though the second is prefered.
The first method is to simply handle dragging inside of the DoMouseDown method, and when done, update and return. This is used to handle the various Macintosh controls (as this is the method that is favored by the Macintosh routine TrackControl).
The second method is to capture the mouse. To 'capture' the mouse means that so long as the mouse button is down, mouse move and the final mouse up method will all be funneled to this view--the view has effectively 'captured' the mouse for the duration of the dragging.
To capture the mouse, return true from this routine. Then, all subsequent mouse move and the final mouse up event will only call this veiw, regardless of where on the screen the mouse is dragged.
While the mouse is captured, all calls to the mouse handling routines will set the flag KCapturedMouse; this indicates the mouse is currently captured and is probably dragging something.
void XGView::DoMouseMove(Point where, short flags)
This is called when the mouse is moved above this view. By default, the XGView::DoMouseMove method sets the mouse cursor to the arrow cursor.
This routine is called repeatedly when the mouse is captured. If that happens, you should handle mouse dragging functionality by testing for the KCapturedMouse flag and process accordingly.
void XGView::DoMouseUp(Point where, short flags)
This event is called when the mouse button is released inside this view. Normally you ignore this message, unless the mouse has been captured. In that case, you need to stop the dragging operation and update accordingly.
The default routine does nothing. Normaly you don't call the default method from your overridden method.
void XGView::DoSizeView(void)
This event is passed when the view's size has changed. This gives you the opportunity to resize the contents, to adjust the location of child views, and to recalculate the scrollbar range for the larger or smaller display area.
By default, this method loops through all the children views and resizes them using the AutoLocate method. (See below). If you wish to preserve this functionality, you should call the XGView::DoSizeView() method yourself. If you have no children, or if you want to handle relocating the children views yourself, then don't call the XGView::DoSizeView() method.
void XGView::DoMoveView(void)
This event is passed when the view's global location or location relative to the parent view has changed. This is normally ignored, and is used only to relocate a Macintosh control if it is moved.
By default this method does nothing. Normally you would not call the view method.
XGDispatch *XGView::SetFocus()
This overrides the XGDispatch focus routine for internal housekeeping purposes. I note that here only so that if you override the XGView::SetFocus() method (which is rare), you should make sure your method calls the XGView::SetFocus() method explicitly.
bool XGView::IsVisible(void)
void XGView::ShowView(void)
void XGView::HideView(void)This changes the visibility of a particular view. If the parent view is not visible, none of the children view in this parent is also visible. The IsVisible method is used to determine if the parent view is visible only.
bool XGView::IsEnabled(void)
void XGView::EnableView(void)
void XGView::DisableView(void)This enables or disables a view. A disabled view is one which does not accept keyboard or mouse input.
Todo: the enabled attribute is not completely wired up correctly.
bool XGView::IsActive(void)
This returns true if the view (and it's containing window) is currently the active window.
bool XGView::IsCapture(void)
This returns true if this view has captured the mouse. This can be used in addition to detecting the 'KCaptureView' flag in the DoMouseMove method to determine if the mouse is captured.
bool XGView::IsTabStop(void)
Todo: this needs to be wired into the XGDialog class to enable tabstop navigation from view to view.
long XGView::GetRefNum(void)
void XGView::SetRefNum(long)This sets a 32-bit value in this view to any value. This reference number can be any value you wish.
long XGView::GetViewType(void)
This returns the type of this view. The type is the type of view that is used to construct the view; customarly that type is a 4 character identifier used by the view's factory constructing this thing.
short XGView::GetViewID(void)
This returns the identifier of this view. That identifier value can be used to search for a particular view using the FindViewByID method below.
XGView *XGView::GetParent(void)
This gets the parent view that this view is contained in.
XGView *XGView::GetChild(void)
This gets the first child of the children in this view.
XGView *XGView::GetSibling(void)
This gets another sibling of this view. Used by the parent view to find all of the views in this thing.
XGWindow *XGView::GetWindow(void)
This returns the window which this view is contained in.
XGDocument *XGView::GetDocument(void)
This returns a pointer to the document associated with this window. The document handling model for the YAAF library assumes each window has at most one document; this is used as a quick way for the view to find the document associated with this window (if any).
XGView *XGView::FindViewByID(short id)
This recurses through all the children of this view, and finds the view with the specified ID. If there is no child view with this ID, this returns NULL.
XGView *XGView::FindViewByPoint(Point pt)
This recurses though all of the views in this view, and finds the child view which contains this point.
void XGView::Scroll(long x, long y)
Handle scrolling in this view. This is a virtual function which passes by default to the ScrollView method (below). This is called by the XGScrollView procedure (and other YAAF routines) to request that this view be scrolled.
The reason for separating the Scroll method from the ScrollView method is to give a view the opportunity to break it's content region into several sections and scroll them separately. Thus, a view which contains a ruler along the top and left of the view may want to override the Scroll method as follows:
void TMyView::Scroll(long x, long y) { Rect r; r = TopRulerRectangle(); ScrollView(x,y,&r); r = LeftRulerRectangle(); ScrollView(x,y,&r); r = ContentRectangle(); ScrollView(x,y,&r); }By defaul this method scrolls the entire content region right (for positive x) and down (for positive y).
void XGView::ScrollView(long x, long y, Rect *r = NULL)
This scrolls the bits in this view right and down by the amount specified, and invalidates the region that requires updating.
Coordinate System Manipulation
Point XGView::GetPos(void)
Get the location of the upper left corner of this view in my parent's view.
Point XGView::GetSize(void)
Get the size of this view.
Rect XGView::GetContentRect(void)
Get a rectangle which describes the content region of this view. The upper left corner is at (0,0), and the size of the rectangle is the same as returned by GetSize (above).
void XGView::SetLocation(Rect r)
This moves the view to the location specified in the parent view. This automatically calls the DoSizeView() and DoMoveView() methods as they are needed.
void XGView::AutoLocate(Rect r)
Given the rectangle of the parent's content region, this calculates the location where the view belongs, according to the automatic location parameters provided.
By default this is called by the DoSizeView method to automatically reposition the views. This is also called by the XGScrollView class to autolocate the child views, offset by the scrollbars in that view.
void XGView::GlobalToView(Point *p)
void XGView::GlobalToView(Rect *r)These routines convert from the coordinate system of the content region of the window this view is in, to the local coordinate system of this view.
void XGView::ViewToGlobal(Point *p)
void XGView::ViewToGlobal(Rect *r)These convert from the local coordinate system of the specified view to the global system of the window.
void XGView::InvalView(Rect *r = NULL)
This invalidates the rectangle area inside the specified view. If the parameter is NULL (or not included), this invalidates the entire content region of the specified view.
void XGView::ValidView(Rect *r = NULL)
This validates the rectangle area specified inside the view. If the parameter is NULL, this validates the entire content region of the specified view.
void XGView::UpdateView(void)
This forces the DoDrawView method to be called for this view if any part of this view is marked invalid.