This document specifies the current API for
managed windows in
My own OS. The root document is
My
Own System Application Program Interface.
I originally defined the FormDoc widgit for displaying structured text in BibleTrans, then expanded the definition to do graphical data presentation in ShoImage, then moved the structured text part out of the kernel API, leaving only the graphical part. Hence these two widgits:
class FormDoc extends Widgit { // resource-based formatted document
File ResFi, ActFi; // an open resource file, plus an alternate
Char4 AcImPro; // an alternate process ID that owns this window
int LineHi, HotHit; // scroll increment (line height); hilite element in HotSpots
int imTall, imWide; // image height and width
IntArray HotSpots;}~FormDocclass ShoImage extends FormDoc { // user formatted image doc
IntArray imImage, imIcons;
int LineWi, ImSelec;}~ShoImage
The imImage array is a sequence
of drawing instructions, typically one integer each. The high four bits
specifies the operation, and the remaining bits are parameters. Vertical
and horizontal coordinates are specified as 16 bits vertical, 12 bits (max
4095) horizontal. The image has some state associated with it, so you give
it a current location, then do something there, possibly moving to a new
current location. These operations are specified (others may be added later):
0,0,0 -- DoneFollowing a "New location" operation, a sequence of "Line to" operations can be used to chain lines together into arbitrary polygons. The "Fill rectangle" operation keeps the current location as its top-left. Pixels (rectangles and icons) are drawn down and to the right of the current location, but text treats the current position as a baseline. Text (and lines) advance the location to the end (see also font data format below).
2,v,h -- New location
0,v,h -- Fill rectangle (height>0,width>0)
3,v,h -- Line to, new location at end
1,n,f,c; text -- Set color + font, show text
4,name -- Named icon name
6,n,c; pixels -- Set color, show pixels
7,v,h; pixels -- Copy pixels
The "Named icon" uses a Char4 name filling the whole word, so only icons whose names begin with a capital letter (0x40-0x5F) can be used. The icons will be those defined in the system as extended by subclassing IconFontFetch, or else resources in the ResFi file and listed in the (now deprecated) imIcons array. The icons themselves are drawing operations, usually just "show pixels" operations for each layer of color, preceded by a height+width word.
There are a number of defined functions for building visual elements in this model. Each of these takes the array theImg being built (which must already be large enough), a current offset offs in that array, the parameters of the visual element being added, and returns the new offset. The here parameter is expected to be in the defined V*4096+H format:
int ImagText(String theTx, int nc, int offs, int here, IntArray
theImg,
int FontNo, int colo);
int ImagIcon(Char4 theIc, int here, int offs, IntArray theImg);
int ImagLineTo(int here, int thar, int colo, int offs, IntArray
theImg);
int ImagFillRec(int here, int dims, int colo, int offs, IntArray
theImg);
int ImgFrameRec(int here, int dims, int colo, int offs, IntArray
theImg);
int ImgBevelFrame(int here, int dims, int offs, IntArray theImg);
int ImagPushBtn(String theTx, int wide, boolean hili, int offs,
int here,
IntArray theImg);
int AddHotRec(IntArray theHots, int hotx, int msg, int info,
int tpl, int szr);
ImgBevelFrame builds a light/dark gray outline suitable for "3D-look" buttons as drawn by ImagPushBtn. Pushbuttons in particular need to be keyed to hotspots in the HotSpots (theHots) array; these can be added easily using the AddHotRec call. Each hotspot is defined by four numbers in the array, a msg (which should be a valid Char4 value, as it will be the event message sent when the hotspot is clicked), an additional info value (sent as EvInfo in the same message), a top/left tpl and size szr (two 16-bit numbers each). This function stores the four numbers in the array beginning at offset hotx, and returns the offset (hotx+4) to be used in the next call. You can also add your own drawing commands with these very-low-level commands to insert one or two arbitrary numbers into the array and return the new offset:
int ImagInt(int info, int offs, IntArray theImg);
int Imag2ints(int whom, int info, int offs, IntArray theImg);
These are low-level support operations. At a higher level, class ImDocWinBase provides a number of window management services, including drawing the items and processing events.
class ImDocWinBase { // base class for MoDialog & PrefsWinIt is expected you will override most of these methods to provide desired functionality; the base class constructor will produce an error if you attempt to instantiate it other than as a subclass. This is already done in class ImageWinMgr, which can be used for modal dialogs and/or a single (non-modal) preference or dashboard window.
Window theWin; // FormWinStuff wants this first for PoorManConst'r
int theDocID; // EzTxWindo wants these 3 early for ditto..
String myWnTitle;
int FiSeqNo; // = "DocX"/"Imag" if not BigTextEd
FormDoc theWgt;
boolean Logging;
int theTint; // 1: red, 2: green, 3: yellow, 4: blue, 5: purple, 6: teal
Process theOwnerProc;
ImDocWinBase theLink; // in ImDocWinListvoid CheapConstor(int docno, String theTxt, int fino);
void SetNewLnN(int here, int datum);
boolean KeyPress(int theKey);
void Mousing(int whom, int now, Point WnPt);
void ShowMyWindow();
void ActivateWin(int info);
void MoveSize(int here, int size, boolean sho);
void ForceRe4m();
void SetWinKin(boolean sho, Char4 whom, int DocID, int noscro);
void CloSaveWin();
boolean DoDocEvent(Event theEv);}~ImDocWinBase
MoDialog contains its own event loop, and returns only when the dialog is dismissed by the arrival of one of the events "Done" or "Quit" or "CloW" or "OK " or "Canc" (all of which return true, except "Canc"). NewPrefsWin takes the same parameters, but its window is non-modal (noTi is true if you want no titlebar on your window); it returns true if the window failed to open for some reason. From your own event loop you must offer all events to IsPrefsWinEvent, which will return true if the preferences window has handled it. You are expected to override the default operation of some events -- and in the case of a modal dialog, you must do so to recover any user interaction other than "OK" or "Cancel" -- using the ImageItems callback class:
class ImageItems {At the very least you need to override DoItmEvent, which gives you first crack at the events processed within this window. You would use this to process button presses and also any data in data entry fields. You can also use it to completely reformat the window, if desired. In that case, you should call FreshDraw with a new parameter string from within your DoItmEvent handler. If that is not convenient, you can set theParams directly, then send a "FrDr" event to the containing window.
IntArray KeyCodeEvts; // holds KeyC items for MoDialog
String theParams;
boolean NeedRedraw; // set true, then call PrepEvent() to redraw
ImDocWinBase myOwner; // set by ImageWinMgr.Initializeint EstSize(int topLft, int HiWi, int info) { // callback for User items
return 0;}~EstSize // size estimate >= actual image elts needed;
// HiWord >= # hotspots needed, =0 if none
int DrawMe(IntArray theImg, int offs, int topLft, int HiWi, int info,
IntArray theHots, int hotx, boolean hili) { // callback for User items
return offs;}~DrawMe // offs+size used (as from ImagFillRec etc)
// if added to theHots, return Pack2ints(hotx,offs)
boolean DoItmEvent(Event theEv) {return false;}~DoItmEvent // true if took
// call FreshDraw from within DoItmEvent if redraw needed..
void FreshDraw(String newPrams);}~ImageItems
kind,V,H[,tall,wide][,color][,font][,info][,text]where the items in brackets are part of only some of the specifications. The kind is nominally a Char4 label, but only the first letter is significant. In some cases, the remainder of the kind word is used to distinguish between separate buttons or controls during event processing. The color, if specified, is a number representing the one-byte color code as above, or else a triple "RnGnBn" where "n" after its respective letter is a digit representing that color component's value from 0-5. The font, if specified, is a number from 0-7, one of the eight fonts listed in Graphics Operations. Any specified text comprises the remainder of its line, possibly including commas (but not tabs, which cannot be displayed anyway). The "just" specification of text may be centered (V and/or H) or (R) right-justified; the default is left. These 17 display elements are defined:
Fill,V,H,tall,wide,colorThe text component of a popup menu is a comma-delimited list of items, and sele is a 0-base number designating which one is displayed in the unpopped state. You would normally use a parameter item to supply this number. The hili item of a button should be 0; MOS internally replaces it with a 1 while the button is being clicked, but that only works correctly if the kind word on that line is unique. The msg4 item should be a 4-letter event name that your application catches in your DoDocEvent handler. Checkboxes and radio buttons are be managed using a private array of 256 numbered bits, each selected by num. Your program can turn the bits on or off, or query their state using these functions:
Line,V,H,V,H,color -- start,end 1-pixel line
OutL,V,H,tall,wide,color -- 1-pixel rectangle frame
Text,V,H,tall,wide,color,font,just,text -- text display
Ntry,V,H,tall,wide,color,font,just,text -- text entry
Butn,V,H,tall,wide,font,msg4,num,hili,text -- hili: =1 if pressed
Chek,V,H,msg4,num,text
RadB,V,H,msg4,num,text
Grup,V,H,tall,wide -- depressed bevel frame (max nest: 8)
EndG -- items after Grup, before EndG: V,H relative
PopM,V,H,tall,wide,color,font,msg4,sele,text -- sele: sel'd item from text, 0=1st
Icon,V,H,name -- only predef'd for now
Xime,V,H,color -- 32x32 clock icon, real time in light grey
Move,V,H -- drag icon for dragging the win
User,V,H,tall,wide,info -- subclass ImageItems for access
Hots,V,H,tall,wide,msg4,num -- transparent button
KeyC,key,msg4,num -- KeyC=key input posts msg4+msUp
CheckRadioBit(int whom, boolean set); // set bit whom to true or falseThe following built-in icons are available at this time, but you can extend this list by subclassing IconFontFetch:
boolean RadioCheckBit(int whom); // return current setting of bit whom
"Smi!" -- a small "smiley" faceThe Xime line makes sure the time is kept current by sending (and processing) periodic "Clok" events. The Move line displays the "MovI" icon, then if it is clicked, drags the whole window around to follow the mouse. This is useful for borderless (no title) windows that you want the user to be able to reposition.
"Bult" -- a small black dot useful as a bullet
"Maro" -- the small arrow in a popup menu
"ChkF" -- a checkbox in the off state
"ChkN" -- a checkbox in the on state
"RadF" -- a radio button in the off state
"RadN" -- a radio button in the on state
"MovI" -- the Move icon
"Clok" -- a clock icon with the current time when drawn
For visual elements with no specified event message, you can overlay a "Hots" line. To add visual elements other than these, you can override the DrawMe and EstSize methods, which are given the relevant information for each "User" line. EstSize is called before drawing begins, to allocate the array size needed, then DrawMe is required to use up not more than the estimated size(s).
You can supply keyboard shortcuts using "KeyC" lines.
If you are filtering events, you need to make sure the following events make it to the event handler for whatever window is using this imaging model:
"Butn"/"ChkT"/"RadS"/"Mpop"/"Clok"/"MovI" -- Track clicks in their respective display elementsThe AutoEvent function will make sure these windows get their events. The following public objects are defined in package ImDlogPkg:
"mDrg"/"msUp" -- Needed to track mouse release
"KeyC" -- Only if you are using keystroke equivalents
"Imag" -- If a redraw is needed
"CloW" -- If you want the window to close itself
final ImageWinMgr thePrefsWindow; // a Preferences windowYou would open the Preferences window thus:
final ImageWinMgr theDashWindow; // a separate dashboard
final ImageWinMgr theProgresBar; // a separate progress bar
if (NewPrefsWin(ItemsTxt,PramTxt,'`',tall,wide,ItemsObj,false)) {/* failed */}where ItemsObj is an instance of your subclass of ImageItems (or null if you don't need to react to any events). If you give it a negative height in tall, it will open the dashboard object window instead. Use the ProgressBar functions to open and manage the progress bar. If you are diverting "CloW" events, and you want any of these windows to self-close, you might check whether they are destined for such a window thus:
Window aWin = EventWindow(theEv);and similarly for the others. See package VuResFiWn for another implementation of this model.
if (aWin != null) if (aWin == thePrefsWindow.theWin) thePrefsWindow.CloseItDown();
class IconFontFetch { // to extend icons & fontsWhen you create an object of your extended class, the base class constructor installs it in a list of such objects that gets searched whenever your program asks for a named icon or font. Your access function gets first shot at all requests, so you can override the defaults if you wish; otherwise return null for any fonts or icons your code does not recognize. Java (and therefore also Turk/2) has no explicit destructors, so you must call UnInstall() before this object goes out of scope if allocated final within a function or global in a sublaunched process that quits.
IconFontFetch NextUp;
IntArray GetIconAddr(Char4 whom) {return null;} // o'ride to return tbl..
IntArray GetFontAddr(Char4 whom) {return null;}
void UnInstall() {/*uninstall this object*/}~UnInstall
IconFontFetch() {/*install this object*/}~IconFontFetch}~IconFontFetch;
Override GetIconAddr to return an integer array reference
of the named icon, and GetFontAddr to return an integer
array reference of the named font, or null in either case if your
object does not recognize that name. An icon array begins with the icon
height and width packed into a single integer (16 bits each, as V*0x10000+H),
then a sequence of drawing commands (mostly just "show
pixels" operations; embedded icons are not allowed), followed by a zero
terminator.
A font specifier array is somewhat more complicated. It has a prolog,
the index, then the pixels. The first number is by convention the font
name. The second number is a composite of the line height, descent and
ascent, packed one byte each as H*0x10000+D*0x100+A. The third
and fourth numbers are the number of pixels separating each character,
and the width of a space. A monospace font prolog has two more numbers,
a zero followed by the character width (which should be the same as the
space width), and the index is omitted; the pixels for "!" start
in table position [6]. A proportional font index starts in position [4]
for the space, which should be the same as for "!" because there
are no non-white pixels in a space. The pixel information must be in ASCII
order, and the final index position CHR(0x7F) pointing just past
the last displayable character. Each character is encoded as a sequence
of 1-word pixel columns, up to 32 pixels tall (the 32 bits in one integer),
as many pixels wide as needed (but currently limited to a maximum of 63).
You can think of each character as if rotated 90 degrees clockwise, thus: