Showing posts with label VID. Show all posts
Showing posts with label VID. Show all posts

July 17, 2017

0.6.3: macOS GUI backend

This new Red release contains ~830 commits, closes 86 issues, and brings a large number of  new features. The main one is official support for the macOS GUI, through a new backend for the View engine.


For readers not familiar with our GUI system, you can get a quick overview in a previous article.

In a nutshell, it is a dynamically-built reactive object tree, with:
  • pluggable backends (full support for Windows and prototype for GTK and Android)
  • full 2D vector graphics support (a large subset of SVG)
  • direct reactive programming support (not FRP style for now)
  • a declarative DSL for GUI building and layout management
  • a declarative DSL for 2D graphics

The macOS backend supports all the same features as the Windows backend, except the following, yet to be implemented:
  • fill-pen pattern, fill-pen bitmap and diamond gradient in Draw.
  • matrix transformations on pen and fill-pen in Draw.

The GUI console for macOS will be available in the 0.6.4 branch, so is not part of this release. The View module, though, is compiled in the CLI console by default on macOS, so no show-stopper there.

Here are a few short examples, starting with a GUI Hello World!:
    view [text "Hello Mac World!"]

A tiny demo script (hopefully, it should get us an office at Station F, right? ;-)):
    view [
        t: text "French Touch! " on-time [move t/text tail t/text]
        base 21x15 draw [
            pen off
            fill-pen blue  box 0x0  6x14
            fill-pen white box 7x0  14x14
            fill-pen red   box 14x0 20x14
        ] return
        button "Start" [t/rate: 10]
    ]

A small reactive text size measuring tool (one of our test scripts):
    view [
        style txt: text right
        txt "Text" f: area 200x80 
            font [name: "Comic Sans MS" size: 15 color: black]
            return

        txt "Size in pixels" text "0x0"
            react [[f/text f/font] face/text: form size-text f]
            return
 
        txt "Font name" drop-list 120
            data  ["Arial" "Consolas" "Comic Sans MS" "Times"]
            react [f/font/name: pick face/data any [face/selected 3]]
            return
  
        txt "Font size" s: field "15" react [f/font/size: s/data]
        button "+" bold 40 [s/data: s/data + 1]
        button "-" bold 40 [s/data: max 1 s/data - 1]
        return
    ]


Generating macOS bundle apps is made simple by our toolchain, just use the -t macOS target when compiling, for example using our SVG Tiger demo:
   $ red -o ~/Desktop/ -t macOS tiger.red
This will produce a tiger.app bundle on the Desktop:



Cross-Platform GUI Metrics

In order to cope with different UI guidelines across GUI platforms, this release also introduces an experimental rule-oriented GUI rewriting engine, capable of modifying a face tree dynamically according to pre-set rules. It is integrated as a last stage in VID (Visual Interface Dialect) processing. The currently implemented rules are per-platform for now (more general, cross-platform rules are also planned):

Windows rules:
  • color-backgrounds: color the background of some colorless faces to match their parent's color
  • color-tabpanel-children: Like color-backgrounds, but tab-panel specific
  • OK-Cancel: buttons ordering rule, puts Cancel/Delete/Remove buttons last
macOS rules:
  • adjust-buttons: use standard button sub-classes when buttons are narrow enough
  • capitalize: capitalize widget text according to macOS guidelines
  • Cancel-OK: buttons ordering rule, puts Ok/Save/Apply buttons last

To give you a quick grasp about why that feature matters and what it is capable of, here is a simple example, which leverages the buttons ordering and capitalization rules:
    view [
        text "Name" right 50 field return
        text "Age"  right 50 field return
        button "ok" button "cancel"
    ]

You can see, side-by-side, the macOS and Windows generated forms. Notice the button text and ordering, yes, they differ from the source code! The GUI rules have ensured that:
  • the buttons are ordered according to each platform's guidelines, "Ok" last on macOS, "Cancel" last on Windows.
  • the button's labels are properly capitalized on macOS.

This small example just demonstrates the concept, but actually, there is no limit on how much it could alter the UI and how far it could go with the post-processing.

As it is still experimental, if it causes you any trouble, you can easily disable it using:
    system/view/VID/GUI-rules/active?: no
You can also remove rules selectively, by modifying the content of the following lists:
    system/view/VID/GUI-rules/OS/Windows
    == [
        color-backgrounds
        color-tabpanel-children
        OK-Cancel
    ]

    system/view/VID/GUI-rules/OS/macOS
    == [
        adjust-buttons
        capitalize
        Cancel-OK
    ]
