Saphirion / Development

smarter | better | faster


R3 GUI Actors

R3 GUI Actors

Author: Carl Sassenrath, Saphirion AG 

Contents

1. Concept

An actor implements a style function.

If you think of a style as an object class, its actors are like the methods, and they operate on the instance of that class, the face object. Essentially, they are functions that are reused for each instance of a style, each face.

We call them actors because they are are not true methods and are similar to the actor functions used in schemes.

This document is for advanced users who plan to implement their own styles and need to provide new functions for rendering, input, or other control. Casual GUI users do not need to know about actors.


2. Defining Actors

GUI styles define actors to provide functions that handle events, process input, modify attributes, and setup graphics rendering.

Within a style an w:actors block holds the actor definitions. The block is a collection of actor names followed by their function body blocks. No function creators or argument specifications are needed, the f:make-style function will create those.

Note that actor blocks are treated in the same way as the body block of a Funct or Closure construct so that the set-words used in the actor block define variables local to actor (initialized to none). If you need to set the value of a variable that isn't local to the actor, you can either use a set-path or f:set.

The naming convention for actors begins with w:on- followed by a verb or verb-noun that best describes the action. Examples are: w:on-draw or w:on-view. Although not strictly required, using this convention helps make GUI code more clear.

Here's an example actors block as it would look within a style definintion:

actors: [
    on-make: [
        ...
    ]
    on-update: [
        ...
    ]
    on-resize: [
        ...
    ]
    on-scroll: [
        ...
    ]
    on-over: [
        ...
    ]
]

Here is a complete style definition of w:clicker, the base-style that implements buttons.

clicker: [

    about: "Single-action button without text. Basis of other styles."

    tags: [internal]

    facets: [
        init-size: 28x28
        bg-color: 80.100.120
        border-color: 0.0.0.128

        pen-color: ; set by on-draw
        area-fill: ; set by on-draw
        material: 'chrome
        focus-color: guie/colors/focus
        draw-mode: 'normal
        materials: none
        face-width: none
    ]

    options: [
        face-width: [integer!]
        init-size: [pair!]
        bg-color: [tuple!]
    ]

    state: [
        validity: none
    ]

    draw: [ 
        normal: [
            pen pen-color
            line-width 1
            grad-pen linear 1x1 0 (viewport-box/bottom-right/y) 90 area-fill
            box 1x1 (viewport-box/bottom-right - 2) 1
        ]
        focus: [
            fill-pen focus-color
            box -1x-1 viewport-box/bottom-right 5
            pen pen-color
            line-width 1
            grad-pen linear 1x1 0 (viewport-box/bottom-right/y) 90 area-fill
            box 1x1 (viewport-box/bottom-right - 2) 1
        ]
    ]
    actors: [
        on-make: [
            if face/facets/face-width [
                face/facets/init-size/x: face/facets/min-size/x: face/facets/max-size/x: face/facets/face-width
            ]
        ]
    
        on-init: [
            set-facet face 'materials make-material face get-facet face 'material
        ]
        
        on-draw: [
            set-material face face/state/mode
            color: get-facet face 'border-color
            if face/state/mode = 'over [color: color / 2]
            face/facets/pen-color: color
            arg ; return draw block
        ]

        on-over: [ ; arg: offset or none
            face/state/mode: pick [over up] face/state/over: not not arg
            draw-face face
        ]

        on-click: [ ; arg: event
            face/state/mode: arg/type
            if 'up = face/state/mode [face/state/mode: 'over]
            draw-face face
            if arg/type = 'up [
                focus face
                do-face face
            ]
            true ;don't do unfocus
        ]
        
        on-focus: [ ; arg/1: TRUE for focus, FALSE for unfocus; arg/2 - forced re-focus flag
            set-facet face 'draw-mode either get arg/1 ['focus]['normal]
            set-facet face 'focus-color either get arg/1 [guie/colors/focus][255.255.255.255]
            draw-face face
        ]
        
        on-key: [ ; arg: event
            if arg/type = 'key [
                switch arg/key [
                    #" " [
                        do-face face
                    ]
                ]
            ]
        ]

        on-validate: [
            face/state/validity: validate-face face
        ]
    ]
]

2.1 Actor Arguments

Actor arguments are fixed and standardized. The arguments are:

face The face upon which the actor acts.
arg A single value or block of multiple values.

When an actor is called, argument values are passed to the actor body block. Local variables can be defined using set-words (same way as in FUNCT method).

2.2 Inherited Actors

