The C64 OS Programmer's Guide is being written

This guide is being written and released and few chapters at a time. If a chapter seems to be empty, or if you click a chapter in the table of contents but it loads up Chapter 1, that's mostly likely because the chapter you've clicked doesn't exist yet.

Discussion of development topics are on-going about what to put in this guide. The discusssions are happening in the C64 OS Community Support Discord server, available to licensed C64 OS users.

C64 OS PROGRAMMER'S GUIDE

Class Reference: TKView:TKObj

Overview

TKView is a fundamental class. It inherits from TKObj, and all other classes that are provided with C64 OS inherit from TKView.

TKView provides several groups of properties and methods allowing TKView itself and all of its subclasses to behave as nodes in a tree which defines the structure of a user interface. The nodes are able to participate in handling and propagating mouse and keyboard events. They also know how to resize and position themselves based on a set of anchors and offsets. TKView and all of its descendents have the ability to draw themselves, and to perform mouse event hit testing.

TKView may be instantiated directly when the user interface requires a generic container for one or more subviews. For instance, if you want to construct a user interface that consists of a scrollable list with a button below the list, a TKView can be instantiated as the container for both the TKScroll view and the TKButton control. TKScroll and TKButton both inherit from TKView and their offset and anchor properties can be set to size and position them within their parent TKView container.

When a TKView is resized, it propagates the resizing to its children and computes their new size and position. TKView can also be used as an intermediate container for just a single child view to create a border around that child which would ordinarily sit flush to the edges of its parent. By setting the bcolor property of that container TKView that border can have a customizable color.

Subclassing notes

All other classes included with C64 OS inherit either directly or indirectly from TKView.

TKView implements very complex logic in its resize, update and hittest methods. Attempting to reimplement any of these methods is not recommended. In order to retain their complex behavior any TKView subclass should call the superclass implementation of these methods.

Class Definition

//os/tk/h/:tkview.h

Init (init_)

During initialization, a TKView's anchor properties are set to Top, Bottom, Left and Right, and to propgate resizing events to its children. Its scroll offsets are zeroed. Its flags are to mark it as: dirty, accepts first mouse, in bounds, visible but transparent, and requiring an initial resize. Its background color is set to dynamically take the background color from the system's color theme.

Responder Methods

Method Description Offset
setfirst_ Set First Responder 10
Method Description Offset
dokeyeqv_ Do Key Equivalent 13
keypress_ Key Press 16
Method Description Offset
musdown_ Left Mouse Down 19
musmovd_ Mouse Moved 22
musup_ Left Mouse Up 25
musclik_ Left Mouse Click 28
musdclik_ Left Mouse Double Click 31
rmusdwn_ Right Mouse Down 34
musalt_ Mouse Alternate Event 37

The responder methods are a group of methods that are responsible for event handling. The TKView implementation of the keyboard and mouse event methods do not directly affect the TKView object, but are responsible for propagating the event up the view hierarchy. Any subclass of TKView may reimplement an event handling method in order to perform some custom behavior. Any method not specifically handled by the subclass should call the superclass method in order to retain the essential event propagation behavior.

Set First (setfirst_)

Input Description
C → Set Set as first responder
C → Clear Resign as first responder
Output Description
- None

Keyboard event routing begins with a view that is called the first responder. There can be only one first responder at a time. If there is no explicit first responder, the root view is the default first responder.

There is a bit flag in the dflags property, Accepts First Key (df_afkey). If this flag is set when a mouse click event is handled, the first responder status is shifted to this object. This is accomplished by calling setfirst_ with the carry set. Set First, internally, looks up the current first responder object and calls setfirst_ with the carry clear. This causes the current first responder to resign its status as first responder, just prior to this object taking on the first responder status.

TKView's accepts first key flag is unset by default. Subclasses of TKView which handle key events should enable this flag in their init_ method.

The first responder status can be programmatically shifted to any object (whose accepts first key flag is set) by explicitly calling its setfirst_ method with the carry set. It is also sometimes desired to programmatically have the current first responder lose its first responder status without explicitly shifting the focus to some other object. This can be done by calling the first responder's setfirst_ method with the carry clear.

The first responder object is pointed to by the Toolkit Environment's First Key View (te_fkeyv) property.

