r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[!REBOL3 GUI]

Graham
24-Jan-2010
[187]
Or maybe the docs are just not upto date
Ashley
25-Jan-2010
[188x3]
I've spent a bit of time going over R3/View and believe it now has 
all the "building blocks" required to build a modern/fast gob! based 
GUI. The amazing thing is that these building blocks are the 10 natives 
that View adds [to Core]. They are:

	gob!
	caret-to-offset
	cursor
	draw
	effect
	map-event
	map-gob-offset
	offset-to-caret
	show
	size-text


With these 10 natives (gob! is actually a type!) we should be able 
to construct simple but powerfull gob!-based GUIs with a smaller 
mezz footprint than R2. My preliminary conversion of RebGUI to R3 
seems to take about 50% the code to do the same thing [compared to 
R2] ... very promising at first glance.


To get a feeling for how tight the code can be the next post is the 
entire [skeleton] source of a working gob!-based GUI.
ctx-rebgui3: make object! [

	cursors: make object! [
		app-start: 32650
		hand: 32649
		help: 32651
		hourglass: 32650
		arrow: 32512
		cross: 32515
		i-shape: 32513
		no: 32648
		size-all: 32646
		size-nesw: 32643
		size-ns: 32645
		size-nwse: 32642
		size-we: 32644
		up-arrow: 32516
		wait: 32514
	]

	colors: make object! [
		page: white
		edit: white
		text: black
		true: leaf
		false: red
		link: blue
		theme: [165.217.246 0.105.207 0.55.155]
		outline: [207.207.207 160.160.160 112.112.112]
	]

	metrics: make object! [
		cell: 4
		gap: cell * 2
		line: cell * 5
		margin: cell * 4
		margin-size: as-pair margin margin
		radius: 2
	]

	;	Private functions

	set 'make-gob make function! [[

  spec [block!] ; offset, size and one or more attribute/value pairs
		/data object
		/local size text gob axis
	][
		size: spec/2
		if any [negative? size/x negative? size/y] [
			text: select spec 'text
			all [block? text text: first find text string!]

   size: 8x4 + size-text make gob! compose [size: 9999x9999 text: (text)]
			all [negative? spec/2/x spec/2/x: size/x]
			all [negative? spec/2/y spec/2/y: size/y]
		]
		gob: copy []
		;	attributes are (text, color, effect, image and draw)
		foreach [attribute value] spec [
			switch attribute [
				box [
					attribute: 'draw
					value: compose [
						pen (get value/1)
						line-width 1
						fill-pen (get value/2)
						box 0x0 (spec/2 - 1x1) (metrics/radius)
					]
				]
				pill [
					attribute: 'draw
					axis: either spec/2/x >= spec/2/y [2] [1]
					value: compose/deep [
						pen (colors/outline/3)
						line-width 1

      grad-pen linear (spec/2/:axis * .1) (spec/2/:axis * .9) (all [axis 
      = 2 90]) [(colors/outline/1) (white) (colors/outline/1)]
						box 0x0 (spec/2 - 1x1) (metrics/radius)
					]
				]
			]
			append gob reduce [attribute value]
		]
		spec: gob

  gob: make gob! compose [offset: spec/1 size: spec/2 (to set-word! 
  spec/3) spec/4 data: (make object! any [object copy []])]
		foreach [attribute value] skip spec 2 [

   append gob make gob! compose [offset: 0x0 size: spec/2 (to set-word! 
   attribute) value]
		]
		gob
	]]

	;	Public functions

	set 'display make function! [[
		title spec

  /local gob xy max-x max-y left-to-right? after-count after-limit 
  here arg append-widget widget last-widget word
		action
		handler
		size
		text
		color
	][
		xy: metrics/margin-size
		max-x: xy/x
		max-y: xy/y
		left-to-right?: true
		after-count: 1
		after-limit: 9999
		
		gob: make gob! compose [text: (title) data: (make object! [])]

		append-widget: make function! [[][
			unless widget [exit]
			unless handler [

    handler: compose/deep [on-down: make function! [[event][(action)]]]
			]
			append gob switch widget [
				bar [

     make-gob compose [(xy) (as-pair max-x - metrics/margin 1) color (colors/outline/3)]
				]
				button [
					all [none? size size: 15x5]

     make-gob/data compose/deep [(xy) (size * metrics/cell) pill none 
     text [center (text)]] handler
				]
				text [
					all [none? size size: 15x5]

     make-gob/data compose/only [(xy) (size * metrics/cell) color (white) 
     text (text)] handler
				]
			]
			last-widget: last gob/pane
			;	1st reverse item?
			unless left-to-right? [

    last-widget/offset/x: last-widget/offset/x - last-widget/size/x
			]
			xy: last-widget/offset
			;	max vertical size
			max-y: max max-y xy/y + last-widget/size/y
			;	horizontal pos adjustments
			all [
				left-to-right?
				xy/x: xy/x + last-widget/size/x
				max-x: max max-x xy/x
			]
			;	after limit reached?
			either after-count < after-limit [
				;	spacing

    xy/x: xy/x + either left-to-right? [metrics/gap] [negate metrics/gap]
				++ after-count
			] [
				xy: as-pair metrics/margin max-y + metrics/gap
				after-count: 1
			]
			all [:word set :word last-widget]
			word: widget: action: handler: size: text: color: none
		]]


  parse reduce/only spec [after bar button handler return reverse rich 
  text] [
			any [
				opt [here: set arg paren! (here/1: do arg) :here] [
					'return (
						append-widget
						xy: as-pair metrics/margin max-y + metrics/gap
						left-to-right?: true
						after-limit: 9999
					)
					| 'reverse (
						append-widget
						xy: as-pair max-x max-y + metrics/gap
						left-to-right?: false
						after-limit: 9999
					)
					| 'after set arg integer! (
						;	return unless this is first widget
						if widget [
							append-widget
							xy: as-pair metrics/margin max-y + metrics/gap
						]
						after-count: 1
						after-limit: arg
					)
					| 'handler set arg block! (handler: arg)
					| 'rich set arg block! (text: arg)
					| [set arg integer! | set arg pair!] (size: arg)
					| set arg string! (text: arg)
					| [set arg tuple! | set arg none!] (color: arg)
					| set arg block! (action: arg)
					| set arg set-word! (append-widget word: :arg)
					| set arg word! (append-widget widget: arg)
				]
			]
		]

		append-widget
		gob/size: metrics/margin-size + as-pair max-x max-y
		gob/offset: system/view/metrics/work-size - gob/size / 2
		append system/view/screen-gob gob
		show system/view/screen-gob
	]]

	set 'undisplay make function! [[gob][
		remove find system/view/screen-gob gob
		show system/view/screen-gob
	]]

	;	Start global GUI event handler

	active-gob: none
	system/view/event-port: open [scheme: 'event]

 system/view/event-port/awake: make function! [[event /local evt gob][
		evt: map-event event
		gob: evt/gob
		while [not object? gob/data] [gob: gob/parent]
		if all [event/type = 'move gob <> active-gob] [
			attempt [active-gob/data/on-away event]
			active-gob: gob
			attempt [active-gob/data/on-over event]
		]
		evt: to word! ajoin ['on- event/type]
		attempt [gob/data/:evt event]
	]]
]
add a closing ']'. An example app is:

blk: copy []
foreach word words-of ctx-rebgui3/cursors [
	append blk compose/deep [
		text (form word) handler [

   on-over: make function! [[event][cursor (ctx-rebgui3/cursors/:word)]]

   on-away: make function! [[event][cursor ctx-rebgui3/cursors/arrow]]
		]
	]
]

display "Test Window" compose [
	text 83x10 rich [size 36 center red "Reb" black "GUI" leaf "3"]
	after 5
	(blk)
	return
	bar
	reverse
	button "Close" [undisplay event/gob]
	button "Open" [
		display "Alert" [
			after 1
			text 50x5 "Some more text."
			bar
			reverse
			button "Close" [undisplay event/gob]
		]
	]
]
Graham
25-Jan-2010
[191]
why post these examples to r3 chat so that we can try them ...
Ashley
25-Jan-2010
[192]
Even better, I'll upload it as a script to my website. Oh, and the 
above app example is missing an important line at the end:

	wait system/view/event-port
Graham
25-Jan-2010
[193]
altme right click copy doesn't work for me ...
Ashley
25-Jan-2010
[194]
do http://www.dobeash.com/gui.r
Pekr
25-Jan-2010
[195]
hehe, so we might get RebGUI 3 sooner, than VID3 :-)
Henrik
25-Jan-2010
[196]
Ashley, are you taking it in the same direction as RebGUI?
Ashley
25-Jan-2010
[197]
Yes and no. Yes it's going to be as minimalistic and bloat free as 
before ... no as I'm aiming for something that allows seperation 
of form and function. RebGUI has a number of limitations that under 
R2 were problematic to resolve but under R3 are doable.
Henrik
25-Jan-2010
[198]
Thanks. All I need to know.
amacleod
25-Jan-2010
[199]
That's awsome!
Geomol
25-Jan-2010
[200]
Ashley, interesting!
NickA
25-Jan-2010
[201]
Ashley, your work is really appreciated!
Reichart
25-Jan-2010
[202]
That is very cool...
Claude
25-Jan-2010
[203]
impressive thank you .... keep going ;-)
Gregg
25-Jan-2010
[204]
Wonderful Ashley.
GiuseppeC
26-Jan-2010
[205]
Nice Ashley. Waiting to see RebGUI in R3. Your project could be a 
big step forward for REBOL
Pekr
26-Jan-2010
[206]
Ashley - maybe you can "just" write a low level layer of RebGUI3 
in such a way, that upper layers (widgets) code will require no change 
to its code? Having RebGUI available for R3 could boost R3 usage 
...
Janko
26-Jan-2010
[207x2]
screenshots screenshots! :)
ok, I ran it :)
Ashley
28-Jan-2010
[209]
Reposting from R3 chat (which seems a bit quiet lately).


