Humpty Promotes > Rfo-Basic > HEW > Reference Manual

HEW is A GUI Framework using RFO-Basic APP development for Android.

HEW Reference Manual v4.40

(todo)
Grid selectors
Select List
Init.bas
This section mainly initiates the graphics screen and sets global bunlde (1) variables.

You should call init_hew() before executing your main program, usually just after including functions.
e.g

include isr.bas               % interrrupt handling
include themes.bas            % widget colors

include event.bas            % event loop
include init.bas            % init screen and globals
%--------------------
% gosub your_files_init            % copy files to sdcard
init_hew()


gosub your_files_init
is optionally a chance for you to copy any files to the sdcard if you have built an apk.
If you use themes.ini to change colors, then it must exist on sdcard before calling init_hew().

Screen Initialisation
Everything, if possible happens in graphics mode using graphics objects.
The exception is if the built-in WebView is needed to display an html page (e.g formfill).

There are three problems that stand when designing HEW apps to run on different sized phones.
a) Different screen sizes.
b) Different aspect ratios.
c) Different pixel densities.

Development Device Size
At the start, dev_w and dev_h are your development device width and height in pixels.
These must be defined whether you use scaling or not. In the least, it let's HEW know about the development aspect ratio.

Init.bas gives you the choice of whether to use scaling/or not.
It sets up scr_w and scr_h to be used by the rest of your app.
(This bit of compact code took a lot of trial and error)

Scaling
If you don't need scaling then set scaling=0 .

scaling=1
For certain things like bitmaps, scaling is neccessary. As a result, all widgets that do their own touch detection (e.g gr.touch x,y) will also re-scale according to scale_x and scale_y which are read from the global bundle (1).

Init.bas scales both width and height to the smallest found ratio (act(w|h) / dev(w|h).
This means everything will
a) fit inside the screen, and
b) be squarely proportioned (i.e circles will be circle and squares will be square after scaling)

Therefore it is advisable to develop on device with a shorter height (e.g h/w ratio 1.5) compared with longer height devices (>1.5). This way, when the apps are run on taller devices, the bottom will be unused to preserve the aspect ratio. Scaling by one-side-only prevents widgets looking distorted.

If you choose to use scaling (scaling=1),  then scr_w,scr_h are set the same as dev_w, dev_h. And you must treat your coordinates as if using the development machine sizes. All the graphics code is then scaled up/down automatically when the app is run on a different machine by BASIC's gr.scale command.

The advantage of scaling is that you can use absolute (dev) coordinates  without worry.
The dis-advantage is that widgets will look fat and bloaty on machines with large screens.

If you choose not to use scaling (scaling=0),  then widgets are sized by relative density. So for the same density (160), larger screens will have more rows.

The advantage is that widgets will look the same size on any screen-size. And you can have more rows for larger screens with same density.
The dis-advantage is that you can't use absolute coordinates and sizes in your app. Instead all values have to be relative to either scr_h, scr_w or the other reference variables. These values are setup and globalised by init.bas, as well as scale_x and scale_y  (see below).

Colors
init.bas will call theme_init() to load default colors for all widget creation.
Since v2.0, init.bas will call it before initiating the graphics screen. This is to entertain setting the canvas color to p_canvas. See section on themes for more.

Global Bundle (1) Variables
In basic!, the main program variables are not available to functions and vice versa. A workaround is to use a bundle (bundles are global). The first ever created bundle has index 1, Init.bas creates this to store values for the rest of the system. and is referred in the manual as global bundle(1).

Init.bas is a function. It initialises the first global bundle with ID 1. To access the bundle, do something like;
e.g bundle.get 1, "scr_h", sh
The available bundle variables can be seen near the end of init.bas.

All HEW widgets avoid actual pixel coordinates and instead are relative according to the screen width|height and/or the current gr.text.size when a widget is created. Among the The global bundle(1) variables there is
"txt_h"
"row_h"
These are calculated purely from the screen size and a standard row height of 28 dots on a density of 160 dpi. You do not have to use them, but they are there to provide a reference and are available in the global bundle(1). Since they only depend on the mentioned, they are therefore independent of any graphics or font settings.

The variables regarding the screen are created inside init_hew() :
"scale_x"  -  scale factor if scaling else 1. normally (actual / devel) but modified to prevent scale distortion and cropping.
"scale_y"  -  ditto
"scr_w"     - screen width    (adjusted if scaling)
"scr_h"      - screen height   (adjusted if scaling)
"row_h"     - reference row height
"txt_h"       - reference text height (slightly less than row_h)
"srows"     -  number of screen rows
To access these variables, use the global bundle (1) to get them into your own variables;
e.g
.
.
init_hew()
bundle.get 1, "scr_w", my_width
bundle.get 1, "scr_h", my_height
bundle.get 1, "widgets", my_widgets
bundle.get 1, "txt_h", my_txt_height


Pre-Requisites

Requires   (include)

All apps must include isr.bas, themes.bas, event.bas and init.bas. This is the minimum requirement.

All widgets are assumed to require isr.bas, themes.bas, event.bas and init.bas.
Additional requirements will be stated depending on the widget.

It is possible to leave out event.bas but only if you have in-depth knowledge of the widgets, e.g
if you are using your own customised event loop.