When a style is derived from another style its actors are inherited.

It should be the derived actors are not bound to any particular style, but are simple functions. This allows actors to be efficiently reused in all instances of a face object.

For example, w:button uses the w:clicker actors here:

button: clicker [
    
    about: "Single action button with text."
    
    tags: [action tab]
    
    facets: [
        init-size: 130x24
        text: "Button"
        text-style: 'button
        max-size: 260x24
        min-size: 24x24
        text-size-pad: 20x0
    ]
    
    options: [
        text: [string! block!]
        bg-color: [tuple!]
        init-size: [pair!]
        face-width: [integer! issue!]
    ]
    
    actors: [
        on-make: [
            either face/facets/face-width = #auto [
                face/facets/max-size:
                face/facets/init-size: face/facets/text-size-pad + as-pair first font-text-size? face-font? face face/facets/text 24
            ][
                do-actor/style face 'on-make arg 'clicker           
            ]
        ]
        
        on-set: [
            if arg/1 = 'value [
                face/facets/text: form any [arg/2 ""]
                show-later face
            ]
        ]
        on-get: [
            if arg = 'value [
                face/facets/text
            ]
        ]
        on-draw: [
            t: get-facet face 'text
            ; limit-text-size modifies, so we need to copy
            ; size is made 20px smaller to incorporate "..." (see text-size-pad)
            l: limit-text-size copy/deep t face/gob/size - face/facets/text-size-pad face-font? face
            set-facet face 'text-body either equal? t l [t][join l "..."]
            do-actor/style face 'on-draw arg 'clicker
        ]
    ]
]

Notice, no actor definitions from w:clicker are needed to be duplicated.

2.3 Accessing Facets

For any given style a facet value may be stored in either the style object itself, or within the face instance. The location depends on whether the facet is static for all face instances, or changes for each instance.

Because you don't know and shouldn't care where it is stored, the f:get-facet function is provided to get the value and the f:set-facet function to set it.

For example, if the w:on-resize actor needs to know the size facet, it would use:

size: get-facet face 'size

If the size is found in the w:face/facets object, that will be used. Otherwise, the w:style/facets object will be used.


3. Standard Actor Names

A number of actor names are predefined for standard actions, and we recommend that you use these for their equivalent actors within your GUI styles:

Actor Description
on-make when face is first created to initialize special values
on-click when mouse button clicked on face
on-drag when dragging inside a face
on-drag-over when dragging and are over a target face
on-drop when drag has stopped or when a file is dropped
on-focus when we have been given or are losing focus
on-get to fetch state values
on-set when state values are set
on-clear when the state values are cleared
on-key when key has been pressed (for our focus)
on-move when mouse has moved
on-over when mouse passes over or away
on-reset when reset is needed
on-resize when size values have changed
on-update when face contents have changed
on-draw when system starts to draw the face (create DRAW block)
on-scroll when scrolling is needed
on-scroll-event when the mouse wheel is used
on-init when face and its parent pane are ready (including initial sizing)
on-attach when a face is attached from another face
on-attached when a face is triggered in the attach reaction chain

4. Default Actors

A small number of actors are defined by default to work for all styles. They are:

Style Description
on-resize Recompute the area-size facet.
on-get Return the face/state of a given name.
locate A special actor to map an event to an offset position.
on-attached By default sets the attached face value to the current face value.

Style definitions are allowed to override these actors with their own definition specific to their operation.


5. Calling an Actor

There will be times when one actor function will call another. This is done with the f:do-actor function. Actors are always called this way, never directly.

For example:

do-actor face 'on-click true

It should be noted that the call will be ignored if the face has no w:on-click actor.

Sometimes you can reuse actor code from another style to avoid duplicate code in multiple styles.

For example:

on-resize: [
    ;call the standard on-resize code from FACE style
    do-actor/style face 'on-resize arg 'face

    ;here follows specific on-resize code for this style
    ...
]

6. Actors for Initialization

6.1 on-make

The w:on-make actor is called when the face is created within the layout engine.

arg

none

return

none

This actor can be used to setup face facet values such as blocks of data, colors, face orientation, etc. and anything else unique to the face. If you are defining a compound style, this is a good actor to set-up any sub-faces.

It is not necessary to compute the face size within w:on-make because w:on-resize will be called later to do that.

Example that sets colors unique to the new face:

on-make: [
    face/facets/colors: copy [255.255.255 128.128.128]
]

6.2 on-init

The on-init actor is called when a new layout is created.

arg