If a subclass of TKView accepts first key and it undergoes a change of appearance as a result of accepting first key status, it should reimplement the setfirst_ method. In its own implementation it should set its dirty flag and then call the superclass setfirst_ method. TKInput is an example of this behavior. When clicked it not only takes first key status but its background color changes to distinguish it as the field in focus and it displays an input cursor. When a TKInput loses first key status, it marks itself dirty again, so that it can be redrawn without the input cursor and with the background color of an unfocused field.

Do Key Equivalent (dokeyeqv_)

Input Description
- None
Output Description
- None

Do Key Equivalent is called when a low-level key command event is queued and being routed into the Toolkit environment to be processed.

TKView's default behavior is to propagate the event up through the responder chain. The responder chain is not identical to the node tree, although there is a relationship between them.

When a key command event is to be propagated, it is sent to the object pointed to by this object's next responder (nextresp) property. If the next responder property is null, then it is sent to this object's parent node instead. Propagation continues until an object handles the event and then does not propagate it any further up the responder chain, or when the event reaches the root view.

Subclasses of TKView which provide support for key command events should implement this method. Any key command event not supported should result in calling the superclass dokeyeqv_ method.

Key Press (keypress_)

Input Description
- None
Output Description
- None

Key Press is called when a low-level printable key event is queued and being routed into the Toolkit environment to be processed.

TKView's default behavior is to propagate the event through up the responder chain. The responder chain is not identical to the node tree, although there is a relationship between them. The responder chain for printable key events is slightly more complicated than it is for key command events.

When a printable key event is to be propagated, it is sent to the object pointed to by this object's next responder (nextresp) property. If the next responder property is null, then it is sent to this object's parent node instead. Propagation continues until an object handles the event and then does not propagate it any further up the responder chain. If the event reaches the root view, and the root view does not handle the event itself, TKView's default behavior is to check if the printable key event is the RETURN key.

If the RETURN key has propagated all the way to the root view, TKView instigates a search for the first TKCtrl object (or any of its subclasses) which is not disabled and has its default flag set. If and when such a control object is found that control's Send Action (sendact_) method is called and the search terminates. The search is performed by walk, and only walks the visible tree. The check for whether a node is a subclass of TKCtrl is performed by instanceof.

Subclasses of TKView which provide support for printable events should implement this method. Unsupported printable key events usually result in calling the superclass keypress_ method, but may refrain from doing so under special circumstances.

All mouse events, except Left Mouse Click

Input Description
- None
Output Description
- None

TKView does not directly respond to mouse events. Its default behavior is to propagate the event up the view hierarchy by calling the same mouse event method on this view's parent view. Propagaion continues until an object handles the mouse event and does not propagate it further, or the event reaches the root view.

Left Mouse Click (musclik_)

Input Description
- None
Output Description
- None

As with all the other mouse events, TKView does not directly respond to mouse click events. Its default behavior is to propagate the click event up the view hierarchy until an object handles the mouse click event and does not propagate it further, or the event reaches the root view.

However, TKView does have one custom behavior for the Left Mouse Click event specifically. It checks to see if its Accepts First Key flag is set. If it's set, it calls setfirst_ with the carry set on itself, and then ends propagation.

Subclasses of TKView which handle key events but do not have complicated mouse event handling are not required to reimplement the musclik_ method. Simply be setting their Accepts First Key flag (df_afkey flag of the dflags property) they will take first key status when clicked.

Mouse Alternate Event (musalt_)

Input Description
- None
Output Description
- None

Mouse event types which do not have their own method result in musalt_ being called. The need to respond to these mouse events is relatively rare. Subclasses which need, for example, to respond to right mouse up, or events relating to the middle button, can subclass musalt_. When musalt_ is called, read the low-level mouse event. Its type then needs to be checked and types that you're not interested in can be ignored.

It takes extra work to read the mouse event, check its type, and branch based on what type it is. This work is unnecessary when, say, the musdclik_ method is called. When that method is called you know that the current mouse event is a left double click. And you only subclass musdclik_ if you have a specific reason to handle that event. The musalt_ method is a tradeoff; it's more difficult to process rare event types, but it saves memory in every class.