This allows you total control where needed, but also helps you conform to UI guidelines with no effort, saving everyone time. Not only do you not have to tweak your code for each platform when you write it, when a new platform is added, you won't have to change your code to support it. In a world where getting one detail wrong may keep you out of an app store, or prevent you from being a "certified" app, this is huge. It should also be possible to use the rule engine to write a guideline linter, where you could get a report of what rules will be applied to your VID code on each platform. By "report", we don't mean just a text listing, but it could highlight elements in the UI that were processed by rules. Having a system that helps you is great. Having a system that tells you how it helped you is even better.

There are tons of possible rules we could implement, if you have ideas for great ones, please let us know by joining us in our online chat room on Gitter or, if you prefer, by posting on our mailing-list.


Other changes in 0.6.3

Core language

The biggest addition to the core language in this release is the date! datatype, which supports all Rebol's date! datatype features and more. The additions include support for a large range of ISO 8601 date formats. About 350 unit tests have been written so far. The full documentation is available here.

Here are a few examples of accepted input formats:
    >> 1999-10-5
    == 5-Oct-1999

    >> 5-October-1999
    == 5-Oct-1999

    >> 5/9/2012/6:00
    == 5-Sep-2012/6:00:00

    >> 4/Apr/2000/6:00+8:00
    == 4-Apr-2000/6:00:00+08:00

    >> 2017-07-07T08:22:23Z
    == 7-Jul-2017/8:22:23

    >> 2017-W23-5
    == 9-Jun-2017

    >> 2017-153T105000-4:00
    == 2-Jun-2017/10:50:00-04:00
Math and other operations are fully supported:
    >> d: now
    == 14-Jul-2017/16:04:07+08:00

    >> d + 10
    == 24-Jul-2017/16:04:07+08:00

    >> d + 100
    == 22-Oct-2017/16:04:07+08:00

    >> d - 24:00
    == 13-Jul-2017/16:04:07+08:00

    >> d - 01/01/2010
    == 2751

    >> d/month: d/month - 5
    >> d
    == 14-Feb-2017/16:04:07+08:00

    >> d/yearday: random 365
    >> d
    == 1-Aug-2017/16:04:07+08:00

    >> sort [1/2/2018 1999-5-3/10:30:28 29-2-1980]
    == [29-Feb-1980 3-May-1999/10:30:28 1-Feb-2018]

    >> random 01/01/2018
    == 15-Dec-1248
Red also adds three new accessors:
  • /timezone: changes the zone and adjusts time accordingly (UTC-invariant)
  • /week: gets/sets the week of the year, starting on Sunday.
  • /isoweek: gets/sets the ISO week of the year, starting on Monday.

Conversions to/from Unix epoch time are also built-in:
    >> to-integer 1/1/1970
    == 0

    >> to-integer now
    == 1500020743

    >> to-date 1000000000
    == 9-Sep-2001/1:46:40

Other Core Additions

New functions were added to the existing simple IO API:
  • delete: deletes a file or an empty folder.
  • size?: returns the size in bytes of a file.

The do native now accepts a URL argument. For example:
   do https://raw.githubusercontent.com/red/code/master/Showcase/eve-clock.red
Run-time error reports now include a compact call stack trace:
    foo: does [1 / 0]
    bar: does [foo]

    bar
    *** Math Error: attempt to divide by zero
    *** Where: /
    *** Stack: bar foo

A set of new functions for disk-cached remote file access is now available: do-thru, exists-thru?, load-thru, read-thru, path-thru. They work in the same way as their normal counterparts, except that the retrieved file is cached locally, so on their next access, the locally cached copy will be used.

The system object has been extended with:
  • system/options/cache: points to the cache folder used by the Red toolchain.
  • system/options/thru-cache: points to the cache folder used by *-thru functions.
  • system/catalog/accessors: Path accessors available, per datatype.

The browse native can now work on macOS (it opens the default browser on a given URL).

Rudolf Meijer did a huge job, gathering currently implemented rules for math operations on mixed datatypes. This has resulted in documenting and improving those rules, better defining the resulting datatype for all math operations.

More changes:
  • Now is now fully operational and can return current date and time.
  • Wait now accepts a time! value argument
  • Improved make and to url! construction when the spec argument is a block.
  • Auto-detect older Intel CPU on Windows platform when building the console.
  • Even? and odd? now support time! values as argument.
  • R/S compiler can now output a function address map for verbosity >= 3
  • Improved min and max natives support for pair! and tuple!(now min/max is applied per dimension to pair! and tuple!, and can work with a number! as second argument).
  • -t compilation option does not force release mode anymore if target is the same OS.
  • Source file name in now displayed on syntax errors at compile-time.

LibRed