none

return

none

When a new layout is created, the w:on-init actor will be called for each face within the layout. At this point the face objects exist and the layout has been initialized, including any special bindings.

It is also called for any trigger faces (special faces that act on w:when layout events.)

Resetting the face on initialization:

on-init: [
    do-actor face 'on-reset
]

6.3 on-attach

The w:on-attach actor is called when this face gets attached from another face.

arg

the face requesting attachment

return

none

Here is simple example hwo it works:

stylize [
    node: box [
        facets: [
            text-style: 'title
        ]
        options: [
            bg-color: [tuple!]
            text-body: [string!]
        ]
        actors: [
            on-attach: [
                print ["ON-ATTACH: Node" face/name "has been requested to attach from node" arg/name rejoin ["[" arg/name "->" face/name "]"]]
            ]
        ]
    ]
]

view [
    A: node red "Node A" attach 'B
    B: node green "Node B" attach 'A
    C: node blue "Node C" attach 'A
]

You should see following output in the console:

ON-ATTACH: Node B has been requested to attach from node A [A->B]
ON-ATTACH: Node A has been requested to attach from node B [B->A]
ON-ATTACH: Node A has been requested to attach from node C [C->A]

For easy access the face/targets field contains faces that are attached FROM the face.


7. Actors for Events

7.1 on-attached

The w:on-attached is called on every attached face. It is triggered by w:do-face function call sequence on a face that attaches to one or more face targets.

7.2 on-click

The w:on-click is called each time a mouse button press or release occurs.

arg

the event object for the mouse click.

return

on down, can be none/false(unfocus is called), true(unfocus is not called) or the drag object. On up, none.

This example prints the button event that occurred:

on-click: [
    probe arg/type
]

w:on-click is also the precursor to dragging (holding down a mouse button, while moving the mouse), so you can create a drag object in w:on-click using the f:init-drag function. If you return the drag object the w:on-drag actor will be invoked.

on-click: [
    if arg/type = 'down [
        return init-drag face arg/offset
    ]
    none ; return value
]

7.3 on-drag

The w:on-drag actor is called when the drag object is created or when the mouse is moving inside its target face.

arg

drag object (created earlier)

return

none

w:on-drag usually comes after w:on-click and ceases to be used when the drag object is destroyed, which happens right after on-drop.

Note that when a drag object exists, the w:on-move and w:on-over actors are not called.

Here is an example used by a slider that changes a value constantly during drag, updates its graphics, and calls its attached faces (if any).

on-drag: [ ; arg: drag
    do-actor face 'on-offset arg/delta + arg/base
    draw-face face
    do-face face
]

7.4 on-drag-over

The w:on-drag-over actor is called when the mouse is moving over a foreign face (not the target of the drag.)

arg

Block of values related to the drag [drag-object offset ???]

return

none

Examples

on-drag-over: [
    ; write this example
]

7.5 on-drop

The w:on-drop actor is called when the drag operation is released.

arg

the drag object created earlier.

return

none

At the end of a drag operation, when one of the mouse buttons is released, the w:on-click action is called with the event, then w:on-drop is called.

After w:on-drop, the drag object is automatically destroyed. The w:on-drop actor is caleld regardless of whether the drag operation was started over this face or a different face.

The w:on-drop actor is also called if a file is dragged and dropped from the system desktop over the face. This is a special case.

Example:

on-drop: [
    ; write an example here
]

7.6 on-focus

The w:on-focus actor is called every time the face gains focus using the f:focus or f:next-focus function or loses focus with the f:unfocus function.

arg

true for focus and none for unfocus.

return

none

Nothing is called after w:on-focus, so if the face is changing appearance, a f:show-later should be called within the actor.

This example makes the background color yello (selection variation of yellow) when the face is focused and makes it white, when the face is unfocused:

on-focus: [
    face/facets/bg-color: pick reduce [yello white] arg
    draw-face face
]

7.7 on-key

The w:on-key actor is called when a face has focus and a key is pressed.

arg

the input event

return

the same event

The w:on-key actor has a default value for all faces, to return the event argument.

Simple keyboard navigation in a street map face:

on-key: [
    if arg/type = 'key [ ;detect only "key-down" event types (use 'key-up for up events)
        dx: dy: 0
        switch arg/key [
            right [dx: 1]
            left  [dx: -1]
            up    [dy: 1]
            down  [dy: -1]
        ]
        if find arg/flags 'shift [
            dx: dx * 3
            dy: dy * 3
        ]
        move-map as-pair dx dy
    ]
    arg ; return same event
]

