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: TKSBar:TKCtrl:TKView:TKObj

Overview

TKSBar is a concrete subclass of TKCtrl. It is a fairly complex class with a lot of behavior, but its configurability is limited to horizontal or vertical.

A TKSBar object is a scroll bar which consists of a striped background track, a solid scroll bar nub which is proportionally sized to visually represent the length of the scrollable content, and two buttons that come together at one end. In a vertical scroll bar the buttons are up and down and appear together below the scroll track. In a horizontal scroll bar the buttons are left and right and appear together to the right of the scroll track.

A scroll bar is rarely if ever instantiated manually. It is typically paired with a TKScroll object which performs the work of allocating, initializing and appending the TKSBar into the view hierarchy. It is only necessary to work with a TKSBar directly if you are implementing your own kind of scrolling class, but even in that case, you could profitably subclass TKScroll and let it handle the creation and set up of its scroll bars.


Basic navigation with a scroll bar is as follows:

The nub may be dragged to scroll long content quickly but roughly. The track can be clicked above or below the nub to scroll the content by exactly one page. Page length is defined dynamically as the number of visible content rows minus one. Or if it's a horizontal scroll bar a "page" is the number of visible content columns minus one. The scroll buttons can be clicked to scroll the content 4 rows (or 4 columns) at a time.

There are several advanced navigation options:

Click and hold on the track above or below the nub to scroll continuously in page-sized incremements. Click and hold on the up/down or left/right buttons to scroll continuously in 4 row (or 4 column) increments. Holding LEFT-SHIFT while clicking the up/down or left/right buttons slows down the scroll speed but increases the precision, by scrolling the content only one line at a time instead of 4. LEFT-SHIFT can also be used to continuously scroll with single-line precision. Hold the COMMODORE key and click the up, down, left or right button to scroll the content all the way to that end in one step.

The mouse wheel can be rolled over a TKSBar to scroll its content. Hold the COMMODORE key while rolling the wheel jumps the content to the start or end in one step. When the mouse wheel is rolled over a TKScroll object which is coordinating with one or more scroll bars, the wheel events are routed to the vertical scroll bar, if one exists.

Subclassing notes

TKSBar is a very complicated and specific class. Subclassing it is possible but practically speaking it is unlikely to be necessary.

Class Definition

//os/tk/h/:tksbar.h

Subclass Method Overrides

Init (init_)

During initialization, TKSBar is configured as a continuous control, the cf_cont flag is set on the cflags property. The repeat timer (rtvalu) is set to 3, which 1/20th of a second. The valtype is configured as a 2-byte integer (or a 16-bit word). This allows scroll bars to scroll through up to 65,536 rows or columns of content.

The orientation of the scroll bar is passed to the init_ routine in the accumulator. This sets the orient property and also affects the initial sizing and anchoring of the scroll bar.

Horizontal and vertical constants are not defined, but there is a note about them in the //os/tk/s/:tksbar.s header. Horizontal is 0 and and vertical is 1. This can be remembered by the mnemonic that "1" is a tall and narrow symbol, corresponding with the tall and narrow layout of the vertical scroll bar.

ldy #init_
jsr getmethod
lda #1 ;tall and narrow = vertical
jsr sysjmp
Scroll bars, vertical and horizontal, enabled and disabled.
Scroll bars, vertical and horizontal, enabled and disabled.

Left Mouse Down (musdown_)

Mouse down performs a complex hit testing procedure to determine which part of the scroll bar has been hit; the track before the nub (0), the nub (1), the track after the nub (2), the up or left button (3), the down or right button (4). If the hit part is the nub or either of the two buttons (1, 3 or 4) it sets the cf_hilit flag on the cflags property. Clicking the track, either above or below the nub, does not highlight any part of the scroll bar.

The hit part, nub pixel size, original mouse position and original scroll offset are recorded on class properties to assist with dragging and continuous firing calculations.

Mouse Moved (musmovd_)

Low-level left mouse tracking events are converted into calls to the musmovd_ method on TKSBar instances. The hit part from left mouse down is consulted. If the hit part is not the nub (1), only the superclass version of this method is called. If the hit part was the nub (1), then a complex set of calculations are carried out to determine the distance scrolled and compute the new position of the scroll nub which is updated as the nub offset (noboff) property.

The send action sendact_ method is called on this every time the scroll nub is dragged.

Left Mouse Up (musup_)

On mouse up the cf_hilit flag on the cflags property is cleared so the scroll bar draws in its normal state again.

Left Mouse Click (musclik_)

If the cf_disab bit of the scroll bar's cflags property is set then a click does nothing. The superclass method is called and no other custom behaviors of TKSBar occur.