Node Methods

Method Description Offset
addchild_ Add child node 40
unparent_ Remove THIS from its parent node 43

Add child node (addchild_)

Input Description
RegPtr Child node to add to this node
Output Description
- None

The user interface hierarchy is established by the node properties of TKView. Every TKView has a parent, child and sibling pointer. Every node, except the root node, has one parent. A node may have one or more child nodes, but has only one child property. The child pointer is to the parent's first child. The way that parent is related to its second child is via its first child's sibling pointer.

Node tree pointer property relationships.
Node tree pointer property relationships

The tree can be built by calling the addchild_ method on a node, (i.e., a TKView,) and passing a RegPtr to the child node. The child node can be any TKView or subclass of TKView. The addchild_ method handles establishing all of the node property pointers. For example, if the node passed in is the first child, this.child is updated to point at the child, and the child.parent is updated to point at this node. If this is a second, third, or Nth child, the first child is looked up and its sibling pointers are followed to find the last child. The node passed in is connected via the sibling pointer of that node, and the child.parent is set to this node.

Subclassing addchild_ is useful when the class wants to limit or keep track of when and how many children are being added. For example, a TKSplit only supports two children. If a third child is attempted to be added it raises an exception. After verifying that another child is allowed to be added, or some other check such as verifying that the child is of an appropriate class, the actual work of manipulating the node pointers can still be performed by calling the superclass addchild_ method.

Remove THIS from its parent node (unparent_)

Input Description
- None
Output Description
- None

It is possible to reorganized the user interface's node tree at runtime. A node can be removed from its parent node and then added as the child of a different parent. The relationships between a node and its own children are unaffected when the node is removed from its parent. In this way an entire branch of the node tree can be moved. This could be used, for example, to reverse the order of the two sides of a TKSplit, by removing both children and then adding them back in the reverse order.

The process of removing a node from its parent is called unparenting. The unparent_ method is called on the node you want to remove from its parent. All of the node pointers are updated accordingly. If this node was in the middle of a sibling chain, the previous sibling's sibling pointer is first updated to this node's sibling pointer. And if this node was the parent's first child, then the parent's child pointer is updated to what was this node's sibling.

There is a check when calling unparent_, if the node has no parent then nothing happens. There are no checks, however, when calling addchild_. It is very important that you not add one node as the child of multiple parents, or unexpected things will happen and a crash or an infinite loop will probably follow. If a node is already attached to the node tree, call unparent_ before adding it with addchild_ to a different place in the node tree.

Sizing Methods

Method Description Offset
resize_ Resize Node 46
contsz_ Get Content Size 49

Resize Node (resize_)

The resize_ method resizing the current node relative to its parent node while taking into consideration its anchoring, offset, and resize mask properties. Resizing is done automatically as part of the Toolkit update cycle. You should never manually call resize_ on any node.

Subclassing resize_ is useful for creating custom container classes.

Get Content Size (contsz_)

The contsz_ method is called when a container class needs to know the size of its content class. You should have no reason to manually call this method. It is called by other classes on their own child, usually to adjust scroll bar representations of the size of the content.

Display Methods

Method Description Offset
update_ Update computed properties 52
draw_ Draw the view's appearance 55

Update computed properties (update_)

The update_ method is called automatically during the Toolkit update cycle. You should never call the update_ method manually. This method handles updating computed properties, and recursively traverses the visible node tree.

For example, in order to save time, if a node in the tree is out of bounds or not visible when its parent is resized the resizing logic on that branch of the tree is skipped. When this branch of the tree later becomes visible, or if its parent's bounds or scroll offsets are adjusted, the new bounds have to be computed and deferred resizing may have to be applied. This is performed by update_ and it refers to the object's modified flags (mflags) property to determine what work needs to be done.

Draw the view's appearance (draw_)

The draw_ method is called automatically during the Toolkit draw cycle. You should never call the draw_ method manually. When the draw_ method gets called, the appropriate draw context has already been configured.

If an object's appearence changes and it needs to be redrawn, the df_dirty flag must be set on the TKView's display flags (dflags) property. Additionally, the tf_dirty flag must be set on the Toolkit environment's flags (te_flags) property. The global dirty flag on the Toolkit environment is necessary to inform the Toolkit update cycle that something within the view hierarchy needs to be updated and drawn. Recursively searching the view hierarchy for a node in need of servicing is expensive, and so it is only performed when the global tf_dirty flag is set on the environment.