Visual updates
Most widget commands do not provide gr.render unless it is needed. So you need to add this in your own code. This is because some apps don't want the user to see the change until a later time.

Theme.bas

Defines the colors used to paint widgets.
Widgets will call theme_color() instead of gr.color().

If you don't want themes.bas, you must replace all the theme_color calls with your own gr.color and remove the theme_init() section from init.bas.

To change the default colors, either modify the entry in themes.bas inside theme_init() OR override the default colors using themes.ini.

Themes.INI
If you want additional themes, you must create data/themes.ini. If this file does not exist, the default colors inside themes.bas > themes_init() will be used instead. Therefore you do not need themes.ini if you don't change themes.

This is what themes.ini looks like;
use_theme = Dark

[default]

[Dark]
p_background=    255,0,0,0,1
p_title=    255,230,140,30,0
p_link=        255,230,140,30,0
p_text=        255,157,218,112,0

.
..etc
[Fancy]
p_background=    255,255,255,255,1
p_title=    255,200,140,250,0
..etc
(download a sample file here)

In this example, there are blank entries under the first theme [default] and some entries under themes [Dark] and [Fancy].

If there are blank entries under [default] then the code-default colors in theme_init()/themes.bas will be used instead. Otherwise the colors defined here will override the default theme 'default'.

For any [theme], if there are blank color entries for any specific color name, then the code-default color in theme_init() for that color will be used instead.

use_theme = <theme> will be the theme that theme_init() will load.

theme_set()
will write the next (use_theme=) inside themes.ini.

Here are the calls you are likely to use;
theme_color (name$)
theme_init ()
theme_list (tlist)
theme_set (theme$)
 
set the current color to the color name$
load default colors (called from init.bas) and load themes.ini, if exists.
returns a list of themes found in themes.ini
sets the next used theme by changing [use theme] inside themes.ini

A new theme is loaded using theme_init() to load  colors from data/themes.ini.
The theme.init() manager also updates colors in formfill.css (if it exists), although any css file can be updated by changing the filename. The css file must support themes by having embedded color markers (see formfill.css).
(Support for formfill has been deprecated).

Canvas color
Since v2.0 of init.bas, there is a color called p_canvas. This color sets the inital canvas color and by default is the same as the background color. However, you may want a diifferent canvas color to contrast the background color e.g if you added a differently shaped (fake) background.
To do this you can either change p_canvas in  themes.bas inside theme_init()/themes.bas OR override it using themes.ini.

Comments
A line starting with a '#' character is treated as a comment.
Event.bas

The main event loop event_get ()  waits for user input (touches) and figures out which widget was touched.

It also handles BakKey detection, and tests if app was put in the background.

To do this, all detectable widgets are put in a list so that the control loop can query their locations.
The widget detection list (widgets) is central to HEW and is built up at the start of your program.
'widgets' is also saved in the global bundle '1'. Some widgets can borrow the event loop by 'taking over' the widget list.

If a widget was touched it will return the widget bundle. If Bakkey was pressed, it will return 0.
Your program should figure out what to do with the return code.

Event.bas does not wait for an 'off-touch', this means your program code has the option to furthur process a 'hold-down' touch (infact some HEW widgets rely on this mechanism).

Available funtions;
event_remove (wg)                % remove a widget from the detect list
event_insert (wg)                % insert a widget at the head of detect list
event_add (wg)                   % insert a widget at tail of detect list
event_shell (n)                   % 1 = detect for shell events, 0 = don't detect shell events (default).

Shell Events
A shell event occurs if there is available output from the Basic! system shell. Event.bas detects this with system.read.ready. If output is available, event_get() returns with -1.

ISR.bas
When an interrupt occurs, e.g BakKey is pressed, timer is called, or an error occurs, this area catches
the interrupt and decides what to do.

OnBackKey
Some functions or code may need to know if the backkey was pressed (e.g inside a loop).
When the backkey is pressed BASIC! first checks in the main namespace, if the variable is undefined, then it will work it's way down the calls looking for the variable until the last function (where the interrupt occurred). Unfortunately there is no way you can identify this last level function (whether by using a commonly named variable or uncommonly named variable).

Therefore a system of using a global bundle(1) variable "isr$" is used to identify the interrupted scope. Thi interrupt status flag is defined at the end of init.bas.

Available functions;
isr_set (s$)                     % set the interrupt status
bk_pressed ()                    % was backkey pressed ?

Any function/code wanting to identify itself as the current scope can call isr_set ("a_name") for debugging purposes. This will also clear the flag for backkey. (do not start the 'name' with an Underscore since this indicates backkey pressed).

Any function/code can query bk_pressed() to see if the backkey was pressed.
To force (trick) a backkey pressed, access the bundle variable isr$ directly and start it with an underscore.


ask_yn.bas
Displays a message in a box with a "yes" and "no"button.

This is a modal dialog and manipulates the global bundle 'widgets' list variable before using event.bas.
demo available
requires: button.bas
detectable: no - modal - own detection.

constructor :  ask_yn_make (style)
where :
style = the buttons style (according to button.bas)

return code : the widget bundle

(since there is only one ask_yn widget, this widget will save itself into the global bundle (1) for the callback)