7.8 on-move

The w:on-move actor is called every time the mouse moves.

arg

the event value (with face-relative positions)

return

none

Important notes:

  • Not required for most styles.
  • Will be called often, so don't define it unless you need it.
  • The w:on-over actor will be called after this actor.
  • Not be called during a drag operation.

7.9 on-over

The w:on-over actor is called every time the mouse moves over or away from the face.

arg

the face relative position or none

return

none

If the face has the w:all-over value specified as true, this actor will be run continuously as long as the mouse is over the face. If w:all-over is not true, it does not report continuously, only on enter and exit.

7.10 on-resize

The w:on-resize actor is called every time the layout is resized.

arg

new size (pair! value)

return

none

Normally, you use this actor to modify the size fields of the draw block and any GOBs used within it. If your style is a compound style, the faces inside may also need to be resized.

Resizing a single face:

on-resize: [
    face/gob/size: arg
    set-facet face 'size arg
]

Resizing a compound face (of 'panel' layout type):

on-resize: [
    do-actor/style face 'on-resize arg 'hpanel
    ;style specific code follows
    ....
]

7.11 on-scroll

The w:on-scroll actor is called from one face to scroll another face.

arg

the face object of the scroller

return

true if the attach was successful

When a scroll-bar is moved it will call this function to tell its target face to scroll. This is how a scroll-bar informs the other face that it's time to update. So, this actor must be defined for styles that are scrollable.

When a face is scrolled, this actor can be called directly by the w:scroll reactor or by a prior attachment that occurs when a scrollable face is defined before a scrolling style.

Do not confuse this with w:on-scroll-event which takes an event to perform.

Scroll a text area face:

on-scroll: [ ; arg: scroller
    gob: sub-gob? face
    size: gob/size - gob/text/scroll
    tsize: size-text gob
    gob/text/scroll/y: min 0 arg/state/value * negate tsize/y - gob/size/y + 5
    show-later face
]

7.12 on-scroll-event

The w:on-scroll-event actor is called when a scroll event occurs.

arg

the event

return

the same event

Scroll events can be caused by the mouse-wheel or other such devices.

Do not confuse this actor with w:on-scroll which is used to scroll a face from another face, such as a w:scroller style.

Here's an example:

on-scroll-event: [
    dy: none
    switch arg/type [
        scroll-line [dy: arg/offset/y / -30]
        scroll-page [dy: negate arg/offset/y]
    ]
    if dy [bump-scroll face dy]
    none
]

Note that w:bump-scroll is a function specific to this style.


8. Actors for Value Control

8.1 on-get

The w:on-get actor returns values stored in the face object and is normally called by f:get-face. Normally, the default actor is all you need.

arg

the name of the variable to fetch (default is value)

return

The value fetched.

The default definition of w:on-get is:

on-get: [ ; arg: the field to get
    select face/state arg
]

8.2 on-set

The w:on-set actor is called by f:set-face for setting the state value of a face or any other value in the face.

arg

A block containing the name and its value.

return

none

The default name is w:value, which means set the primary value of the face.

Here's an example of w:on-set used by a clock style to set its time:

on-set: [
    if arg/1 = 'value [
        if date? time: arg/2 [time: time/time]
        face/state/value: time
        face/facets/clock/set-clock time
        show-later face
    ]
]

8.3 on-clear

The w:on-clear actor is called when a face needs to be cleared.

arg

none

return

none

This actor is called by the w:clear reactor. It is also called when a layout that contains input fields is cleared with the f:clear-layout function.

on-clear: [
    clear face/facets/text-edit
    show-later face
]

8.4 on-reset

The w:on-reset actor is called when the face needs to be reset to a predefined initial value.

arg

none

return

none

This actor is mainly used for the w:reset reactor.

on-reset: [
    do-actor face 'on-set 0
]

9. Other Actors

9.1 on-draw

The w:on-draw actor allows you modify a draw block immediately before it is rendered.

arg

the current draw block for the face

return

the modified draw block

This function may be called often, every time a f:draw-face is needed. You should make this actor as efficient as possible. If it is possible for computations can be performed in other actors, such as w:on-click, that should be done.

Here is an example of the w:on-draw used by buttons (from the clicker style):

on-draw: [
        set-material face face/state/mode
        color: get-facet face 'border-color
        if face/state/mode = 'over [color: color / 2]
        face/facets/pen-color: color
        arg ; return draw block
]
R3 GUI Actor/Reactor design changes