TKView's draw_ method performs the important task of determining which of its own children are visible and inbounds, and then configuring the draw context for each child and calling each child's draw_ method. This process is recursive.

The draw_ method is usually reimplemented by a subclass to draw its custom appearance. However, if the subclass supports child views, it is highly recommended to call the superclass draw_ method to handle drawing those children, rather than reimplementing the complex logic provided by TKView.

Event Methods

Method Description Offset
hittest_ Mouse Event Hit Testing 58

Mouse Event Hit Testing (hittest_)

Hit testing is the procedure by which a low-level mouse event is mapped on to the physical layout of the hierarchical user interface. You should never need to call hittest_ manually. When certain initializing mouse events occur, such as a wheel event or a left mouse down event, hittest_ is called on the root view by a Toolkit KERNAL routine.

The low-level event's pixel coordinates are converted to row/column coordinates with mouserc. These are then normalized to the Toolkit environment's offset on the screen, using its te_posx and te_posy properties. These coordinates are then checked to see if they are overtop of the root view. If they are, the coordinates are saved to the root view's hitrow and hitcol properties.

The hittest_ method of the root view then checks each of its child views for visibility and in bounds, and if the child is under the coordinates of the hit, it renormalizes the event coordinates for the child's offset and calls the hittest_ method on that child view. The new renormalized coordinates are saved on that view's hitrow and hitcol property. This process continues recursively until the last hit child is found. The recursion unrolls returning a pointer to the hit view. The pointer to the hit view is saved to the Toolkit environment's first mouse view (te_fmusv) property.

Only some event types initiate a hit test procedure. For example, a mouse move event and a mouse click event do not get routed to the view above which the mouse pointer was positioned, but are sent to the Toolkit environment's first mouse view instead. Although this may seem unintuitive, the resultant behavior is much more natural than if hit testing were performed for every event type. This allows you, for example, to mouse down on a scroll bar's nub and then drag the mouse up and down, and the nub continues to track the mouse's vertical position even when the pointer is no longer above the scroll bar view.

To track the event with pixel precision, the low-level mouse event can be fetched with readmouse. Its least significant bits can be consulted to get the exact pixel offset within the renormalized row/column cell coordinates that are found in the hitrow/hitcol properties of the view.

The Accepts First Mouse (df_afmus) flag of TKView's display flags (dflags) property is used by hittest_ to determine whether a TKView is sensitive to mouse events. By unsetting its df_afmus flag, the view (and consequently all of its child views) become transparent to mouse events. df_afmus is set by default when a TKView is initialized.


Object Definition

//os/tk/s/:tkview.s

Object Size: 39 (+3) bytes

Responder Properties

Property Description Size Offset
nextresp Next Responder 2 2

Next Responder (nextresp)

By default this property is initialized to null. Key events are propagated to the next responder if it is set. Otherwise they are propagated to the parent node.

You do typically need get or set this property manually. It is used for forming complex event propagation relationships between closely collaborating classes, such as a TKScroll view and its nested TKSBar controls

Node Properties

Property Description Size Offset
parent Parent Node 2 4
child First Child Node 2 6
sibling Next Sibling Node 2 8
Property Description Size Offset
tag Identifying Tag 1 10

Parent Node (parent)

This property is set when this object is added to the node tree by passing a pointer to it when calling the addchild_ method of the object that is to become this nodes parent.

It can be useful to read the parent property when you have a pointer to a node but want to get a relative reference to its parent node.

First Child Node (child)

This property is set the first time the addchild_ method is called on a node. The pointer to the child node is saved to the child property.

It can be useful to read the child property when you have a pointer to a node but want to get a relative reference to its first child node.

Next Sibling Node (sibling)

This property is set when this object acquires its first new sibling. When a node is passed to the addchild_ method of this node's parent, and this node is currently the last sibling in the sibling chain, then this node's sibling property is set to the new sibling.