callback : ask_yn (t$)
where :
t$ = the question
lines can be seperated with the character '|'.      e.g "line 1|line2"

return code : 0=backkey,  1=yes,  2=no
botmenu.bas
Bottom menu widget. This is a six panel popup menu which slides up from the bottom of the screen.

  demo available

detectable: no - modal - own detection.

constructor : botmenu_make ( itms )
where :
 itms = Is a list (of strings). The list should contain 6 strings.

return code :  the widget bundle.


callback : botmenu ( wg )
where :
wg = the widget bundle

return code : the item number selected (1..6) or 0 for quit.
btimer.bas
bTimer is a countdown timer inside a button.
warning: btimer.bas appends the Basic! OnTimer keyword and segment at the end of the file.
This means you cannot use OnTimer anywhere else in your code if you include btimer).
(a goto-skip is used, so you can include btimer.bas at the start of your files)

Btimer is a Hew example of simulating a 'subclass' in Basic!
The timer creates a button, replaces the text with mm:ss. And adds a few more commands.
It also inserts an OnTimer code segment to handle the timer interrupt every second.

Other than that, it behaves like any other button. i.e OnTimer will pass on any button command to it's 'parent' (button). Alternatively you may just call the parent 'button' fuction directly.


requires: button.bas
detectable:  yes

constructor:  btimer_make ( aux$, style, x, y )
where :
aux$ = any auxiliary data passed to button.bas
This should normally be empty ("") but can be used to pass data to button.bas e.g "C"enter..etc.
(see button.bas)

x,y = position of widget (top left corner)
style = (same as button)

return code :
the widget bundle.

callback: btimer ( cmd$, t$, wg )
where :
cmd$ = command
"reset" : stops and resets the timer to the total time.
if t$ is a time e.g "25:29" then the timer will take on this new total. Otherwise the last total is used.
"stop" :  stops the countdown
"start" : starts the timer countdown

The rest of the commands are the same as button.bas

t$ = the time "mm:ss" for 'reset' command.
otherwise same use as button.bas.

wg = the widget bundle

return code : none.

button.bas
Button widget.
demo available
Text with a variety of border styles.
The button can be hidden or moved.
The text can have multiple lines.
A special border style (5) allows a bitmap background for 'on' and 'off'.


detectable: yes
type:  "button"
constructor:  button_make ( aux$, t$, style, x, y )
where :
aux$ = auxiliary data

"C" = centre the button at the x coordinate
"R" = right justify the button at the x coordinate
"B" = bottom align the button at the y coordinate.
"V" = vertically centre the button at the y coordinate (overrides 'B').
"N" = no border (you may also combine e.g "CN" or "RBN"

e.g button_make ( "C", "press me", 4, 100,100 )

"~<width>,<height>" = width, height Override. (experimental)
A tilde (' ~ ') allows to overrride the width and/or height of the button.
This is an experimental feature so the result is un-predictable.

The seperator is a comma and the values must be quoted text.
Either the width e.g "~200" or height e.g ",50" or both e.g "200,50" may be given.
If either the width or height is zero, then the default value is used. The default values are always calculated according to the button text size.

The most useful parameter is the width, as it allows precise horizontal sizing.
The height is the most unpredictable and you may have to adjust text positioning by inserting blank lines.
e.g
b1 = button_make ( "C~200,50" , "button|one", 4, 100,100)

"|<fileprefix>" = filename prefix
If the last part of aux$ contains a bar ' | ' then this indicates a file prefix is appended for a background bitmap for type 5 (see later).

e.g button_make ( "|mybitmap", "press me", 4, 200,200 )
specifies mybitmap_on.png and mybitmap_off.png


filename prefix MUST be the last part (tail) of aux$  (it cannot be in the middle).


x,y = position of widget (top left corner)

t$ = text inside button (will be centered inside) (The font size will follow gr.text.size.)

The amount of text will determine the size (width, height) of the button.
The size does not change. If you want all your buttons to be the same size, then initialize them all with the same text and then change the text with the "text" command.

Multi-Line text can be separated with bars '|' e.g "Multi|line|  button! "
Spaces can be used to increase horizontal width.
Blank lines at the start of the text e.g "|||foobar" can be used to increase the vertical height of the button and the remaining text lines will be centered vertically.
e.g "two|lines " vs "|two|lines "  =>
If you don't want the effect of vertical blank line spacing, then use a spaces at the begining instead of empty strings (e.g "  |  |  |tall|button|  |  |  |").

style = 1,2,3,4 or 5
0 = link  (just text, no border, no background color)   ( previously type 5 )
1 = rectangle
2 = oval
3 = rounded corners
4 = rounded 2              ( previously simple brackets e.g [ click ] )

5 = bitmap background button
example
A bitmap prefix is appended after a bar (' | ') in aux$ (see above)

e.g button_make ("C|bitname", "BitButton", 5, 100,100)

"C" is for centre align (see aux$ above)
"bitname" is the bitmap filename prefix
(no spaces are allowed around the "|")
(The ' ! ' and prefix will be removed from the widget name)

The widget will then expect to find filenames "bitname_on.png" and "bitname_off.png" in the
default directory <base>/data.     (you must make available these images if you use this button type)

The filename prefix will override the default prefix "button" ( button_on.png, button_off.png ).
If no prefix is given, the default prefix is used.

<name>_on will be the image when the button is pressed.
<name>_off will be the image when the button is released.
The action will happen when a "flash" command is called.

Note that images are rectangle, only rectangle buttons work well with this type. If you have a round image, it's background will also show, so you must match the display background with it.


return code : the widget bundle.

callback: button ( cmd$, t$, wg )
where :
cmd$ = command

"flash" : flash the button momentarily
              depending on the button style, either the border/background flashes or bitmap changed momentarily.

"text"  :  change the text inside the button

note: The button size does not change. Be sure to create a size (using spaces) that can surround future text). If future text is too long, it will be truncated.