I've been looking at the rich text gob! functionality and it seems 
the following dialect commands are supported:

	anti-alias logic!
	bold [off]
	italic [off]
	underline [off]
	size integer!
	left|center|right
	drop integer!
	font object!
	para object!
	caret object!
	scroll pair!
	string!


Are there any I've missed? Any doco on this yet? I havn't figured 
out how to use drop or caret yet. Anyone have any working examples 
for these?


A design question: is there any reason for retaining font and para 
support given that we could move the few remaining unsupported words 
out of those objects and into the dialect itself? (e.g. have the 
dialect directly support font names and valign words).


Also, it would be nice if we had control over the default font name, 
size and alignments [at the very least]. Perhaps a system/view/text 
object?
Steeve
28-Jan-2010
[210]
drop discards the n previous pushed commands in the block stream.

[italic "italic" bold "bold+italic" drop 2 "no-more-bold-italic" 
]
Henrik
28-Jan-2010
[211]
there is something regarding 'drop that may cause crashes. this will 
be fixed, when cyphre gets around to it.
Steeve
28-Jan-2010
[212]
The CARET object is tricky (it handles the cursor position and the 
selected area (for hilighting), see gui.r for more infos.
Cyphre
28-Jan-2010
[213]
Ashley, all current keywords of the richtext dialect can be found 
in system/dialects/text. There is not much docs about it yet but 
I'll tyr to gather some examples and post here.

I'm open to discuss the design improvements as so far not much people 
used the dialect so I'm sure we can enhance it for some useful things.

Does anyone know if there is R3 rich text group already on this world? 
Or should we create new one?
Steeve
28-Jan-2010
[214]
!area enhanced text ?
Henrik
28-Jan-2010
[215]
I think that's a product, so it's better with an R3 specific group.
Pekr
28-Jan-2010
[216]
this group is imo ok, no? Or - REBOL 3 View, if we want to separate 
low-level engine from the GUI one ... but I see no reason for it 
...
Gabriele
29-Jan-2010
[217]
Ashley, my VID had examples of using caret for fields etc. I assume 
Carl's one too...
Henrik
29-Jan-2010
[218]
Gabriele, maybe you should upload your old GUI to R3 chat for reference.
Pekr
29-Jan-2010
[219]
I think R3-alpha is still alive as well, so Gab's GUI should be there 
too. It was many files IIRC. The question also is, if it will work 
with new R3 releases. So maybe it is easier for ppl to just get to 
r3-alpha ... I think each of us has access there :-) (note: I understand 
your message, why you want it in R3 chat, I just tried to point out, 
it is already available)
Gabriele
29-Jan-2010
[220]
Henrik: that would surely increase confusion by many levels. a great 
idea :P
Henrik
29-Jan-2010
[221]
Gabriele, no it wouldn't. Don't upload to the same header.
BrianH
29-Jan-2010
[222]
Create a subheading of Community/Libraries (621) and upload it there.
Ashley
29-Jan-2010
[223x4]
Got caret working, but it's overly complex IMHO, as in:

s: "A bit of text."

c: make object! compose/deep [
	caret: copy [[(s)] (tail s)]
	start: copy [[(s)] (at s 3)]
	end: copy [[(s)] (at s 6)]
]


show append clear system/view/screen-gob make gob! [text: [s caret 
c]]
Any other dialect word (e.g. scroll, size, bold, color) prevents 
caret from working (i.e. if you use caret you are forced to use font 
and para objects).

Also, it seems the caret object could be simplified down to:

	caret: make object [
		caret: start: end: none
	]


Are the blocks (caret/1 start/1 end/1) supposed to have any other 
values in them? (e.g. color tuple, 2nd string!, etc)
system/dialects/text is handy. Seems the shortcut b, i, u and nl 
words are not yet implemented/working. 'drop is cute, and I note 
that 'drop without an argument defaults to drop 1.
Any way of using anti-alias with caret? Seems:

	[text: [anti-alias on s caret c]]


kills the caret and font/para objects don't have an anti-alias word.
Cyphre
29-Jan-2010
[227x2]
Ashley, I can't see most of your problems when using r3-a96.exe
Please try:
do http://cyphre.mysteria.cz/tests/caret-test.r

You should see it works correcty.


The only problem I was able to repro is that the shortcuts b,i,u 
and nl aren't working...probably some 'regression' in newer builds 
as I remember it worked before.
regarding the caret obect:

the CARET, HIGHLIGHT-START and HIGHLIGHT-END fields must be defined 
as block! of the following format:
[block! string!]


the first block! value must be the gob/text block! at the index position 
of the text element


the second string! value must be string of the text element at specified 
position


You cannot just copy the first block as in your example above. You 
have to set the block to the position where the text element really 
is in the dialect block(this way the text engine can use the index). 
This part is a bit tricky but it was decided after long discussion 
with Carl. I proposed to use simple integer! for the index, but Carl 
wanted it to be this way which is easier as you can manipulate the 
block index easily without the need to use INDEX? to get the integer.
Ashley
29-Jan-2010
[229]
Thanks, your example (and explanation) makes it all clear now (I 
only tested/debugged with a single string before).
Graham
3-Feb-2010
[230]
Is the lack of a table face ( or whatever the new jargon is ), a 
reflection of the difficulty of building it, or some other issues 
with the gui engine?
Henrik
3-Feb-2010
[231x2]
lack of time. building it should be fairly trivial.
the resize engine is still the main issue for troubles and so the 
best result looks something like this:

http://rebol.hmkdesign.dk/files/r3/gui/166.png
Graham
3-Feb-2010
[233]
Henrik, we can disable resizing until that is fixed!
Henrik
3-Feb-2010
[234x2]
no we can't. the layout engine depends on it for weighting elements 
at their "correct" sizes. the resize engine must be fixed in order 
to fix layout.
Weighting happens by "pushing" other elements aside, like soap bubbles 
pushing against eachother. The bigger the element is, the more it 
pushes. But space is also divided between the number of elements 
available in a given group, so a group of 5 buttons takes a little 
more space than a group of 3 buttons.


That gives the problem you see with strange spacing before and after 
the vertical scroller, because it's size is not big enough to provide 
push. and the other elements are too small to provide enough push. 
Combining the size of the face and the push factor is why resizing 
is broken.

But there are more bugs in it than that. If you push too much, the 
elements overflow and will be clipped by the right and bottom edges. 
Furthermore, the calculation of space to the right edge and bottom 
edge is also broken. It's almost impossible to predict in your head 
how the layout will look.


I'd like to replace the resize engine with something more concrete, 
perhaps with springs instead and fixed pixel sizes (oh, maybe similarly 
to what the VID Extension Kit does) or depending on whether Carl 
get's started again with his specs list (which I unfortunately can't 
locate). I hope we'll get to start this month.
Graham
3-Feb-2010
[236]
Gabriele, were you going to upload your GUI system as well?