The sibling property is useful for counting how many children a node has, or for finding the Nth or last child of a node. Finding a node's first child is performed by reading its child property. To find it's second child you would read the first child's sibling property. To find the last child, continue to follow the sibling pointers until you reach a node whose sibling pointer is null.

Identifying Tag (tag)

The tag property is a convenient way to identify a node. It is very open and undefined and can be put to any creative use.

One example of its possible use is when two or more objects share a callback. It is often easier to read the tag from the this object than it is to try to identify the object by its this pointer. The callback can then do different things depending on the tag's value.

Another common use is to find a view somewhere in the view hierarchy by its tag. This can be done with viewwtag. The View With Tag routine only searches from the start node down. To search the entire tree the root view can be passed as the start node. However, tags can be reused, the same tag found on more than one object, and View With Tag can still be used to find it, by starting somewhere other than the root node.

Sizing Properties

Property Description Size Offset
offtop Offset Top 2 11
offbot Offset Bottom 2 13
absbot Absolute Bottom 2 15
height Height 2 17
Property Description Size Offset
offleft Offset Left 2 19
offrght Offset Right 2 21
absrght Absolute Right 2 23
width Width 2 25
Property Description Size Offset
rsmask Resize Mask 1 27

The sizing properties are used during the Toolkit update cycle and adjusted by the object's resize_ method to dynamically change the position and size of the view relative to its parent view. These properties are used again prior to the object's draw_ method to configure the draw context. The draw_ method can read these properties to help it decide how to draw itself. Alternatively the draw_ method can simply start outputting its appearance using the standard context drawing KERNAL routines and allow the context to figure out where those characters end up on the screen. The context automatically clips the output and provides feedback to the draw routine about, for example, when further output to the current row or column will no longer have any effect on the screen. This feedback can help make the draw_ method more efficient.

Resize Mask (rsmask)

The resize mask is a set of bits which determine how a view gets resized when its parent view gets resized. These are its top, buttom, left and right anchor bits (rm_ankt, rm_ankb, rm_ankl, and rm_ankr) defined by //os/s/:toolkit.s. The resize mask has one additional bit, resize children (rm_rschd). If the resize children bit is clear, then when a view's resize_ method is called, it does not recursively call the resize_ method on any of its children.

A container view has two broad conceptual layout modes: constrained and unconstrained. How a container's children are anchored and positioned within it depends on whether it is meant to be constrained or unconstrained. Although it is possible to configure different child views of the same parent using both of these broad conceptual modes, the result is unproductive and could lead to glitches in the layout, hit testing, drawing or all three.

Constrained Layout

A constrained layout is when a container has a fixed set of child views, with a fixed relationship to one another but a flexible size. When the container is resized the size and position of the child views react, becoming either larger or smaller themselves to fit the space.

For example, imagine you have a user interface that has a list with two buttons below it. One button on the left and another on the right. When the container view is resized, there will still be a list at the top with two buttons below, one on the left and one on the right. However, the list will get bigger or smaller in both dimensions, the buttons will stick to the bottom getting closer or further from the top, and the buttons will stay the same width but will get closer or further apart. See the following diagram.

Example of a constrained layout.
Example of a constrained layout

In this "constrained" layout, the list (blue) is anchored to the top, bottom, left and right. But its bottom edge is offset from the edge of its parent by some number of rows to make room for the buttons. When the container (yellow) is resized the height and width properties of the list are recomputed dynamically, as is the absolute bottom.

The left button (green) is anchored bottom and left, and it has a fixed width. When the container (yellow) is resized, its offset top and its absolute right are recomputed dynamically. The right button (purple) is anchored bottom and right, and it too has a fixed width. When the container (yellow) is resized, its offset top and its offset left are computed dynamically. In other words, the way that a view is anchored determines which of its other properties are dynamically computed when its parent is resized.

In a constrained layout, views with a fixed height or width should be anchored to the top or bottom but not both, or anchored to the left or right but not both. Any view that should flex in a given dimension should be anchored to both sides of that dimension, but can have offsets to make room for something fixed to be positioned above, below or to the side.

TKView does not have the ability to dynamically resize two views in proportion to one another. For example, TKView cannot have one child that is 33% of its width and another child view beside it that is 66% of its width, such that as the container is resized the children maintain this ratio. If this were required, it could be accomplished with a custom subclass of TKView.

