Resize-Vid

Version 1.0.0
Copyright (C) 2002-2003 Romano Paolo Tenca

Table of Contents

1. Introduction
2. Use
3. The VID dialect
      3.1. Facets
            3.1.1. RESIZE
            3.1.2. ALONE
            3.1.3. USER DEFINED GROUPS
            3.1.4. ANCHOR
            3.1.5. CODE
      3.2. Defaults
4. Resize-dump
5. How does auto-resize work?
6. Adding and removing faces
7. Hints
8. Do-resize
9. Technical Notes
10. View Dialect
      10.1. Layout-resize
11. License
12. Aknowledgements



1. Introduction

Resize-vid makes creating resizable windows easy; with automatic resizing of the faces they contain. This document will outline its use, but looking at the examples included with resize-vid will help to answer a lot of the "How do I...?" questions that always come up when you are learning to use a new tool or library.

It consists of a View dialect and VID extensions (auto-resize system).

The dialect is intended to be used by style programmers; that is, people creating new VID styles. The VID extensions are used in Layout spec blocks, used by anybody creating a GUI with VID.

The code requires Rebol View (1.2.1 or later) or Rebol Link (IOS).



2. Use

To use the auto-resize system, you must do two things:

1) DO the resize-vid.r script, or include its code directly in your script.

do %resize-vid.r
2) Call the AUTO-RESIZE function, passing the face you want it to act on. Generally, the face will be the result of a call to the standard LAYOUT function.

view/options auto-resize layout [field "try"] 'resize



3. The VID dialect

The following words can be used as word facets (like feel, edge, font-size...), when defining a face in a layout block; many of these words will be used as standard face flags. They affect the default resize behaviour.


3.1. Facets


3.1.1. RESIZE

Change the size of the face (mutually exclusive)

 resize-xy (default) resize the face in both axes
 resize-x resize only in the x axis
 resize-y resize only in the y axis
 resize-none do not resize


3.1.2. ALONE

Do not insert this face in any group (by default any face will be put in a group)

 resize-alone do not compose groups with this face


3.1.3. USER DEFINED GROUPS

Force a group of faces to be resized like a group (mutually exclusive)

 resize-next force a group with the following face (can be concatenated)
 resize-of 'name insert this face in the group called 'name


3.1.4. ANCHOR

Change the offset of a face. Cannot be used with resize-next and resize-of. An anchored face is like a resize-alone face.

 anchor-x target corner anchor the x offset
 anchor-y target corner anchor the y offset
 anchor-xy target corner anchor both the x and y offset

target - can be the lit-word name of a face or the keyword 'panel to refer to the containing panel

corner - must be a pair which refers to one of corners of target:

left-top        0x0     1x0     right-top
left-bottom     0x1     1x1     right-bottom
Examples:

field anchor-x 'panel 1x1
    ; x offset of field will follow
    ; the right-bottom corner of panel
field anchor-xy 'but 1x0
    ; x and y offset of field will follow
    ; the right-top corner of the 'but face


3.1.5. CODE

Execute some code after the resize operation

 resize-do execute the block

after the resize, execute this block of code as if it were called like this:

func [face delta delta-offset] <block>
delta is the change in size, delta-offset is the change of offset, pay attention can be called many times in a resize session with different args (for size, for offset...)

Examples:

text "Resize the font" resize-do [
    if delta <> 0x0 [
        face/font/size: face/size/y * 0.5
    ]
]


3.2. Defaults

resize-xy is the default for all faces.

Many styles have a custom default flag that overrides the general default.

 RESIZE FLAGSTYLES
 resize-xy (default)face image box icon area panel list text-list anim
 resize-alonebackdrop backtile sensor key
 resize-nonearrow sensor key button toggle check radio btn btn-cancel btn-help btn-enter tog led
 resize-xfield choice info text vtext txt body banner vh1 vh2 vh3 vh4 label lbl title rotary h1 h2 h3 h4 h5 tt code drop-down
 resize-ylogo-bar (Link)

Some styles have custom code to handle the resize:



4. Resize-dump

The file resize-dump.r contains a function (resize-dump) which prints on the console the resize-layout tree with all flags for debugging purposes. Example:

do %resize-vid.r
do %resize-dump.r
view resize-dump auto-resize layout [
    across
    L1: label 50 "Label 1" A1: area 50x50 "Area 1" return
    L2: label 50 "Label 2" A2: area 50x50 "Area 2"
]



5. How does auto-resize work?

The auto-resize engine tries to find groups of vertical and horizontal faces; i.e. columns and rows. When a face is in a group and it is resized, the offset of the other faces in the same group will be changed so that they are still aligned visually.

Important: vertical groups (columns) have priority over horizontal (rows).

Once a layout is created, it doesn't store the orientation facets (ACROSS and BELOW) that were used to create it, so resize-vid has to figure things out for itself, with help from you. Here's an example:

across
L1: label 50 "Label 1" A1: area 50x50 "Area 1" return
L2: label 50 "Label 2" A2: area 50x50 "Area 2"

What do you see? A vertical group and, inside, two horizontal groups of faces (a column with two rows)?

a)   | L1 A1 |
     | ----- |
     | L2 A2 |
Or a horizontal group and, inside, two vertical groups of faces (a row with two columns)?

b)   -------
     L1 | A1
     L2 | A2
     -------
Auto-resize sees the it the second way.

As I said, vertical groups (columns) have precedence, so b) is the option auto-resize "sees". This is obviously important because the resize behaviour depends on it. The two labels (L1 and L2) do not resize vertically, so in the b) case, the label (L2) will not be pushed down by the upper label (L1); it will be always at the same position.

Instead, the area faces (A1 A2) will extend vertically and the second one (A2) will be pushed down by the upper area (A1). The result is that the label (L2) will lose its horizontal alignment with the area (A2).

How can you tell auto-resize to give precedence to horizontal groups? You need to use the 'resize-next or the 'resize-of facets to create user defined groups of faces to tell auto-resize how to group things.

The simpler of the two is 'resize-next, which means:

"Create a group between the current face and the following one in the layout definition"

So the code:

auto-resize layout [
    across
    L1: label "Name"   resize-x RESIZE-NEXT A1: area "Area 1" resize-xy return
    L2: label "Adress" resize-x RESIZE-NEXT A2: area "Area 2" resize-xy return
]
will result in the a) case:

a)   L1 A1
     -----
     L2 A2

The area (A1) expands its y axis and BOTH (L2) and (A2) are pushed down the same amount of space, because they are in the same horizontal group (row). Thus (L2) and (b2) will still line up with each other.

The second facet you can use is 'resize-of. This is useful when the faces you want to group are not consecutive in the layout definition:

auto-resize layout [
    L1: label 100x20 "Label 1" resize-x RESIZE-OF 'G1
    L2: label 100x20 "Label 2" resize-x RESIZE-OF 'G2
    return
    A1: area 100x20 "Area 1" resize-xy RESIZE-OF 'G1
    A2: area 100x20 "Area 2" resize-xy RESIZE-OF 'G2
]
RESIZE-OF must be followed by a lit-word! atttribute that is used as the group identifier; it is used like the 'of facet for radio buttons.

In both examples only the first resize-next and the first resize-of are really useful, auto-resize can figure, by itself, that the other faces form a horizontal group.

'resize-next and 'resize-of are not limited to two faces, nor are they limited to horizontal groups. Any combination of faces which form complex nested groups can be coerced with 'resize-next or 'resize-of (this can, however, lead to effects that are hard to visualize, so it's nice that you can run things so easily to see the results :-).



6. Adding and removing faces

If you add or remove a face from a layout auto-resize is acting on, you must call auto-resize again to update the internal representation of the layout. You can call auto-resize with the window, panel, or face from which you have removed a face:

main: layout [
    f: field "try"
    button "remove" [
        remove find main f
        auto-resize main show main
    ]
]
auto-resize main
view/options main 'resize
Hint: when you recall auto-resize, all the resize layout will be rebuilt, so you must be sure that the window is in a consistent state: for example if the window is too small, some faces may have a size of 0 (or a negative value) and auto-resize will be confused by this. Select a good min-size with View/options (under new View betas and Link), and call auto-resize on the window after adding or removing faces.



7. Hints

To resize a complex layout, try auto-resize without any resize flags and see what happens. Then:

1) Add Resize-none, Resize-x, Resize-y, Resize-xy to the faces which do not suit your needs.

