It's the beginnings of a text mode windowed UI, written in rexx.
Should be multiform.
/*
Test rexx app for UI
version 0.1
Tom Dyer 2020
*/
call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs"
call SysLoadFuncs
wm = .windowmanager~new(.logger~new)
wm~logger~setloglevel(2)
win = .logwindow~new
win~logger=wm~logger
win= .window~new
win~screen= wm~screen
win~name = "The Logging Window"
label1 = .label~new("this is a label",1,1)
label2 = .label~new("a second label", 2,1)
input1 = .inputbox~new("", 1, 20, 30)
input2 = .inputbox~new("test", 2, 20, 30)
input3 = .inputbox~new("test2", 3, 20, 30)
fieldhelplabel = .label~new("",10,20)
input1~validator= .validator~new()
input2~validator= .numericvalidator~new()
input1~validator~fieldhelp=fieldhelplabel
input2~validator~fieldhelp=fieldhelplabel
win~objects~insert(label1)
win~objects~insert(label2)
win~objects~insert(input1)
win~objects~insert(input2)
win~objects~insert(input3)
win~objects~insert(fieldhelplabel)
wm~window~insert(win)
wm~run()
wm~logger~log( "wm is run",1)
do i = 1 to 3
say "shutdown "
call syssleep(i)
end
exit
::class windowmanager
::attribute running
::attribute logger
::attribute keyboard
::attribute screen
::attribute window
::attribute focusableitems
::attribute activeitem
::method init
expose logger screen
use arg logger
self~window = .list~new
self~focusableitems = .list~new
screen= .screen~new()
::method run unguarded
expose keyboard screen
keyboard= .keyboard~new()
keyboard~logger= self~logger
keyboard~listener=self
self~findfocusable
self~drawwindows
self~logger~log("start wm",1)
self~keyboard~poll
self~logger~log("back from pollkey",1 )
return
::method findfocusable
do i = 1 to self~window~at(0)~objects~items
if (self~window~at(0)~objects~at(i))~isInstanceOf(.focusable) then do
self~focusableitems~insert(self~window~at(0)~objects~at(i))
end
end
self~focusableitems~at(0)~hasFocus = .true
self~activeitem= self~focusableitems~at(0)
::method nextFocus
self~logger~log(self~focusableitems~items,0)
do i = 0 to self~focusableitems~items -1
self~logger~log(i ||"might"|| self~focusableitems~at(i)~hasFocus,0)
if self~focusableitems~at(i)~hasFocus = .true then do
self~focusableitems~at(i)~lostFocus
if i = self~focusableitems~items -1 then do
self~focusableitems~at(0)~gotFocus
self~activeitem=self~focusableitems~at(0)
return
end
else do
self~focusableitems~at(i+1)~gotFocus
self~activeitem=self~focusableitems~at(i+1)
return
end
end
end
::method drawwindows
do i = 1 to self~window~items
self~window~at(i-1)~draw
end
::method sendkey
use arg key
self~logger~log(key,0)
select
when key~alt= .true & upper(key~value) = "X" then do
self~keyboard~running= .false
self~screen~running = .false
self~logger~log("shutdown called",0)
end
when key~alt= .true & upper(key~value) = "R" then do
self~drawwindows
self~screen~draw
end
when key~tab=.true then do
self~nextFocus
end
otherwise
self~activeitem~sendkey(key)
end
self~drawwindows
::class screen inherit AlarmNotification
::attribute logger
::attribute rows
::attribute columns
::attribute platform
::attribute running
::attribute data
::constant ansi '1b5b'x
::method ansiclear
return self~ansi||'2J'
::constant isLinux linux
::constant isWindows windows
::method init
use arg logger
self~logger
self~data = .mutablebuffer~new()
if pos("Linux", SysVersion()) <> 0 then do
self~platform=self~isLinux
end
if pos("Windows", SysVersion()) <> 0 then do
self~platform =self~isWindows
end
self~getscreensize
self~setalarm
::method setalarm
if self~running = .false then exit
alarm = .alarm~new(1, self)
::method getscreensize
expose rows columns
if self~platform = self~isLinux then do
/* linux */
do line over .SystemQueue~new("stty size ") ; nop ; end
parse var line rows columns
end
if self~platform = self~isWindows then do
/* not tested but should work eh */
parse value SysTextScreenSize() with rows columns
end
::method triggered
self~draw
::method draw
self~clear
say self~data
self~setalarm
::method clear
say self~ansiclear
/* call SysCls */
::class keyboard
::attribute logger
::attribute running
::attribute listener
::method poll unguarded
expose k
if self~running = .false then exit
k = sysgetkey("noecho")
key = .key~new
key~value=k
if c2x(k) = .key~tabcode then do
key~tab=.true
key~value=""
end
if c2x(k) = .key~bscode then do
key~bs=.true
key~value=" "
end
if c2x(k) = .key~spacecode then do
key~space=.true
key~value=" "
end
if c2x(k) = .key~altcode then do
k = sysgetkey("noecho")
key~alt=.true
key~value= k
end
self~logger~log("key" key~get(), 1)
self~listener~sendkey(key)
self~poll
::class key
::constant altcode "1B"
::constant tabcode "09"
::constant spacecode "20"
::constant bscode "7F"
::attribute alt
::attribute tab
::attribute value
::attribute space
::attribute bs
::method get
expose value
return value
::class logger
::attribute logdata
::attribute running
::method init
self~logdata = .list~new
::method log
expose loglevel
use arg message, level
rc=lineout("logfile",message)
if level > loglevel then do
self~logdata~insert(message)
rc=lineout("logfile",message)
end
::method setloglevel
expose loglevel
parse arg loglevel
::class window
::attribute name
::attribute screen
::attribute objects
::method init
self~objects = .list~new
::method draw
self~makewindow
self~screen~data = self~makewindow
::method maketitlebar
titlebar = center( self~name, self~screen~columns, "*")
return titlebar
::method makewindow
d = self~maketitlebar
do i = 1 to self~screen~rows-3
d = D||"*" || right("*",self~screen~columns-1," ")
end
time = time()
d = d||center(time, self~screen~columns, "*")
do i = 1 to self~objects~items
d=d||self~objects~at(i-1)~draw
end
return d
::class logwindow subclass window
::attribute logger
::method draw
super~draw
do i = 1 to logger~logdata~allItems
self~screen~data(logger~logdata[i])
end
::class widget
::attribute fieldhelp
::attribute row
::attribute column
::attribute data
::attribute disdata
::attribute validator
::method predraw
self~disdata = self~data
::method draw
self~predraw
return x2c(1b)||x2c(5b)||self~row||";"self~column||"H "||self~disdata
::method init
expose data row column
use arg data, row , column
row = row + 2
column = column + 2
::class label subclass widget
::class inputbox subclass widget inherit focusable
::attribute length
::method init
expose data row column length
use arg data, row, column, length
self~validator = .nil
self~init:super(data, row, column)
::method predraw
self~disdata = left(self~data,self~length,"_")
if self~hasFocus = .true then do
self~disdata = self~disdata ||" * "
end
::method sendkey
use arg key
if key~bs = .true & length(self~data ) > 0 then do
self~data = left(self~data, length(self~data)-1 )
end
else do
if self~validator <> .nil then do
if self~validator~isValid(key) = .false then key~value = ""
end
self~data = self~data||key~value
end
::class focusable mixinclass object
::attribute hasFocus
::method gotFocus
self~hasfocus = .true
::method lostFocus
self~hasfocus = .false
::class validator
/*
normal validator letters and numbers
*/
::attribute validkeys
::attribute fieldhelpstring
::attribute fieldhelp
::method init
self~validkeys = .string~graph || " £"
self~fieldhelpstring = "This field is alphanumeric"
::method isValid
use arg key
if self~fieldhelp <> .nil then self~fieldhelp~data = self~fieldhelpstring
if pos(key~value, self~validkeys) > 0 then return .true
else return .false
::class numericvalidator subclass validator
/*
numeric validator 4
*/
::method init
self~validkeys = .string~digit
self~fieldhelpstring = "This field is numeric"
::class SystemQueue subclass RexxQueue
::method init
use strict arg command
command "| rxqueue"
self~init:super
I would certainly like to use this TUI. Another good reason for me to switch from Regina to OORexx! Just need to decide whether to try version 4.2.0 or dive right into 5.0.0beta. Any thoughts? I use Debian Linux.
Chris
I would certainly like to use this TUI. Another good reason for me to switch from Regina to OORexx! Just need to decide whether to try version 4.2.0 or dive right into 5.0.0beta. Any thoughts? I use Debian Linux.
Chris
It's a bit of fun. I wrote it on oorexx 5 beta (I can't remember if I used any of the new functionality, I might have).
From my perspective, on various linux platforms, I am finding v5b working well.
I (hope) it displays some good OOP and OOD.
On Monday, 27 April 2020 14:59:12 UTC+1, Bob Bobskin wrote:
I would certainly like to use this TUI. Another good reason for me to switch from Regina to OORexx! Just need to decide whether to try version 4.2.0 or dive right into 5.0.0beta. Any thoughts? I use Debian Linux.
Chris
It's a bit of fun. I wrote it on oorexx 5 beta (I can't remember if I used any of the new functionality, I might have).
From my perspective, on various linux platforms, I am finding v5b working well.
I (hope) it displays some good OOP and OOD.
When one can add a password field with this amount of code, it's nice :)
(my partner disagrees, she looks bemused that anyone can be excited by a box you can type in, in a black screen, which does nothing).
::class passwordbox subclass inputbox
::method predraw
self~disdata = copies("*",self~length)
if self~hasFocus = .true then do
self~disdata = self~disdata ||" P "
end
Hi Chris,
*very* impressive!
Had to test it on Windows where in principle it works (having ansicon installed, cf.
<https://github.com/adoxa/ansicon/releases> for the time being).
One thing that is interesting on Windows: in my case the screen buffer size is 135x3000 (width x
height) the window size is 135 x 45. It seems that the screen buffer size gets used on Windows. Also
the cursor positioning does not quite work (it is placed on the first column almost at the bottom),
though entering text will appear in the first field.
Hope you remain bored :), please keep up your interesting work!
---rony
Rony,
I think the OP is Bob, not Chris. As for the issues you noted on
Windows, you should be aware of an open bug against the ANSI escape
sequence support. There is an easy workaround however; just issue a
"dummy" command to cmd.exe - like 'rem' - before you (or Bob's code)
issues any ANSI sequences. This will get the support enabled which it automatically is for cmd.exe but not (yet) for ooRexx. HTH,
Gil B.
Hi Chris,
one hint ad Windows: SysTextScreenSize() got updated in ooRexx 5.0 and can be used to find out more
about the current command line window (and also to set the respective data).
Your current usage will return the "screen buffer size", which in my case is 135 x 3000.
The following Rexx program will demonstrate the new features and what they give in my case:
--- testscreen.rex - begin ---
-- screen buffer
parse value SysTextScreenSize() with rows columns
-- visible window size, positions in buffer (0-based)
parse value SysTextScreenSize("windowrect") with top left bottom right
say "current console buffer is" rows "rows by" columns "columns"
say "current window rectangle is ("top"," left") ("bottom"," right")" -
"(0-based, position in buffer)"
say "---"
say "sysTextScreenSize():" sysTextScreenSize()
say
do arg over ("buffersize", "windowrect", "maxwindowsize")
say "SysTextScreenSize("arg"):" sysTextScreenSize(arg)
end
--- testscreen.rex - end ---
Here the output:
--- output - begin ---
current console buffer is 3000 rows by 135 columns
current window rectangle is (0, 0) (44, 134) (0-based, position in buffer) ---
sysTextScreenSize(): 3000 135
SysTextScreenSize(buffersize): 3000 135
SysTextScreenSize(windowrect): 0 0 44 134
SysTextScreenSize(maxwindowsize): 56 135
--- output - end ---
After having used the command line screen for output from different commands, the buffer got filled
already and the rectangle that gets shown off the buffer is given e.g. as:
--- output - begin ---
current console buffer is 3000 rows by 135 columns
current window rectangle is (46, 0) (90, 134) (0-based, position in buffer) ---
sysTextScreenSize(): 3000 135
SysTextScreenSize(buffersize): 3000 135
SysTextScreenSize(windowrect): 52 0 96 134
SysTextScreenSize(maxwindowsize): 56 135
--- output - end ---
If you look up rexxref.pdf, 8.66. *CHG* SysTextScreenSize (Windows only), you will find more
information, also about setting/changing these values.
---
Another hint: as you are using ooRexx 5.0 (it is of release quality, faster, comes with very
interesting new features) you can also use ANSI/Regina style commands with the ability of
redirecting stdin, stdout and stderr from/to stems, but also from/to e.g. Rexx arrays.
rexxpg.ref,6.5 ADDRESS Instruction, gives an example of this new ooRexx feature, rexxref.pdf
documents it in full. You can therefore from now on forgo the " | rxqueue" pipe, if you want.
---rony
On 29.04.2020 14:09, Rony wrote:
Hi Chris,
*very* impressive!
Had to test it on Windows where in principle it works (having ansicon installed, cf.
<https://github.com/adoxa/ansicon/releases> for the time being).
One thing that is interesting on Windows: in my case the screen buffer size is 135x3000 (width x
height) the window size is 135 x 45. It seems that the screen buffer size gets used on Windows. Also
the cursor positioning does not quite work (it is placed on the first column almost at the bottom),
though entering text will appear in the first field.
Hope you remain bored :), please keep up your interesting work!
---rony
On 27.04.2020 16:22, Bob Bobskin wrote:OORexx! Just need to decide whether to try version 4.2.0 or dive right into 5.0.0beta. Any
On Monday, 27 April 2020 14:59:12 UTC+1, Bob Bobskin wrote:
I would certainly like to use this TUI. Another good reason for me to switch from Regina to
thoughts? I use Debian Linux.
functionality, I might have).
Chris
It's a bit of fun. I wrote it on oorexx 5 beta (I can't remember if I used any of the new
a black screen, which does nothing).
From my perspective, on various linux platforms, I am finding v5b working well.
I (hope) it displays some good OOP and OOD.
When one can add a password field with this amount of code, it's nice :) >> (my partner disagrees, she looks bemused that anyone can be excited by a box you can type in, in
::class passwordbox subclass inputbox
::method predraw
self~disdata = copies("*",self~length)
if self~hasFocus = .true then do
self~disdata = self~disdata ||" P "
end
Rony,
I think the OP is Bob, not Chris. As for the issues you noted on
Windows, you should be aware of an open bug against the ANSI escape
sequence support. There is an easy workaround however; just issue a
"dummy" command to cmd.exe - like 'rem' - before you (or Bob's code)
issues any ANSI sequences. This will get the support enabled which it automatically is for cmd.exe but not (yet) for ooRexx. HTH,
Gil B.
On 4/29/2020 8:09 AM, Rony wrote:
Hi Chris,
*very* impressive!
Had to test it on Windows where in principle it works (having ansicon installed, cf.
<https://github.com/adoxa/ansicon/releases> for the time being).
One thing that is interesting on Windows: in my case the screen buffer size is 135x3000 (width x
height) the window size is 135 x 45. It seems that the screen buffer size gets used on Windows. Also
the cursor positioning does not quite work (it is placed on the first column almost at the bottom),
though entering text will appear in the first field.
Hope you remain bored :), please keep up your interesting work!
---rony
--
Gil Barmwater
I don't have a windows machine to try it with, and whilst I did put in some (best guess) code to try to make it work on Windows, I wasn't really able to check.
Given that there is some interest, I think I'll aim to get bored again, and upload it to github or something as a project, so that people can "improve" it.
Best
On Wednesday, 29 April 2020 14:02:20 UTC+1, Rony wrote:
Hi Chris,
one hint ad Windows: SysTextScreenSize() got updated in ooRexx 5.0 and can be used to find out more
about the current command line window (and also to set the respective data).
Your current usage will return the "screen buffer size", which in my case is 135 x 3000.
The following Rexx program will demonstrate the new features and what they give in my case:
--- testscreen.rex - begin ---
-- screen buffer
parse value SysTextScreenSize() with rows columns
-- visible window size, positions in buffer (0-based)
parse value SysTextScreenSize("windowrect") with top left bottom right
say "current console buffer is" rows "rows by" columns "columns"
say "current window rectangle is ("top"," left") ("bottom"," right")" -
"(0-based, position in buffer)"
say "---"
say "sysTextScreenSize():" sysTextScreenSize()
say
do arg over ("buffersize", "windowrect", "maxwindowsize")
say "SysTextScreenSize("arg"):" sysTextScreenSize(arg)
end
--- testscreen.rex - end ---
Here the output:
--- output - begin ---
current console buffer is 3000 rows by 135 columns
current window rectangle is (0, 0) (44, 134) (0-based, position in buffer) ---
sysTextScreenSize(): 3000 135
SysTextScreenSize(buffersize): 3000 135
SysTextScreenSize(windowrect): 0 0 44 134
SysTextScreenSize(maxwindowsize): 56 135
--- output - end ---
After having used the command line screen for output from different commands, the buffer got filled
already and the rectangle that gets shown off the buffer is given e.g. as:
--- output - begin ---
current console buffer is 3000 rows by 135 columns
current window rectangle is (46, 0) (90, 134) (0-based, position in buffer) ---
sysTextScreenSize(): 3000 135
SysTextScreenSize(buffersize): 3000 135
SysTextScreenSize(windowrect): 52 0 96 134 SysTextScreenSize(maxwindowsize): 56 135
--- output - end ---
If you look up rexxref.pdf, 8.66. *CHG* SysTextScreenSize (Windows only), you will find more
information, also about setting/changing these values.
---
Another hint: as you are using ooRexx 5.0 (it is of release quality, faster, comes with very
interesting new features) you can also use ANSI/Regina style commands with the ability of
redirecting stdin, stdout and stderr from/to stems, but also from/to e.g. Rexx arrays.
rexxpg.ref,6.5 ADDRESS Instruction, gives an example of this new ooRexx feature, rexxref.pdf
documents it in full. You can therefore from now on forgo the " | rxqueue" pipe, if you want.
---rony
On 29.04.2020 14:09, Rony wrote:
Hi Chris,
*very* impressive!
Had to test it on Windows where in principle it works (having ansicon installed, cf.
<https://github.com/adoxa/ansicon/releases> for the time being).
One thing that is interesting on Windows: in my case the screen buffer size is 135x3000 (width x
height) the window size is 135 x 45. It seems that the screen buffer size gets used on Windows. Also
the cursor positioning does not quite work (it is placed on the first column almost at the bottom),
though entering text will appear in the first field.
Hope you remain bored :), please keep up your interesting work!
---rony
On 27.04.2020 16:22, Bob Bobskin wrote:OORexx! Just need to decide whether to try version 4.2.0 or dive right into 5.0.0beta. Any
On Monday, 27 April 2020 14:59:12 UTC+1, Bob Bobskin wrote:
I would certainly like to use this TUI. Another good reason for me to switch from Regina to
thoughts? I use Debian Linux.
functionality, I might have).
Chris
It's a bit of fun. I wrote it on oorexx 5 beta (I can't remember if I used any of the new
a black screen, which does nothing).
From my perspective, on various linux platforms, I am finding v5b working well.
I (hope) it displays some good OOP and OOD.
When one can add a password field with this amount of code, it's nice :) >> (my partner disagrees, she looks bemused that anyone can be excited by a box you can type in, in
::class passwordbox subclass inputbox
::method predraw
self~disdata = copies("*",self~length)
if self~hasFocus = .true then do
self~disdata = self~disdata ||" P "
end
Substantial update made to improve behaviour.
Would love to have some test feedback on it.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 295 |
Nodes: | 16 (3 / 13) |
Uptime: | 09:22:05 |
Calls: | 6,644 |
Calls today: | 4 |
Files: | 12,190 |
Messages: | 5,326,327 |