Unconstrained Layout

An unconstrained layout is when a container has one or more child views which either stack up vertically, or across horizontally, or both. When the container is resized, the child views maintain their size and position but may overflow the visible bounds of the container.

For example, imagine a container that holds a label next to an input field. Below that in the stack comes another label and another input field. Below that perhaps comes a set of checkboxes each with a label. Then below that perhaps a multi line text area with a button below it. This layout is called unconstrained, because the number of child views and how much space they occupy is not constrained by the size of the containing view. See the following diagram.

Example of an unconstrained layout.
Example of an unconstrained layout

In this "unconstrained" layout, the container (yellow) has 4 child views (blue) which are much larger than itself. The child views extend out horizontally and vertically past the visible bounds of the container and into a virtual space (grey) that may in fact be much larger than the screen.

The child views of a container in an unconstrained layout are typically always anchored top and left, each with a fixed height and width. Each child view's offset top is used to stack them one after the next, vertically.

If the content size (contsz_) method is called on the container, TKView checks the sizes and positions of all of its visible children, and computes the size of the grey rectangle dynamically so that it minimally fits all of the children and then returns that as its content size.

Calling the content size (contsz_) method on a container with a constrained layout, on the other hand, will always return a size equal to the container's own current size, because the nature of a constrained layout is that all of the children resize themselves to fit within their container.

Typically a container with an unconstrained layout will be set as the content view a TKScroll view. The TKScroll view calls contsz_ and adjusts its scroll bars to allow the user to move that large virtual grey square around so that different parts of it are visible through the smaller area of the container.

Mixing Layout Concepts

In most practical user interfaces constrained and unconstrained layouts are combined together. In the diagram showing the example constrained layout, above, the list (blue) itself is a kind of unconstrained layout. The list may have hundreds of items each of which is stacked one after the other. The list is typically added to a TKScroll view, so the full content of a long list can be viewed. The TKScroll view is anchored top, bottom, left and right in its container, but the TKList itself is only anchored top and left within the TKScroll.

Less common, although entirely possible, is to treat one of the child views of an unconstrained layout as itself the container of a constrained layout.

There is a way of mixing layouts that does not work and will produce erroneous calculations and glitchy drawing. Imagine a container with an unconstrained layout, with many child views stacked up vertically which push past the visible vertical height of the container. To then add another child to that container and anchor the child to the bottom, is invalid. Although it might make some conceptual sense, TKView cannot compute its size or position properly.

Lastly, a TKView may validly mix layout concepts in two different dimensions. For example, a TKView may have a constrained layout horizontally, with children that are anchored left and right and resize to fit the available horizontal space without overflowing, and at the same time have an unconstrained layout vertically. A typical use case for this is a form with a large set of controls that each have a fixed vertical height that are stacked one after the next, down and off the bottom edge of the container view, but which horizontally are anchored left and right so they all dynamically fit the container's width.

This mix of constrained and unconstrained will also typically be embedded in a TKScroll view. It is possible to enable only one scrollbar to handle the unconstrained dimension. When the TKScroll calls the container's contsz_ method, it will correctly compute that the content width is the current width of the TKView, and the content height will be computed to contain all of of the children.

Scrolling Properties

Property Description Size Offset
s_top Scroll Top Offset 2 28
s_left Scroll Left Offset 2 30

Every view's visible rectangle is a view port into large virtual space. The scroll properties define where inside that virtual space the view's visible rectangle is oriented. This is accomplished by the s_top and s_left properties being set into the draw context for the current view prior to its draw_ method being called.

When the view draws using the draw context it sets the local row and column of where to start drawing. This coordinate is automatically computed relative to the draw context's scroll offsets. In a subclass of TKView that handles drawing large content, such as TKList, the s_top property is used to determine the index of the top visible list item. The view can draw more efficiently by only starting to draw from the currently visible content.

When TKView has multiple children, it consults its own s_top and s_left properties to determine which of its children are within its visible bounds. Anything outside its visible bounds gets flagged for requiring updates, such as resizes, but the work is deferred until those children are scrolled into the visible area.