2) If a face overlaps other faces in the same pane, try adding Resize-alone ('backdrop 'backtile 'sensor and 'key styles have it by default)

3) If two consecutives faces must be kept together, add Resize-next to the first of the two.

4) If a face must always be at the same distance from the lower-right corner of a panel/window, add Anchor-xy 'panel 1x1 to it.

5) If a face, called for example 'but, must be always at the same distance from the lower-right corner of another face, and for some reason the auto-resize system cannot figure it out by itself, add Anchor-xy 'ar 1x1 to the 'but face:

ar: area 100x50 "Hello"
pad 50x0
but: button "OK" anchor-x 'ar 1x1
the button will then follow the lower-right corner of the area.

Hint: Anchors are useful in some cases but often a little set of Resize-next facets can do all the work. So use it only as as last resort.

6) If you want to execute some code after the resize of a face, add Resize-do. This can be useful for slider and scroller faces to sync them visually them with another face like a list:

across
lst: list 54x100 data [["1"] ["2"]][text 50x15]
sld: sld 16x100 resize-do [
    print "Time to do some calculation and then call sld/redrag"
]
Hint: Normal faces are resized in the order given by their y and x offset, so in this case, first the list and then the slider. Anchored and Resize-alone faces are resized without ANY ORDER.

7) To help see how faces are resized, set the background color of some faces to a visible color.

8) Use resize-dump to understand the layout resize tree.

9) Ask if you have problems, but with a working example :-)



8. Do-resize

Sometimes this can be useful, to activate the resize manually, for example to adapt the layout to user preferences before displaying it. This can be done calling do-resize. The template is:

USAGE:
    DO-RESIZE face size offset /nosize
DESCRIPTION:
     Execute the resize
     DO-RESIZE is a function value.
ARGUMENTS:
     face -- "Face to resize" (Type: object)
     size -- "Size to add" (Type: pair number)
     offset -- "Offset to add" (Type: pair number)
REFINEMENTS:
     /nosize -- The size of face is already set
where size and offset are the values to add to the face's size and offset.

Example:

ly: auto-resize layout [area 100x100]
do-resize ly 50x25 0
You can also change the size of the face and then call do-resize with /nosize:

ly: auto-resize layout [area 100x100]
ly/size: ly/size + 50x25
do-resize/nosize ly 0 0
Hint: If the face is a window already displayed by View/options 'resize, changing the window size forces a standard View resize event which calls the auto-resize event handler. This can lead to some side effects - like recursive resizing calls. It is safe to use do-resize on a window face that is not displayed.



9. Technical Notes

All the functions of the resize system are stored in an object called ctx-resize.

The resize system adds an event-func to the screen to handle the resize events.

Parameters used by the resize code for a single face are stored in a Rebol object (prototype: ctx-resize/resize-ob).

To get the object relative to a face, you must call ctx-resize/get-rd with the face parameter:

ly: auto-resize layout [ar: area 100x100]
probe ctx-resize/get-rd ar
This object is stored as the value of the flag word 'resize-d, to avoid adding a new field to the standard face object.

Resize-vid supports the standard facet 'resize in styles: if defined, it will be called to execute the resize operations.



10. View Dialect


10.1. Layout-resize

Undocumented.



11. License

This software is provided 'as-is', without any express or implied
warranty.  In no event will the author be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. This notice may not be removed or altered.

2. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.

3. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.



12. Aknowledgements

Thanks to Petr Krenzelok for his deep beta testing and all his support.

Thanks to Gregg Irwin for his deep revision of this doc.

I must also thank all the people on the IOS Developer server for the useful discussions in the Vid Group.

Enjoy!

Romano Paolo Tenca

Email me for bugs or requests for feature
Web site with the latest version


Copyright Romano Paolo Tenca. All Rights Reserved.
Formatted with REBOL Make-Doc 0.9.4.2 on 25-Mar-2003 at 17:56:40