"show" : shows the widget and enable in touch detection list

t$ : unused

"hide"  : hides the widget and disable in touch detection list
t$ : unused

"move": moves the button according to t$

t$ = x,y move coordinates (string)

"x,y".  eg. "100,50"   eg. "+100, -50"
if preceeded by "-" or "+", then the movement is relative, otherwise it is absolute.


"set"    : set button as pressed or un-pressed
t$ = flag (string)
"1" = set to pressed. Wait till finger up.
"0" = set to un-pressed. Wait till finger up.
"-1" = set to pressed. Don't wait.
"-0" = set to un-pressed. Don't wait.


t$ = text or data for cmd$ (provide an empty string if unused)

wg = the widget bundle

return code : none.
console.bas

Uses txtscroll to simulate a text console.
The widget ID returned is the actual txtscroll widget it uses.

Each text line added with "print" will be added to the end of the txtscroll box. If the box is full, it will scroll up 1 line.

Can be used for display-only or you can add it the the detection-list (widgets) to respond to a touch.

If you make it detectable and it's touched, then you must either pass a "touch" cmd to itself i.e con ("touch", "",wg)
or alternatlively call txtscroll directly e.g call txtscroll ("touch", 0,wg)


consoles are useful for displaying constant text output and for debugging programs in graphics mode.

requires: txtscroll.bas
detectable:  yes
type:  "console"
constructor:  con_make ( aux$, bsize, x,y, ww, wh )
where :
aux$ = auxiliary
Normally empty ('")
used to pass extra data to txtscroll (see txtscroll.bas)

bsize = buffer size    (lines of text)
x,y = position of widget (top left corner)
ww, wh = width, height of widget

return code :
the widget bundle. (this will be the txtscroll widget bundle)

callbacks:
con ( cmd$, t$, wg )
con_bulk ( blist, wg )  for bulk printing of many lines
where :
cmd$ = command
"print" : adds and prints a new line t$ to the end of the console
The console will be scrolled if needed.

"touch" :  passes the touch cmd to txtscroll.
"tag" : appends t$ to the last line without adding a newline.
"clear" : clears the console
"raw" : set raw mode to t$.
"0" =  off
"1" = on
raw mode will tell txtscroll to ignore embedded commands after a '|' symbol.

t$ = text to print
if t$ contains newlines ("\n"), then it will be split into seperate lines.
Empty ("") if unused.

blist = list to print
Printing a list is much faster than printing individual lines

wg = the widget bundle

return code : none.

example

include txtscroll.bas
include console.bas
include themes.bas
include event.bas
include init.bas

init_hew()
bundle.get 1, "scr_w", scr_w
bundle.get 1, "scr_h", scr_h


wg_con=con_make ("", 10, scr_w*0.25,scr_h*0.8,scr_w*0.7,scr_h*0.2)
con ("print","hello world",wg_con)


keyinp.bas

This is a push-out keyboard input for a line of text.
The input field is always at the top of the screen.

Warning: key code translation does not work for all types of keyboards, but you should see some results with the standard Android keyboard. Your mileage may vary.

There are two modes of operation. "once" or "stay".

once : will show the keyboard for input and hide it after.

stay :  will leave the keyboard on the screen after input, although it will not be responsive until another "input" call.





detectable :  yes - (although input area not usually used this way)
type:  "keyinp"
constructor :  keyinp_make ()
where :
entry nothing. There is only one keyboard widget and it will be saved in global bundle (1) as "keyinp".

return code :  nothing

callback : keyinp ( cmd$, dat$ )
where :
cmd$ = command

"input" : get a line of text from user into dat$

Input will be appended to any text already in dat$.

The keyboard will be brought up if in 'once' mode, and brought down after input.
The keybaord will be left on if in 'stay' mode.

If BackKey was pressed in mode 'once' the return code will be 1
If BackKey was pressed in mode 'stay' the return code will be 2.

If 2 is returned, the mode will automatically be put into mode 'once', this is because
most keyboards hide the keyboard if the backkey is pressed.

"put" : overwrite current text with dat$

"label" : change the label to dat$.
The only embedded command is "|I" (bar I) which will italic the text.

"setmode" : set the operating mode to dat$.  The mode can either be "once' or "stay".

"once" :  Put in Once-mode and hide it if previously shown.
"stay"  :  Put in Stay-mode and show it if previously hidden.


"getmode" : get the current mode and return the numeric value
returns 1 = once,  2 = stay


dat$ = data for commands
(see commands)

return code :
for command "input"        : 0 = okay,   else the backkey code (see input command).
for command "getmode" : the mode. (see getmode command)

link.bas
The link widget has been deprecated in favour of using a borderless button instead.

msg_ok.bas
Displays a message in a box with an OK button.

This is a modal dialog and manipulates the global bundle(1) 'widgets' list variable before using event.bas.

demo available
requires: button.bas
detectable :  no - modal - own detection
type:  <none> (is modal)
constructor :  msg_ok_make (style)
where :
style = the button style (inside) (according to button.bas)

(since there is only one msk_ok widget, this widget will save itself into the global bundle (1) for the callback)


callback : msg_ok (t$)
where :
t$ = the message
lines can be separated with the character '|'.      e.g "line 1|line2"

return code : none

numpad.bas

A popup numeric pad for number input.

The widget slides up from the bottom.
The number/result must be passed by reference, so must be already declared.
Some buttons can be disabled.



(no longer supports external text object)

numpad.bas replaces gnumpad.bas ( renamed ).

detectable : no - (is modal - own detection)
type:  <none> (is modal)
constructor : none (numpad_make () is no longer needed)

callback : numpad (cmd$, [&]num)
where :
cmd$ = command

"<any>" = opens widget, gets input

all commands (even if unrecognised) will open the widget for input)