R3 GUI Actor/Reactor design changes

Author: Richard Smolak
Date: 20-Jan-2013

Contents

1. Introduction

This document describes the changes related to the decision to simplify the current actor/reactor model.


2. No more Reactors

The Reactors have been completely removed from the system because we (the RMA team) agreed they make the usage of the framework confusing and not flexible enough.

After the changes made to the R3GUI the programmer will need to deal only with Actors.


3. Actor Overriding

Here is an example how to override a style (default) actor of a face:

view [
    my-field: field on-key [
        ;arg holds event object
        if arg/type = 'key [
            print ["field" face/name "key:" mold arg/key]
        ]
    ]
]

Running the above code you should see that the w:on-key actor has been overridden in the w:my-field face and the new code is executed instead.

But now the typed characters aren't shown in the field. That's because the style w:on-key actor is not called anymore.

Here is a modified code of the above example executing the style actor after the newly added code:

view [
    my-field: field on-key [
        ;arg holds event object
        if arg/type = 'key [
            print ["field" face/name "key:" mold arg/key]
        ]

        ;now call the FIELD style actor
        do-actor/style face 'on-key arg face/style
    ]
]

This techinque is flexible enough so the programmer can call the style actor at any possible place in the new code that overrides the style actor.

NOTES:

1. Should we introduce API function wrapper for calling the style actor in some easier way?

2. If yes, what syntax form and name should have such function wrapper?


4. ON-ACTION actor

Because the DO reactor doesn't exist in the system, the ON-ACTION actor has been added as 'system actor' for the default style terminal action.

The ON-ACTION actor is useful if the style needs to call some default action from multiple places (actors) in the style definition.

For example, the BUTTON style needs to call the default style action from the ON-KEY actor and also from the ON-CLICK actor, so it is better to call the ON-ACTION actor from the both code points to avoid the necessity to override multiple style actors.

The ON-ACTION actor can be overridden in the layout block without the need to call the original style actor code. Here is an example:

view [
    button on-action [print "button pressed"]
]

NOTES:

Styles should not define the ON-ACTION actor. This way the layout programmer doesn't need to deal with any interferences.

Do we need a better name for this actor?


5. Face ATTACH mechanism

The face attaching subsystem has been reworked. The ATTACH reactor doesn't exist. The ATTACH keyword has been added to the layout dialect to keep the current syntax.

Summary of main changes in the subsystem:

  • the face/targets field contains faces that are attached FROM the face
  • the face/attached field contains faces that are attached TO the face
  • the ON-ATTACH actor is called in the target face during the time the target face is being attached from any source face. The ON-ATTACH actor is optional.

for example:

view [
    t1: toggle "toggle 1" attach 't2
    t2: toggle "toggle 2"
    t3: toggle "toggle 3" attach 't1
]

In the example above:

t1/targets

contains t2

t1/attached

contains t3

t2/attached

contains t1

t3/targets

contains t1

  • the attached actions are chained by default (if the default ON-ATTACHED actor is used). So if we use the example above:
pressing t1

triggers t2 only

pressing t2

no effect

pressing t3

triggers t1 but since t1 is attached to t2, t2 is triggered as well

  • if any triggered face attaches back to the initial face in the chain, such a feedback attachment is skipped and ignored
  • the ON-ATTACHED actor is called in every face that is triggered in the attach reaction chain.

If the ON-ATTACHED actor returns TRUE the reaction is chained. Otherwise the reaction is terminated in such face.

The default ON-ATTACHED actor contains following code:

on-attached: [  ;arg: dst-face no-show-flag
    apply :set-face [arg/1 get-face face arg/2]
    true
]

Where the ARG is the source face that triggers the actual face.

NOTES:

1. Are the face/targets, face/attached and other naming good enough or are there better names?

2. Any feedback to the chaining is appreciated.

3.


6. API function changes

Following table describes all API functions that have been changed, added or removed:

Function name state Description
DO-FACE changed Function name has been reused for the changed behaviour. Now the function executes the standard action code sequence of a face.The sequence contains the code that tries to call all attached targets of the face and then the ON-ACTION terminal actor (see below)
DO-STYLE renamed to DO-ACTOR DO-ACTOR now tries to call the face (overriding) actor first. If the face actor is not defined it calls style actor. DO-ACTOR/STYLE calls only the specified style actor code. It can be used to mix different actor calls.
DO-TARGETS added This function calls DO-FACE function on all target faces (the faces that have been attached FROM the calling face). Use DO-TARGETS/CUSTOM to execute custom code instead of the DO-FACE call on every target face.
DO-ATTACHED changed This function calls DO-FACE function on all faces which are attached TO the calling face. Use DO-ATTACHED/CUSTOM to execute custom code before the DO-FACE call on every attached face.