The TKScroll view and its TKSBar controls are typically used to manage the s_top and s_left properties of the TKScroll's content view. However, it is also possible to programmatically adjust the scroll properties. If the scroll properties are adjusted manually, it is necessary to set the bounds check bit (mf_bdchk) of the view's modified flags (mflags.) This informs TKView that it needs to perform a bounds check on all of its child views.

Drawing Properties

Property Description Size Offset
dflags Display Flags 1 32
mflags Modified Flags 1 33
bcolor Background Color 1 34

Display Flags (dflags)

The display flags property holds a set of 8 bit flags. These are mainly used to assist in drawing the view, but also have role in event processing.

Constant Value Note
df_dirty %0000 0001 Flags the view to be redrawn
df_sized %0000 0010 Indicates that the view's sizing properties are up to date
df_opaqu %0000 0100 TKView's draw_ method performs a context clear before redrawing
df_afkey %0000 1000 The view accepts first key status
df_afmus %0001 0000 The view accepts processes and propagates mouse events
df_first %0010 0000 The view is the first key view
df_ibnds %0100 0000 The view is inside the visible bounds of its parent
df_visib %1000 0000 The view is visible

The most common flag that needs to be set manually is df_dirty. If any property that affects drawing is manually changed, df_dirty needs to be set (along with the Toolkit environment's te_flags tf_dirty flag) in order for the view to have its draw_ method called on the next draw cycle.

df_opaqu is typically disable, but if the children of a TKView do not completely cover its visible area, and it does not have an opaque ancestor, then it's df_opaqu flag may need to be set to prevent a visual ghosting.

df_afkey is typically disabled. Custom subclasses of TKView which are capable of handling key events should enable this flag.

df_afmus is enabled by default so that this view participates in event propagation. There are certain circumstances under which you may want a view and its children to ignore mouse events. That can be accomplished by enabling this flag.

df_first is set if this view is currently the first key view. Some subclasses, such as TKInput, modify their appearance when this flag is set. This allows the text field in focus to stand out amoung a set of other text fields. Key events are automatically routed first to the view with this flag set. You should never manually set this flag. To affect this flag, call the setfirst_ method.

The df_visib flag determines the visibility of the view. If this flag is unset the view will not be drawn and it will not participate in mouse or key event handling. Sizing and bounds checking are deferred until the view becomes visible again.

Lastly, the df_ibnds and df_sized flags are computed internally and should not be adjusted manually.

Modified Flags (mflags)

The modified flags property holds special flags that are used to indicate when resizing and bounds checking need to be performed on a view. If a parent view is scrolled, it recursively calls bounds check on each of its children. However, if one of its children is not visible, the bounds check does not recurse into that branch of the view hierarchy. Instead the mf_bdchk flag is set on the mflags property.

If a parent view is resized, it recursively calls resize_ on each of its children. However, if one of its children is either invisible or out of bounds, the resize does not recurse into that branch of the view hierarchy. Instead the mf_resiz flag is set.

When a view becomes visible, and one of its modified flags is set, the bounds check or resize is performed just prior to redraw during the update cycle. It is possible that a view which becomes visible itself has an invisible child view. In that case, the bounds or size check is performed on it, but the modified flags are set again on its own invisible child.

If any of a view's sizing properties are manually modified, its resize (mf_resiz) flag should be set on the modified flags (mflags) property.

If a view's scroll properties are manually modified, it's bounds check (mf_bdchk) flag should be set on the modified flags (mflags) property.

Hit Test Properties

Property Description Size Offset
hitrow Hit Row 2 35
hitcol Hit Column 2 37

The hitrow and hitcol properties can be read to get the coordinates of a mouse event resulting from the last hit test. These properties have been normalized to the coordinates of this view. Custom subclasses of TKView can use these properties to determine where within the view the event hit.

For example, when a standard TKButton is clicked, where the click occured within the button is not important. However, a subclass that draws itself as a stepper control (up and down arrows beside a value) may ignore events that happen over the value and perform different behaviors if the event is over the up or the down arrow.

Relationships

Inherits from: TKObj

Parent Section: Class Reference

Next Section: Subclassing


Next Chapter: Writing an Application

Table of Contents



This document is subject to revision updates.

Last modified: Jul 02, 2024