&num = value typed by user (if not quit)

&num must be called by reference e.g numpad ("input",&num) to get the result.
This means num must be previsouly declared or an error message will occur during the call.

Use return code to determine if quit.

"dotoff" = remove decimal point button.

"negoff" = remove negator button.

"alloff" = remove both decimal buttin and negator button.

"<any>|<maxwidth>" = set maximum characters for input to num.
<any> = any or no command

<maxwidth>= number of characters allowed including decimal point but not (' - ').
This must follow the bar (' | ') character.

e.g numpad ("foo|5",&n)

The default is the number of chars that will fit into the default output box. Max is 15.

"txtobj" = override the output text with your own basic! text object.
(no longer supported)


num = numeric parameter (see cmd$)

return code :
0 = OK was pressed (num is updated if returning a number)

1 = quit or BackKey pressed.  Any touch above the widget will quit.
(num is not updated)

example
numpad_make()   % no longer needed

rc = numpad ("" , "&num")

if rc=0 then print "num=";num else print "cancelled"


pickform.bas

Can be used as a form filler or list picker, it gets input from the user.
It is the graphic equivalent of formfill.bas.

Each row has
A type:  "title", or "label", "menu", "checkbox", "radio", ..etc.
A label: e.g "Settings"
A value: e.g "99"

"menu" items will close the form with the row number returned.

The values that are passed are always updated. If a 'quit' option is needed, send a temporay value list to pickform_make instead of the real list.

Features
  • Can be windowed and positioned.
  • Slide transition effects from any of the 4 sides.
  • Themed with themes.bas
  • embedded subforms and picklists
PickForm (aka gformfill) no longer supports infinite lists. Only 1 bitmap is used, meaning that lists longer than two screenfuls are not recommended (depending on the memory of the phone). It does mean though that scrolling is smoother and precise.
If you need longer lists, consider using formfill (the html equivalent).

Future Plans
pickform is currently modal (closes when it quits). An idea pickform is to have it modeless (interact with event.bas). A 'stay' mode can be implemented (similar to keyinp).


demo available
pickform replaces gformfill (renamed)

detectable : no - modal - own detection ( open with 'input' cmd )
type:  <none> (is modal)

constructor : pickform_make ( x, y, ww, wh,  itmtyp, itmlab, itmval )
where:
x, y = position (top left corner) of widget. (including borders)
x
-1 = Centering
Positions form horizontally to center of screen.

< -1 (e.g -99) = Justify (right)
Any negative coordinate (except -1) will treat the value as the (positive) right coordinate instead of the left. This is helpful for transitions that slide in from the right hand side of the screen

y
-1 = Centering
Positions form vertically to center of screen.

< -1 (e.g -99) = Justify (bottom)
Any negative coordinate (except -1) will treat the value as the (positive) bottom coordinate instead of the top. This is helpful for transitions that slide in from the bottom of the screen


ww, wh = width and height of the widget (including borders)
ww
0 = full screen width

-1 = auto_width mode -1
width will try to encompass the widest content, even if it means using the full screen width.

-2
= auto_width mode -2
width will try to encompass the widest content, but will limit to max 2/3 of screen width.

-3 = auto_width mode -2 + center justify
width will try to encompass the widest content, but will limit to max 2/3 of screen width.
the widget will be centered on the x coordinate

wh
The height will be rounded to the nearest row.

0
= full screen height

-1 = auto_height mode -1
height will try to encompass all rows or full screen height, whichever is the shortest.

-2
= auto_height mode -2
height will try to encompass all rows or 2/3 screen height, whichever is the shortest.

-3 = auto_height mode -2 + center justify
height will try to encompass all rows or 2/3 screen height, whichever is the shortest.
the widget will be centered on the y coordinate

(during execution, the pos or size might be changed internally to force the list to fit screen.)

Above auto_modes can be freely mixed with user_specified values,
e.g wg_form1= pickform_make (20 , scr_h*0.1 , -1, -2, setM_typ, setM_lab, setM_val)

itmtyp, itmlab, itmval = 3 string lists containing each row's type, label and value