LibRed has been improved, thanks to the work of Joa-quim on a libRed binding for the Julia language, providing Julia with the full power of Red's native GUI system. Several new functions were added to libRed API:
  • redBinary(): constructs a binary! value from an external byte array.
  • redImage(): constructs an image! value from various possible external byte arrays.
  • redGetField(): gets the value of an object's word.
  • redSetField(): sets the value of an object's word.
There is more info about them in the libRed documentation.

LibRed's robustness has also been vastly improved. LibRed API functions can now catch null pointer arguments, and even invalid pointers passed to the libRed API. In these situations, libRed returns a Red error! value.

View engine

In addition to the macOS backend, a new test backend is included in this release. This backend works by simulating a GUI backend for testing purposes. It is still experimental but works fine so far. We should be able to write a whole suite of unit tests for the View engine and VID dialect now and run them on a headless Linux server (like our Travis CI). In the same way, this backend enables Red users to unit test their GUI apps with minimal effort (though more tooling on top of the current backend is welcome).

The working principle is simple: use view/no-wait to produce your GUI without starting the event loop, then form your tests using the following model:
  • Set the focus on the face where you want to simulate an event (using set-focus).
  • Trigger an event (using do-event).
  • Test if the result of the event conforms to your expectations.

Here is an extract from a short test script:
    view/no-wait [
        hello: button "Hello" [print "ok"]
        name: field
    ]

    set-focus hello
    do-event 'click

    set-focus name
    do-event/with 'key #"4"
    do-event/with 'key #"2"
    do-event/with 'key 'enter

    probe name/text
    probe name/data