Should be any function name changed to better one?

R3 GUI Actor overriding techniques

R3 GUI Actor overriding techniques

Author: Richard Smolak
Date: 20-Jan-2013

Contents

1. Introduction

During the R3 GUI application developement there are situations where you may look for a way how to override the default functionality of an actor in a specific style.

There are two possible techiques how to do it depending on your preferences.


2. Overriding techniques

We'll use a simple example to demonstrate both overriding techniques. Let's have the following layout:

view [
    field
    text-list [
        "Robert"
        "Bolek"
        "Richard"
        "Ladislav"
    ]
]

The code above shows a simple field and a list of names in a window. We want to use a matching filter on the names in the list every time the user types some character in the field.

2.1 Overriding actor functionality using the STYLIZE function

This techinque is useful in case you want to separate the newly added actor code from the layout dialect or if you plan to derive new styles based on the additional code.

Here is a possible solution:

stylize [
    filter-field: field [
        actors: [
            on-key: [
                ;execute the 'original' actor of FIELD style
                do-actor/style face 'on-key arg 'field

                ;apply the matching filter on my-list
                val: get-face face
                set-face/field my-list make map! either empty? val [
                    [1 [true]]
                ][
                    compose/deep [1 [find/match first value (val)]]
                ] 'filter
            ]
        ]
    ]
]

view [
    filter-field
    my-list: text-list [
        "Robert"
        "Bolek"
        "Richard"
        "Ladislav"
    ]
]

The example above works well but there is one issue. The w:my-list name is hardcoded into the definition of the new style ON-KEY actor which is not good, since it can work only in case the MY-LIST name is defined and refers to the list related to the filter field.

We should refine the example to be reusable. For that purpose we can use the w:attach dialect keyword to achieve a more general and system-friendly functionality:

stylize [
    filter-field: field [
        actors: [
            on-init: [
                ;execute the 'original' actor of FIELD style
                do-actor/style face 'on-init arg 'field
            ]
            on-key: [
                ;execute the 'original' actor of FIELD style
                do-actor/style face 'on-key arg 'field

                ;apply the matching filter on the attached target face(s)
                foreach target select face 'targets [
                    if target/style = 'text-list [
                        val: get-face face
                        set-face/field target make map! either empty? val [
                            [1 [true]]
                        ][
                            compose/deep [1 [find/match first value (val)]]
                        ] 'filter
                    ]
                ]
            ]
        ]
    ]
]

view [
    filter-field attach 'my-list
    my-list: text-list [
        "Robert"
        "Bolek"
        "Richard"
        "Ladislav"
    ]
]

The above example works with any text-list face which is attached to a filter-field. Also, the filter-field can be used as a base for new styles. Notice the code used in f:stylize is also longer and more complex, because in fact we derived a new child style from the FIELD parent style.

2.2 Inline overriding using the layout dialect

Sometimes you don't want to create a new derived style. This can be handy in the following conditions:

  • you intend to use the changed behaviour just once, and
  • don't want to use the changed actor behaviour as a base for new styles

Here is a possible solution:

match-filter: func [
    list [object!]
    value [string!]
][
    ;apply the matching filter on my-list
    set-face/field list make map! either empty? value [
        [1 [true]]
    ][
        compose/deep [1 [find/match first value (value)]]
    ] 'filter
]

view [
    field on-key [
        ;execute the 'original' actor of the field
        do-actor/style face 'on-key arg 'field
        ;call the filtering function
        match-filter my-list get-face face
    ]
    my-list: text-list [
        "Robert"
        "Bolek"
        "Richard"
        "Ladislav"
    ]
]

In the above code the ON-KEY word in the layout dialect means you want to override the on-key actor of the FIELD style, i.e., instead of the original actor, the given code will be evaluated.

You can override any other existing actor using the same approach. The actor name is then followed by a block which is used instead of the original ON-KEY actor block defined in the FIELD style.

In this case we don't mind whether the inline block contains any application specific code.

Same as with the original style actor, you are free to put any code into the inline actor block.

For example, you can call the original actor before or after your application-dependent code. Or even don't call the original style actor at all or chain multiple actor calls and so on. It all depends on your needs.