The hit part from mouse down is consulted. The low-level mouse modifier flags (musmods) is checked for the mus_cbm flag to perform a scroll jump, or the mus_shft flag to set the decrement to 1. Otherwise, the decrement is set to 4. The nub position is recalculated, the scroll position (the value property) is updated, and the sendact_ method is called.

Resize (resize_)

When a scroll bar is resized, it calls an internal recalc routine which performs a complex recalculation of all the computed properties:

  • scrollable lines (scrlns)
  • nub size (nubsz)
  • nub movable lines (nublns)
  • nub offset (nuboff)
  • page size (pagesz)

Draw (draw_)

The draw method of TKSBar takes the orientation into consideration. It also takes the cf_hilit and cf_disab flags on the cflags property into consideration. Finally, it takes the orient property into consideration.

The track and buttons are redrawn first. Then the size and position of the nub is used to redraw it over the track. If the cf_hilit flag is set, the appropriate segment of the scroll bar is drawn with the selected color.

Control Methods

Method Description Offset
sendact_ Send the action to the parent view 64

Send the action to the parent view (sendact_)

The nub's offset is computed first. And then the superclass's sendact_ method is called. When TKScroll instantiates the a TKSBar it assigns itself as the target. Thus, sendact_ targets the coordinating object, but it is the responsibility of the coordinating object to set itself as the target.

The action method called on the target is adjust_. It is therefore necessary that the coordinating object conforms to the class methods TKScroll, insofar as having an adjust_ method at the same method offset. This would automatically be the case for any subclass of TKScroll.

Scroll Bar Methods

Method Description Offset
reflect_ Reflect content view's scroll offset 79
recalc_ Recalculate computed properties 82

Reflect content view's scroll offset (reflect_)

The reflect_ method is called when the coordinating class changes the scroll offsets of its content view.

For example, TKScroll supports keyboard commands to scroll and page through its content. After changing the scroll offsets of its content view it has to call reflect_ on its own TKSBar objects. This method then retrieves a reference to that content view by following the pointers to its parent and then to the parent's ctntview property.

This makes it a requirement that any coordinating class that embeds a TKSBar must conform the TKScroll class's object definition, insofar as having a pointer to its content view at the same object property offset. This would automatically be the case for any subclass of TKScroll.

reflect_ potentially moves the position of the scroll nub, but does not recalculate the scroll nub's size.

Recalculate computed properties (recalc_)

The recalc_ method recalculates all of the computed properties:

  • scrollable lines (scrlns)
  • nub size (nubsz)
  • nub movable lines (nublns)
  • nub offset (nuboff)
  • page size (pagesz)

This is called automatically by the TKSBar's resize_ method. If the size of the content changes, the size of the nub and related properties have to be recalculated. This can be performed either by calling recalc_ directly, or by invalidating the size of the coordinating parent class, which will force a resize_ method call, which indirectly calls recalc_.

This is handled by the coordinating class, TKScroll. If you intend to implement an alternative to TKScroll it is necessary to understand how resize_ works and when to call it. When only the size of the content to be scrolled changes, the size of the TKSBar does not change. The scroll offset of the nub also does not necessarily change, for example, if the scroll offset is zero, the nub will remain at the top or left of the track. However, the size of the nub will change, and the distance the content will be scrolled relative to the distance that the scroll nub is moved will change. The numbers necessary to make these calculations correct are updated when recalc_ is called.


Object Definition

//os/tk/s/:tksbar.s

Object Size: 65 (+3) bytes

Display Properties

Property Description Size Offset
orient Orientation 1 54

Orientation (orient)

During initialization orient is set from the value passed in the accumulator.

This property cannot be changed in isolation. Anchoring properties are set during init_ that correspond to the orient property. These associated properties would have to be changed manually if the orient property were ever changed.

In practice, the TKScroll class deletes and recreates TKSBar objects from scratch when its setbar_ method is called.

The values that this property can have are not defined as constants.

Constant Value Notes
0 Horizontal
1 Vertical

Computed Properties

Property Description Size Offset
scrlns Scrollable Lines 2 55
nubsz Nub Size 2 57
nublns Nub Movable Lines 2 59
nuboff Nub Offset 2 61
pagesz Page Size 2 63

None of the computed properties should ever by manually changed. These should be considered either private, or read-only.

Modifying one of these properties to anything other than the value it is set to after calling recalc_ would result in improper display or improper behavior and could in theory lead to crash or a lockup by infinite loop.

Relationships

Inherits from: TKCtrl

Parent Section: Class Reference

Next Section: Subclassing


Next Chapter: Writing an Application

Table of Contents



This document is subject to revision updates.

Last modified: Nov 21, 2024