Using this test backend requires setting some options in the header (see the linked script's header), and compilation in release mode.

Another notable addition is the foreach-face function, which powers our GUI rewriting rules engine. It allows easy traversal of a face tree (depth-first), selecting only the faces you need to process. The syntax is:
    foreach-face <root> [<actions>]
    foreach-face/with <root> [<actions>][<conditions>]
    
    <root>       : root face of the tree.
    <actions>    : actions to perform on matched faces.
    <conditions> : optional conditions for selecting faces.
The first version applies the actions block to all faces, while the second one (/with) will select only faces matching the conditions block (which needs to return a true value to act on the current face). Both the actions and conditions blocks have an implicit face word defined, which refers to the current face in the tree. For example:
    do %tests/vid.red
    collect [foreach-face/with win [keep face/text][find face/text #"i"]]
will return:
    == ["China" "in panel" "option 1" "option 2" "option 3" "option 4"]
Here is a more sophisticated example using foreach-face to dynamically localize labels and adjust buttons size and position accordingly, so that they fit the text nicely:

    langs:  ["English" "French" "中文"]
    labels: [
        ["Name" "Age" "Phone #" "Cancel" "Submit"]
        ["Nom" "Age" "Tél." "Abandon" "Envoyer"]
        ["名字" "年龄" "电话" "取消" "提交"]
    ]
    set-lang: function [f event][
        root: f/parent
        condition: [all [face/text face/type <> 'drop-list]]

        list: collect [foreach-face/with root [keep face/text] condition]
        forall list [append clear list/1 labels/(f/selected)/(index? list)]

        foreach-face/with root [
            pads: any [metrics?/total face 'paddings 'x 0]
            prev: face/size/x
            face/size/x: pads + first size-text face
            face/offset/x: face/offset/x + ((prev - face/size/x) / 2)
        ][face/type = 'button]
    ]
    view [
        style txt: text right 45
        drop-list data langs select 1 on-change :set-lang return
        group-box [
            txt "Name"  field return
            txt "Age"   field return
            txt "Phone" field
        ] return
        pad 15x0 button "Cancel" button "Submit"
    ]

You can also detect window resizing events, and use the current window size to resize and position faces dynamically.

It is now also possible to change the mouse cursor shape, using pre-defined values, setting a custom image to face/options/cursor, or using the cursor keyword in VID, followed by an image! value or one of the following keywords: arrow, I-beam, hand, cross.

Here is an example:

Other changes:
  • Lit-words are now accepted in flags facet blocks.
  • New Shape dialect command: close.
  • Changed default background color to white in tab-panel (Windows).
  • Added system/view/metrics (used mostly by VID, for more accurate sizing/positioning).
  • Added accelerated? option in face, when set to true, for faster/smoother face rendering (only base faces). Z-ordering is then only honored between accelerated faces.
  • When a button has the focus, pressing enter key will trigger a click event.
  • Renamed enable? facet to the more correct enabled?.
  • New function: set-focus (sets the focus on a given face, important for GUI testing).
  • New class option in face/options, allows setting a sub-class of a native control.
  • text-list now accepts a data keyword and any-string! values as input. This lets you to feed the list with values from VID. For example:
    view [
        text-list data parse
            read https://api.github.com/repos/red/red/events
            [collect [any [thru "message" 3 skip keep to ["\n" | {"}]]]]
    ]

The above script is just a single expression using two DSLs. I let you meditate on that. ;-)


VID dialect

VID has received many enhancements too. The most significant are:
  • more accurate sizing and positioning of native widgets using OS metrics
  • addition of alignment control, extending across/below layout modes.

So, it is now possible to add optional alignment keywords for the two linear layout modes:
  • across: top, middle, bottom
  • below: left, center, right
Those keywords can also follow the return command, if changing the alignment mode of the next row/column is required. The defaults are top and left. Here is a short example:
    view [
        style chk: check "Option" data yes
        style vline: base 2x60 red
        across top    vline button "Ok" text "Text" field chk return
        across middle vline button "Ok" text "Text" field chk return
        across bottom vline button "Ok" text "Text" field chk
    ]

Other changes:
  • New on-created event, triggered just after a face has been shown for the first time.
  • New strike option for faces: sets the strikethrough font style.
  • New init [<body>] styling option allows you to define a block of code to run when the style is instantiated.
  • later option added to react keyword.
  • Allows data and at keyword argument to be an arbitrary Red expression (see the above text-list example).
  • More robust face options parsing.
  • The default actor for h1 to h5 and text widgets is now on-down.
  • VID now saves the style name for each face in face/options/style.

Parse dialect

A new case command has been added to Parse dialect. Case temporarily changes the case matching mode, for the next rule only.

Syntax:
  case <mode> <rule>

  <mode>: TRUE (case-sensitive matching) or FALSE (case-insensitive) (logic!, word!)
  <rule>: rule on which the local case matching mode is applied to.

Red/System dialect

For newcomers, Red/System is Red's built-in system programming dialect, offering a Red-like syntax with C-level semantics (and many improvements over C, like namespaces, exceptions, RTTI,...).

This release brings an important improvement: structures can now be passed and returned by value on internal and external function calls. They can also now be inlined in other structures. This is achieved by putting the value keyword after a struct! type declaration:
 name [struct! [<fields>] value]
Passing structs by value is sadly not formally specified in C language, resulting in incompatible compiler-specific ABIs. Moreover, those ABIs are not documented, or only partially, so gathering all the right information was painful and time consuming. Just to illustrate how bad the situation is, after spending days researching all the various C compilers ABI, I was able to answer a stackoverflow question about returning C structs by value, which was left unanswered for 6 years... I might write a synthetic article about those C ABIs someday, from my notes, as I could not find such documentation online. Anyway, the hard work has been done for you. Red/System now implements the most common ABI for each platform:
  • Windows: Microsoft Visual C ABI
  • Linux: gcc/Clang ABI (with support for ARM-specific ABI) 
  • macOS: Clang ABI

In addition, more stack-oriented features are now supported:

The new use feature allows you to create local variables anywhere in a function body. It is useful for splitting long functions and creating local variables in macros.

The ARM backend has also been enhanced significantly in this new release:
  • fixes and improvements to soft integer division routine.
  • fixes non-passing unit tests on floats.
  • better AAPCS conformity and various bug fixes.
  • improved accuracy of overflow detection in multiplication.

Console

ANSI escaping sequences are now supported in the Red CLI console, thanks to Oldes. See this pull request for more info and a screenshot.

Other console changes:
  • improved auto-completion, now completes the longest common substring.
  • auto-detect older Intel CPU (non-SSE3) on Windows platform when building console.
  • system/console/size now provides the size of the console in columns and rows

What's Next?

The 0.6.4 version will mostly focus on the GUI console, not only bringing it to macOS, but also extending it greatly. It should be merged into the master branch in the next few days, as the new GUI console is almost finished.

The 0.6.5 version is for Android, and is already being worked on in a separate, private repo. We will merge it with the red/red public repo once it's ready, because we need control on the PR timing and the Android release. It will be a big one, unlike what you've seen so far. ;-)

In the meantime, and as usual, enjoy and have fun!

March 25, 2016

0.6.0: Red GUI system

Five years ago, when I started writing the first lines of code of what would become later the Red/System compiler, I had a pretty good picture already of what I wanted to achieve with Red, and all the ideal features that should be included, just not sure how much time and efforts it would require to have them. Two years and half ago, baby Red printed its first output. And today, we celebrate a major step forward with the addition of a brand new GUI system entirely written in Red itself! What a journey!



Here it is, the long awaited 0.6.0 release with its massive 1540 commits! The major new features are:
  • View engine, with Windows backend (from XP to 10)
  • VID dialect
  • Draw dialect
  • Reactive GUI programming
  • GUI console
  • Simple I/O support for files and HTTP(S) queries.
  • Codecs system with following codecs available: BMP, GIF, JPEG, PNG
  • Objects ownership system

All those additions made our Red executable grow from 767 KB to 910 KB (Windows platform), sorry for the extra 143 KB, we will try to [red]uce that in the future. ;-)

Let's start with the elephant in the room first, the GUI system. Here is an architecture overview:

Only the Windows backend is fully usable for now, Android and OS X are work-in-progress, Linux (using GTK) will follow soon, iOS will come later this year. Also, we have other targets in mind, like JS/HTML which are not scheduled yet, but could come this year too.

Red/View

First let me mention that View, VID and Draw were invented by Carl Sassenrath (of Amiga fame) in the Rebol language, a long time ago. Red's version retains all the best features and pushes the boundaries of simplicity even further. The main features of our View engine are:
  • A live updating mode that reduces the need to a single view function in most cases.
  • Full abstraction over rendering backends.
  • Two-way binding using live objects.
  • Event bubbling/capturing stages.
  • Built-in drag'n drop support for most face types.
  • Gestures support (experimental).
  • Native widgets support.
  • Full integration with the OS features.
  • Flexible backend support that can be mapped to virtually any kind of UI library.

The current list of supported widgets is: base, text, button, check, radio, field, area, text-list, drop-list, drop-down, progress, slider, camera, panel, tab-panel, group-box.

Next releases will bring more widgets, like: table, tree, divider, date/time picker, web-view and many others!

For more info about View, see the View reference document.

Main differences between Red/View and Rebol/View are:
  • Red relies on native widgets, Rebol has custom ones only, built over a 2D vector library.
  • Red faces are synchronized with their widgets on display in realtime by default, Rebol faces require manual calls to many functions for keeping faces and widget updated.
  • Red introduces reactive GUI programming.

Red/View will update both face and graphic objects in realtime as their properties are changed. This is the default behavior, but it can be switched off, when full control over screen updates is desirable. This is achieved by:
    system/view/auto-sync?: off
When automatic syncing is turned off, you need to use show function on faces to get the graphic objects updated on screen.

VID dialect

VID stands for Visual Interface Dialect. It is a dialect of Red which drastically simplifies GUI construction. VID code is dynamically compiled to a tree of faces, feeding the View engine. You can then manipulate the face objects at runtime to achieve dynamic behaviors. VID offers:
  • Declarative programming.
  • Automatic layout system.
  • Cascading styles.
  • Default values for...everything.
For more info about VID, see the specification.

In case you are reading about Red or Rebol for the first time, here are a few code demos to show how simple, yet efficient, is our approach to GUI programming:

A GUI Hello word
    view [text "Hello World"]
Greet the name you type in the field
    view [name: field button "Hi" [print ["Hi" name/text]]]
A simple reactive relations demo, drag the logo around to see the effect
   view [
        size 300x300
        img: image loose http://static.red-lang.org/red-logo.png
        return
        shade: slider 0%
        return
        text bold font-size 14 center "000x000" 
            react [face/text: form img/offset]
            react [face/font/color: white * shade/data]
    ]
 
Simple form editing/validating/saving with styles definitions
   digit: charset "0123456789"
    view [
        style label: text bold right 40
        style err-msg: text font-color red hidden
    
        group-box "Person" 2 [
            origin 20x20
            label "Name" name: field 150
            label "Age"  age:  field 40
            label "City" city: field 150
            err-msg "Age needs to be a number!" react later [
                face/visible?: not parse age/text [any digit]
            ]
        ]
        button "Save" [save %person.txt reduce [name/text age/text city/text]]
    ]
    set [name age city] load %person.txt
    ?? name ?? age ?? city

You can run all those examples by copy/pasting them one-by-one into the Red console for Windows. To get the console, just download it and double-click the Red binary, wait ~20 seconds for the console to be compiled for your OS (yes, that little file contains the full Red toolchain, runtime library and console source code), paste the code and have fun. ;-)

Draw dialect

Draw is a 2D vector-drawing dialect which can be used directly, to render on an image, in faces for local rendering, or specified through VID. It is still a work in progress as not all features are there yet. We aim at full Rebol/Draw coverage and full SVG compatibility in the not-too-distant future.

A simple example of Draw usage:
    shield: [
        fill-pen red   circle 50x50 50
        pen gray
        fill-pen white circle 50x50 40
        fill-pen red   circle 50x50 30
        fill-pen blue  circle 50x50 20
        
        pen blue fill-pen white
        polygon 32x44 45x44 50x30 55x44 68x44 57x53 60x66 50x58 39x66 43x53
    ]
    
    ;-- Draw in a draggable face, in realtime.
    view [
        size 300x300
        img: box 101x101 draw shield loose
        at 200x200 base white bold react [
            [img/offset]
            over?: overlap? face img
            face/color: get pick [red white] over?
            face/text: pick ["Hit!" ""] over?
        ]
        button "Hulk-ize!" [replace/all shield 'red 'green]
        button "Restore"   [replace/all shield 'green 'red]
    ]
Copy/paste the above code example in a Red console on Windows, and become an Avenger too! ;-)

For more info about Draw, see the specification.

Main differences between Red/Draw and Rebol/Draw:
  • Red does not yet cover all the commands of Rebol/Draw yet.
  • Red's version allows commands to be grouped in blocks, ease-ing insertion/removal at run-time.
  • Red's version allows commands to be prefixed with a set-word, allowing to save local position in Draw blocks in a word.

Reactive GUI programming

This is a deep topic which should be part of a future separate blog article. So, I will just copy/paste here the little information already in the VID documentation:

Reactions (or reactors, not sure yet which terms is the most accurate) are created using the react keyword, directly from Red code or from VID dialect. The syntax is:
    react [<body>]
    
    <body> : regular Red code (block!).
This creates a new reactor from the body block. When react is used in VID, as a face option, the body can refer to the current face using face word. When react is used globally, target faces need to be accessed using a name.

Reactors are part of the reactive programming support in View, whose documentation is pending. In a nutshell, the body block can describe one or more relations between faces properties using paths. Set-path setting a face property are processed as target of the reactor (the face to update), while path accessing a face property are processed as source of the reactor (a change on a source triggers a refresh of the reactor's code).

Basically, it is about statically-defined relations between faces properties, without caring when or how the reactive expressions will be evaluated. It will happen automatically, when needed. Here are a couple of examples you can copy/paste in the Red console on Windows:

Make a circle size change according to slider's position:
    view [
        sld: slider return
        base 200x200 
            draw  [circle 100x100 5]
            react [face/draw/3: to integer! 100 * sld/data]
    ]

Change the color of a box and a text using 3 sliders:
    to-color: function [r g b][
        color: 0.0.0
        if r [color/1: to integer! 256 * r]
        if g [color/2: to integer! 256 * g]
        if b [color/3: to integer! 256 * b]
        color
    ]

    to-text: function [val][form to integer! 0.5 + 255 * any [val 0]]

    view [
      style txt: text 40 right
      style value: text "0" 30 right bold
    
      across
      txt "Red:"   R: slider 256 value react [face/text: to-text R/data] return
      txt "Green:" G: slider 256 value react [face/text: to-text G/data] return
      txt "Blue:"  B: slider 256 value react [face/text: to-text B/data]
    
      pad 0x-65 box: base react [face/color: to-color R/data G/data B/data]
      return
    
      pad 0x20 text "The quick brown fox jumps over the lazy dog." font-size 14
        react [face/font/color: box/color]
    ]


GUI console

We have a GUI console now, in addition to the existing CLI one!

The GUI console is now the default on Windows platform, and is fully Unicode-aware. The system shell (DOS) console is still available using --cli option:
    red --cli
The GUI console is still in its infancy and will be enhanced a lot in future releases. Anyway, so far, it already supports:
  • history of commands
  • completion on words and object paths
  • multi-line editing for blocks, parens, strings, maps and binaries.
  • navigation using HOME and END keys
  • select/copy/paste using the mouse and keyboard shortcuts
  • auto-scrolling when selecting with the mouse out of the boundaries
  • very fast text rendering
  • automatic vertical scroll bar
  • customizable prompt
Try this cool one-liner for making the prompt more active:
    system/console/prompt: does [append to-local-file system/options/path "> "]

This is how the GUI console looks like:


Simple I/O support

In order to have really some fun with the GUI, we have added some minimal support for blocking IO basic actions covering files and HTTP(S) requests. read and write action are available now. Their /binary, /lines and /info refinement are working. do, load, save have also been extended to work with files and urls.

When not using /binary, read and write are expecting UTF-8 encoded data. Support for ISO8859-1 and other common encoding formats will be available in next release.

The full IO will come in 0.7.0 with ports, full networking, async support and many more features.

Codecs

Codec system support has made his entrance in this release. It is a very thin layer of encoders/decoders for binary data, integrated with load, save and actions which rely on /as refinement. load and save will auto-detect the required encoding format and try to apply the right encoder or decoder on the data.

Currently only image format codecs are provided: BMP, PNG, GIF, JPEG. Any kind of encoding (related to IO) is a good candidate for becoming a codec, so expect a lot of them available in the future (both built-in Red runtime and optionaly installable).

For example, downloading a PNG image in memory, and using it is as simple as:
    logo: load http://static.red-lang.org/red-logo.png
     
    big: make font! [name: "Comic" size: 20 color: black]
    draw logo [font big text 10x30 "Red"]
    view [image logo]
Saving a downloaded file locally:
    write/binary %logo.png read/binary http://static.red-lang.org/red-logo.png
Saving images is not fully functional yet, PNG should be safe though.

Objects ownership system

Red's objects ownership system is an extension of object's event support introduced in previous releases. Now, an object can own series it references, even nested ones. When an owned series is changed, the owner object is notified and its on-deep-change* function will be called if available, allowing the object to react appropriately to any change.

The prototype for on-deep-change* is:
    on-deep-change*: func [owner word target action new index part][...]
The arguments are:
  • owner: object receiving the event (object!)
  • word: object's word referring to the changed series or nested series (word!)
  • target: the changed series (any-series!)
  • action: name of the action applied (word!)
  • new: new value added to the series (any-type!)
  • index: position at which the series is modified (integer!)
  • part: number of elements changes in the series (integer!)
Action name can be any of: random, clear, cleared, poke, remove, removed, reverse, sort, insert, take, taken, swap, trim. For actions "destroying" values, two events are generated, one before the "destruction", one after (hence the presence of cleared, removed, taken words).

When modifications affect several non-contiguous or all elements, index will be set to -1.
When modifications affect an undetermined number of elements, part will be set to -1.

Ownership is set automatically on object creation if on-deep-change* is defined, all referenced series (including nested ones), will then become owned by the object. modify action has been also implemented to allow setting/clearing ownership post-creation-time.

As for on-change, on-deep-change* is kept hidden when using mold on object. It is only revealed by mold/all.

Here is a simple usage example of object ownership. The code below will create a numbers object containing an empty list. You can append only integers to that list, if you fail to do so, a message will be displayed and the invalid element removed from the list. Moreover, the list is always sorted, wherever you insert or poke a new value:
    numbers: object [
        list: []
    
        on-deep-change*: function [owner word target action new index part][
            if all [word = 'list find [poke insert] action][
                forall target [
                    unless integer? target/1 [
                        print ["Error: Item" mold target/1 "is invalid!"]
                        remove target
                        target: back target
                    ]
                ]
                sort list
            ]
        ]
    ]
    
    red>> append numbers/list 3
    == [3]
    red>> insert numbers/list 7
    == [3 7]
    red>> append numbers/list 1
    == [1 3 7]
    red>> insert next numbers/list 8
    == [1 3 7 8]
    red>> append numbers/list 4
    == [1 3 4 7 8]
    red>> append numbers/list "hello"
    Error: Item "hello" is invalid!
    == [1 3 4 7 8]
    red>> numbers
    == make object! [
        list: [1 3 4 7 8]
    ]
Object ownership is deeply used in Red/View, in order to achieve the binding between face objects and the widgets on screen, and the automatic "show-less" synchronization. 

The work on this is not yet completed, more object events will be provided in future releases and the ownership support extended to enable objects to own more datatypes. More documentation will be provided once the work on that will be finished. In the future, its use will be extending to other frameworks and interfaces. Such "reactive objects" will be called "live objects" in Red's jargon.

Red/System changes
  • Full stack traces in debug mode on runtime errors.
  • New compilation directive: #u16 (literal UTF-16LE strings support).
  • Added log-b native function for getting the binary logarithm of an integer.
  • Added equal-string? runtime function for testing c-string! equality.
  • Several improvements to some compiler errors reporting accuracy.
  • Improved function! type support.
  • New compilation option: debug-safe? (for safer stack traces)
  • New --catch command-line option for console to open on script errors.
  • Improved compilation speed of variables assignment.
  • Fixes for broken exceptions support on ARM backend.

Additions to the Red runtime library

New functions

  • show, view, unview, draw, layout, react, size-text, to-image, do-events, dump-face, within?, overlap?, remove-reactor, set-flag, find-flag?, center-face, insert-event-func, remove-event-func.
  • event?, image?, binary?.
  • debase, wait.
  • request-file, request-dir.
  • read, write, exists?, to-local-file, to-red-file, dirize, clean-path, split-path.
  • what-dir, change-dir, list-dir.
  • also, alter, extract, collect, split, checksum, modify, unset.
  • as-color, as-rgba, as-ipv4.
  • cd, ls, ll, pwd, dir. (console-only)
Use help in the console to get more information about each function.

New datatypes

  • binary!
  • event! (Windows only for now)
  • image! (Windows only for now)

Binary! datatype supports all the series actions. Literal base 2, 16 and 64 encodings are available:
    red>> 2#{11110000}
    == #{F0}
    red>> to string! 64#{SGVsbG8gV29ybGQh}
    == "Hello World!"
Event! and image! are a work-in-progress, though image! is already very capable (documentation will be added soon).

Other changes

set and get native improvements:

If A and B are object values, set A B will now set the values in A from B, for the fields they have in common (regardless of the fields definition order in the objects).

Added /only and /some refinements:
  • /only: set argument block or object as a single value
  • /some: `none` values in the argument block or object are not set

o Icons and other "resources" are now supported for inclusion in Windows executables. They can be set from Red's main script header, these are the currently supported options:

  • Icon: file! or block! of files
  • Title: string!
  • Author: string!
  • Version: tuple!
  • Rights: string!
  • Company: string!
  • Notes: string!
  • Comments: string!
  • Trademarks:  string!

If no Icon option is specified, a default Red icon will be provided.

o index? action is now allowed on words. It will return the word's index inside a context or none if the word is unbound. This is a shortcut for the following idiom:
    index? find words-of <object> <word>
 
o Remaining list of changes:

  • Implemented type-checking for infix operators in the interpreter.
  • Implemented native! functions type-checking support when called by compiled code.
  • Added system/state/trace? for enabling/disabling call stack traces on errors.
  • system/options/args gets the command-line string.
  • Added DO/ARGS support.
  • Error report for catchable infinite block rules recursions in Parse.
  • Added limits to Parse stack to avoid eating up all the memory.
  • Auto-conversion of float values in routines.
  • Big series (> 2MB) support enabled.
  • Lexer support for base2 and base64 encoding.
  • DO and LOAD work on file! and url! values now.
  • Added support for cycles detection for MOLD/FORM and comparisons.
  • Support for set operations on hash!.
  • SORT works on paren! now.
  • string! to issue! conversion support.
  • file! to string! conversion support.
  • Allowed float! values as arguments to AS-PAIR and MAKE pair!.
  • Added percent! support in vector! series.
  • Added matching typesets support to Parse.
  • Added PUT support to object! and any-series!.
  • Added support for make bitset! <binary>
  • Setting a tuple component to none now eliminates the component.
  • Support for HOME and END key in console.
  • Multiline editing support for paren! and map! in console.
  • Added proper error handling for malformed paths evaluation attemps.
  • Scripts using routines will now output a proper error when run from interpreter.
  • Better error handling when decoding UTF-8 string.
  • Allow PROBE to have an unset! value as argument.
  • Support X in addition to x for pair! literal syntax.
  • Prevent empty conditions in conditional iterators from entering an infinite loop.
  • Improved formatting of error messages arguments.
  • Several output improvements to HELP.
  • Allow DIR? to take an url!.
  • Allow system/console/prompt to be an active value (e.g.: a function).

Ticket processing

We have closed 260+ tickets since last release (0.5.4), among which 54 concern issues in previous releases. We have currently ~92.5% closed tickets overall, which is a bit lower than the usual 95%+, mostly due to the huge amount of new code and feature in this release. So, we will aim at getting back to a lower number of opened tickets for the next release.

I would like to make a big thank to all the contributors who reported issues, tested fixes and sent pull requests. It has been, more than ever given the number of newly implemented features, a huge help in making Red better. I would like to especially thank namely a few people for their outstanding contributions:

  • WiseGenius: for helping us solve the epic crush library generation bug, improvement suggestions and huge work on testing/reporting GUI issues! 
  • nc-x: for help in testing the GUI, making many useful issue reports and improvement suggestions.
  • The "Czech group" (Pekr, Oldes, Rebolek): for their constant support and for taking care of the Red community when I'm not available. ;-)
  • PeterWAWood: for bringing us the ~30'000 unit tests, testing framework and constant help and support, since day one!
  • Micha: for issues reporting and kindly providing us an online Mac OSX server for our build farm.

What's next?

Our focus for next releases (0.6.x) will be:
  • Drastically speed up compilation time by pre-compiling the runtime library.
  • Simple garbage collector integration.
  • Improvement of our Windows GUI backend.
  • First usable versions of MacOSX and Android GUI backends.
  • Integration of our Android APK building toolchain in master branch.
  • Improvements for reactive GUI programming support.
  • Custom widgets creation framework.
  • Animation and timers support.
  • More documentations and tutorials for beginners.
  • More code demos.

See the detail for next releases on our public Trello board and come to our chat room to ask any question.

In the meantime, enjoy the new Red, I hope to see many impressive GUI demos and apps in the next weeks. ;-)

Fork me on GitHub