Types of items
itmtyp
"title"
:            Displays text with a title background.
itmval
"C"    - center the text in itmlab
"R"    - right justify the text in itmlab
"|B"   - a bar (' | ') B will frame the title with the background color.  e.g "|B", or "C|B" or "R|B"

default is 'left' justify with no border.

"menu" :        A menu item will close the form and return the row pressed.
itmval
"C"    - center the text in itmlab
"R"    - right justify the text in itmlab

"checkbox":  Checkbox item.  
itmval
"0"    =  checkbox ON
"1"    =  checkbox OFF

"radio" :        Radio item.
itmval
"0"    =  radio ON
"1"    =  radio OFF
There must be at least 2 radio items. When one radio item is selected, all the others are turned off.

"counter" : or counter|min,max        2 digit Counter item   (number spinner)  
|min,max
By default, "counter" on it's own has minimum value 0 and maximum value 99.
Optionally, the minimum and maximum can be added after a bar (' | ') with comma seperator.
e.g  "counter|1,10"

Both min and max must be present if used.


itmval
the initial and input value of the counter.

"text_in":  Text Input.  
itmval
"a line of text"
Initial and input value of the text input.
Tapping on the text calls the standard basic! text input dialog.
The width of the whole row is determined by the number of characters in itmlab or itmval whichever is longest.

"subform|<wg>": embedded subform
wg
This is the widget bundle ID of the embedded subform (another pickform).
It must be converted to a string and tagged after a bar ( ' | ' ).
This means the subform must be created first to obtain it's widget ID.

(you MUST supply a widget ID)

itmval
"C"    - center the text in itmlab
"R"    - right justify the text in itmlab

subform history.

When a subform row is tapped, it will open up the subform. This way, you can simulate multi-level lists of menus. When the last item (a menu) is pressed, all the previous forms will close and -1 is returned to indicate a subform press. Knowing this, you can interrogate the widget bundle field "subhist" to find a history chain of pressed rows, seperated by commas,
e.g

if rc<0 then                              % subform pressed ?
   bundle.get wg_form1, "subhist", s$     % get subform history chain
   print s$
endif

returns "2,3,4" meaning the 2nd row was pressed in form1, then the 3rd row was pressed in form2 and finally a menu row 4 was pressed in form3.

BackKey will close only 1 level and will not add it to the history chain.

"picklist|Title,item1,item2,item3.." : one-level picklist

Title,item1,item2,item3..
This is an embedded picklist in the item type. (see picklist)
It must follow after a bar ( ' | ' ). This list is not optional, it MUST be present.

itmval
This is the initial and picked type from the picklist.

When a type 'picklist' row is tapped, pickform will call picklist. The text picked will end up in itmval.
The form will not close.

If you use this type, you MUST include picklist.bas somewhere in your code.
(If you don't use it, there is no need to include the file.)

"integer" : or integer|max,min        Whole number input.

This will call numpad to get a whole number if tapped.
If you use this type, you MUST include numpad.bas somwhere in your code,
(If you don't use it, there is no need to include the file.)

When the row is tapped, numpad is called with initial value of zero (empty). If the user quits, then the original value is perserved.

"|max,min"
You may specify a range by appending "max,min" after a bar (' | ').
If you use this, then both values must be present.

"real" : or real|max.min        Decimal number input.

This will call numpad to get a real (decimal) number if tapped.
If you use this type, you MUST include numpad.bas somwhere in your code,
(If you don't use it, there is no need to include the file.)

When the row is tapped, numpad is called with initial value of zero (empty). If the user quits, then the original value is perserved.

"|max,min"
You may specify a range by appending "max,min" after a bar (' | ').
If you use this, then both values must be present.


<other> :  "label"
itmlab
Any type not recognised is considered a label.
A label is just text and cannot be justified unlike a title.
itmval
Unused

subtext
All itmlab's can have subtext (a line of smaller text below) by appending a bar (' | ').
e.g list.add itmlab, "Pick Option", "Red", "Blue", "Green|(this is apple green)"

no separator
All itmlab's can prepend a tilde (' ~ ') to suppress the next separator line.
e.g list.add itmlab, "Pick Option", "Red", "Blue", "~Special Sale", "Green"
    list.add itmtyp, "title",       "menu, "menu", "label",         "menu"



return code : the widget bundle.


callback : pickform (cmd$, data$, wg)
where :
cmd$ = command

"input" : activate the widget and get input. - A selected menu item will close the form.

data$
contains a transition effect. if empty or unrecognised, default will be center.

"left" = slide in from the left
"right" = slide in from the right
"top" = slide in from the top
"bottom" = slide in from the bottom

"update" : updates the size of the widget according to the lists.

You might need this if the lists have changed contents

"setpos" : set a new position

data$ =  "x,y" where x,y is the new position of the form. ( including borders)
"x,y" is a string containing the new coordinates  seperated by a comma.
You may also use auto_modes.

e.g
x=100
y=200
pickform ("setpos", int$(x) + "," + int$(y), wg_form1)


"setfont" : update the window size according to the current font size. (unsupported since v3.0)

data$  :  (see cmd$)

wg = the widget bundle

return code :
The item row number selected (1..maxitem) or

special returm codes


0 =    for quit/bakkey.

-1 =   a subform row was pressed.
It's history chain is in the widget bundle "subhist" variable. (see 'subform' above).

Unlike it's html equivalent (FormFill), there is no type called 'submit'. Instead use type "menu" which will exit the form, always with itmval updated, so If you wish to implement a 'Cancel' operation, then pass a temporary itmval list to pickform_make instead of the real one.

Usage summary:

checkbox, radio itmlab : label text
itmval : "1"=ON , "0"=OFF

counter, text_in, picklist
integer, real
itmlab : label text
itmval :  initial and returned values (converted to text).

menu, title, subform
itmlab  : label text
itmval = justify : "C"enter  or "R"ight  (default is left justify)
append"|B" for title border (titles only)

counter, integer, real
itmtyp: counter|min,max
itmtyp: integer|min,max
itmtyp: real|min,max
|min,max is optional, but both values must be present if used.

integer, real
you must include numpad.bas if you use this type.

picklist
you must include picklist.bas if you use this type.

subform itmtyp : subform|wgid
e.g "subform|"+ int$(wg_form2)
|wgid must be present, it is not optional.

-1 is returned if subform is tapped and not quitted.
Last history chain is in bundle.get wg, "subhist", s$


<all labels>
itmlab : "main|sub text "

append "|some subtext" will append additional text using a smaller font beneath the main text.

itmlab : "~Some text, then no separator line after"

prepend a tilde "~" before the text will suppress the next separator line.

picklist.bas

PickList is a quick select list for short lists with transition effects.

You can slide it in from any of the four screen edges. The default transition is centre with no transition effect.

There is no 'make'. picklist is modal. The selection row number is returned.

Do not give long lists because it uses a single bitmap too store all the rows.
If the bitmap is too tall, the result is unpredicable.

The colors can be changed either from themes.bas or themes.ini. PickList uses the paint prefix p_pl_.

picklist automatically takes care of the list height and positioning. If you need more control, use pickform instead.

picklist replaces gselect (renamed).

detectable : no - modal - own detection
type:  <none> (is modal)

constructor : (none)
(there is no 'make', everything is generated on the fly and will be 'on top').

callback : picklist ( effect$, label$ )
where :
effect$ = transition type

"left" = slide in from the left
"right" = slide in from the right
"top" = slide in from the top
"bottom" = slide in from the bottom
if effect$ is anything else, the default is 'no transistion' and centerd in the middle of the screen.

Manual Positioning

An embedded position can be entered after a bar (' | ') as x,y.
e.g "top|100,100" will drop down from 100,100.

Centering uses the special coordinate "-1"
e.g "top|-1,-1" will drop down leaving the widget at the center of screen.

Justify (right,bottom) uses negative coordinates other than "-1"
Any negative x coordinate (except -1) will treat the value as the (positive) right coordinate instead of the left. This is helpful for transitions that slide in from the right hand side of the screen.

Any negative y coordinate (except -1) will treat the value as the (positive) bottom coordinate instead of the top. This is helpful for transitions that slide in from the bottom of the screen

e.g "bottom|100,-200" will pull up from y coordinate 200 leaving the bottom of the widget at 200.

Justify (center) uses a tilde prefix "~"
e.g "top|~"+int$(x) + "," + ,int$(y)" will drop down at the center of position x
      "top|"  +int$(x) + ",~" + ,int$(y)" will drop down at the vertical center of position y

All manual positions are inclusive of the widget border.

label$ = A string of  labels
Labels for each row is separated with commas (' ,').

The first label which is always the Title, will not be selected if touched. The next label will be selected as item number one.

All labels will be centered.

return code : the item number selected (1..n) or 0 for quit/bakkey.

e.g
rc = picklist ("left" , "Pick A Color,Red,Green,Blue,Yellow")

Tip: you can match the return code with the picked label like this;
rc = picklist ("left" , label$)
if rc then picked$ = word$(label$,rc+1,",")



progress.bas

(modeless) The Progress bar widget displays a bar as an indicator 0..100%.

detectable:
yes (although not used this way)
type:  "progress"
constructor :  progress_make ()
where :

return code
:  the widget bundle.

callback : progress (cmd$, num, wg)
where :
cmd$ = command
"show" : show the widget.
"hide"  :  hide the widget.

"inc" :  increase the bar by a dot step
the total number dots depends on the device, the widget bundle variable maxdot$ will have the longest string of dots.
If maxdot$ length is reached, then the bar is reset to 1 dot.
Only use this if you don't know the current percentage of progress.

"set" : set the progress percentage num of the full bar.
where fraction num = 0..1 indicating zero to 100%
normally you should use this to set the progress value rather than the 'inc' method.

num = percentage change for cmd$=set.   else ignored.

wg = the widget bundle

return code : none
text.bas
A text widget displays a line of text.

The font size will follow gr.text.size.

detectable:
yes (although not normally used this way)
type:  "text"
constructor :  text_make (aux$, t$, x, y)
where :
aux$ = formatting

aux$ should be normally an empty string but can contain these embedded commands;

"C" = align center
"R" = align right

t$
= text displayed

x,y = position of widget (top left corner)
return code :  the widget bundle.

callback : text_do (cmd$, t$, wg)
where :
cmd$ = command
"flash" : flash the text momentarily
"text"  :  change the text inside the button
"hide" :  hide the object
"show" : show the object

t$ = text to be changed (provide an empty string if unused)
For cmd$="flash" If t$ is non-empty e.g "3", the flash will flash that many times, otherwise it will flash once.

wg = the widget bundle
return code : none
textbox.bas
A text box for input or output.

For input, add the returned widget ID to the event detect list,  then either call the widget with command 'input' or handle it with your own routine. For output-only, do not include it in the detect list.

You can have any size box and update the text with strings containing newlines ("\n").
The font size will follow gr.text.size.

You can change the look of the label and border by appending "|<cmd>" to the label in textbox_make.

detectable:
yes
type:  "textbox"
constructor :  textbox_make ( lab$, x, y, ww, wh )
where :
lab$ = label on top of the box

append a sub command after "|" to change the look, sub commands are;

"I"   =  label in italics
"N" = no border (border is merged with background color)

x,y = position of widget (top left corner)

ww,wh = window width and height

return code :  the widget bundle.

callback : textbox ( cmd$, data$, wg )
where :
cmd$ = command
"input" : calls the BASIC! input dialog to get new text.

data$ is not used, the new data is not returned.
To get the new text, use command 'get'.

If the dialog is cancelled by user, the return code is non-zero.

"get"  :  get the current text into data$

data$ must be called by reference e.g textbox ("get", &data$, wg_tb1)
( be sure to define 'data$' before calling )

"put" :  overwrite the current text with data$
"label" :  overwrite the label with data$

data$ = text used in 'get , 'put' and 'label' (provide an empty string if unused)


wg = the widget bundle

return code : 0 if ok. non-zero is an error or cancelled.
txtscroll.bas
Vertically scrollable text pane.

demo available

detectable: yes - ( respond with 'touch' cmd. )
type:  "txtscroll"
constructor :  txtscroll_make ( aux$, tlist,  x,y ,w,h )
where :
aux$ = extra data
Normally this should an emtpy string but can contain the following;

"N" : No Border  - remove the border surrounding the widget
"R" : Rounded Border - corners are rounded
"W" : raW mode - embedded formatting is ignored. Default is OFF.
"S" : Snap mode - snaps contents to nearest row. Default is OFF.

tlist = list containing lines of text (there is no limit to the number of lines)
If RAW mode is OFF then embedded commands after a bar character '|' will format the text.
Embedded commands are;
"C" : Center text and color it
"R" : Right justify text and color it
"I : Italicizes text
"2 : use color 2 for text
"3 : use color 3 for text
"V"  : reVersed color. (background and foreground colors are swapped)
Commands must be uppercase.
You may have multiple commands, e.g ("C3V") they are processed in the above order.
The formatting colors used
(p_tsc_text2 and p_tsc_text3 ) are defined in themes.bas and.or themes.ini.

x,y = position of text pane (top left corner)  -  (not including borders )

w,h =  width and height of the text pane -  (not including borders )
The width and height might be adjusted to fit inside the screen. The height in particular will be adjusted to a multiple number of text height).

notes
The text size depends on gr.text.size. (which may be modified to correct rounding errors)
Scrolling will be snapped to the nearest row.

return code :  the widget bundle.


callback : txtscroll (cmd$, n, wg)
where :
cmd$ = command
"touch" : enter touch mode.    finger will scroll the text until finger is lifted.
A slow slide will slide the text by pixel.
A quick fling will scroll a large number of lines depending on the touch velocity.
A slide may also trigger a fling depending on the velocity.
A tap (no movement) returns the tapped row number.

"scroll" : remote scroll mode.  will scroll the text by n lines.
n < 0 the text will scroll up (the window moves down towards bottom of list)
n > 0 the text will scroll down (the window will move up towards top of list)

"goto" : goto line n
This will also refresh the contents and snap to the nearest row.
If
n=0 then the page will just be refreshed.
If
n is out of bounds, then n will be intepreted as the  nearest row next to n.

"hide" : hide the widget and take it off the detect list.

"show" : show the widget and insert it at the head of the detect list.

"roll"  : roll on or off
0 = roll off the text and hide the widget
n = show the widget and roll on the text with row n as top of the window.

"gettop"  : get the top row number in window
"getbot"  : get the bottom row number in window

wg = the widget bundle


return code :
"touch" :
If the widget was just tapped (no movement), the tapped row number is returned.
If the widget was scrolled, zero is returned.


"gettop" , "getbot" :
Row number is returned.

Any other command :
The return code is undefined.

notes
Any touch movement or animation (eg. roll) triggers an internal gr.render. Otherwise you may have to
supply your own gr.render after (if you are using events.bas, you usually don't need an extra gr.render).

By careful positioning of the embedded text command "|V", a primitive select list can be implemented.
(the parser for the text formatting after the '|' is tolerant as it ignores extra '|'s)
An example is given in the demo: txtscroll_demo.bas.



Support my projects!
Donate





Leading Cloud Surveillance, Recording and Storage service; IP camera live viewing

Leading Enterprise Cloud IT Service; cloud file server, FTP Hosting, Online Storage, Backup and Sharing

Powered by FirstCloudIT.com, a division of DriveHQ, the leading Cloud IT and Cloud Surveillance Service provider since 2003.