RubberViewsWE
with
Auto Layout

Fit all browser and device sizes automatically

________________


RubberViewsWE is a single class for Xojo Web Edition that takes care of resizing all controls on a WebPage, a WebDialog or on a WebContainer, including font size, and image sizes for ImageWell.

 

RubberViewsWE is extremely convenient when client browser size varies considerably, between desktop computer and iPhone usually at 1920x1080, laptops often used at 1280x1080, Windows tablets or affordable smart phones at 1280x800 or even 1024x765, and on the other size of the spectrum high dpi screens at 2550x1600 or more. And those are standard resolutions. Any resizable window can adopt any size in between, as well as any aspect ratio. Moreover, portable devices such as phones and tablets rotate, and get from Portrait (vertical) to Landscape (horizontal) in seconds.

 

It is impossible to do it all with fixed size WebPages. RubberViewsWElets you design one WebPage, and have it displayed in the best of conditions for all these cases.

 

If you already know RubberViews on desktop, the Web Edition will feel very familiar. It can be used just the same way, so you can reuse a large amount of your code.

 

Best of all, RubberViewsWE is very simple to use, so you can add it to your project in minutes, but it is not limited to a single autogrow and autoposition feature.

 

RubberViewsWE offers a very powerful Auto Layout set of constraints that lets you set elaborate relationship between controls. You now can have controls resize relative to other controls, have them move together at a distance, or attach to each other in sophisticated ways. Or execute a new set of constraints based on reaching a maximum or minimum size. It is very similar to iOS Auto Layout, so anybody familiar with it will be right at home. See the special chapter about this exclusive feature below.

 

RubberViewsWE is very simple to use. 3 minutes Start :

 

- Drag the RubberViewsWE folder into your project.

- Drag an instance of RubberViewsWE over the WebPage or WebContainer

- In the WebPage or WebContainer Open event, call the Init method :

 

RubberViewsWE1.Init(Self, 800, 600)

 

800 is the width of the webpage at design time, and 600 its height.

 

Then to have the controls resized in the Resized event*

 

RubberViewsWE1.SizAll(Self)

 

*WebContainers Resized events do not fire. To get a resized event inside a WebContainer, place a WebCanvas in there, lock all its sides, and use the Resized event of the Canvas.

 

There are options available for that method. The complete parameters are :

 

SizAll(WPage as WebView, optional noContentResize as Boolean, optional KeepRatio as Boolean)

 

noContentResize as its name indicates, makes RubberViewsWEresize controls but not font sizes or pictures.

 

RubberViewsWE1.SizAll(Self, True)

 

KeepRatio will insure that no matter the shape of the resized window, controls will keep their original aspect ratio. This is important for circles and squares, for instance.

 

RubberViewsWE1.SizAll(Self, False, True)

 

Note that these options apply to all controls on the page. See next paragraph to select controls.

 

RubberViewsWE Properties

 

A set of properties allows you to customize the way RubberViewsWE works. Through these properties, you will be able to limit what RubberViewsWE does, for instance if images should be resized, or font size be modified, or through the AutoLayout property, set the relationship between controls. See next chapter about the Auto Layout feature, an exclusive and very powerful part of RubberViewsWE.

 

Ignore

You also may want RubberViews not to resize and move some controls. This is achieved with the Ignore property.

 

RubberViews1.Ignore = RubberViews1.Ignore + "CheckBox1"

 

Important : If you indicate only part of the control name that is common to several, for instance "Oval", all controls that have "Oval" in their name will be concerned. Make sure to separate that partial name from the others with a Return in the Inspector, or in code, as follows :

RubberViews1.Ignore = RubberViews1.Ignore + EndofLine +_  "CheckBox" + EndOfLine

If you enter only one item in the Inspector, make sure to click on the pencil right to the field and press Enter at the end of the item to have an EndOfLine in the field.

 

KeepRatios

It is possible to apply KeepRatio only to selected controls. For instance, in the demo project, all controls resize freely, but the oval* remains circular.To obtain that, add the name of the control to the RubberViewsWE KeepRatios property. Please note that it is plural, as opposed to the SizAll keepRatio property which is singular.

 

RubberViewsWE1.KeepRatios = RubberViewsWE1.KeepRatios + "Rectangle2"

 

This property is available in the IDE, so you can add all controls you want there as well.

 

Important : If you indicate only part of the control name that is common to several, for instance "Oval", all controls that have "Oval" in their name will be concerned. Make sure to separate that partial name from the others with a Return in the Inspector, or in code, as follows :

RubberViews1.KeepRatios = RubberViews1.KeepRatios + EndofLine +_  "Oval" + EndOfLine

If you enter only one item in the Inspector, make sure to click on the pencil right to the field and press Enter at the end of the item to have an EndOfLine in the field.

 

* In Web Edition, there is no oval in the library. You create one by applying the Ovalized WebStyle that comes with RubberViewsWE to a rectangle. Please note that unless Width = Height it will be egg shaped.

 

LiveResize

When true, if the browser window is resized, controls will be resized in real time, before the RubberViews engine polishes up, with content resize, eventual corrections, and Auto Layout. Accessible in the Inspector as a switch, it can also be set by code :

 

RubberViews1.LiveResizeOn = True

 

Live Resize uses client side JavaScript to provide smooth resize on the browser. For that reason, the content is not resized, and special settings such as keepRatio or Ignore do not happen during Live Resize. But as soon as the size of the window settles, the standard RubberViews engine takes over with all custom settings enforced.



Note that LiveResize cannot be used on WebDialogs.

 

VERY IMPORTANT : Live Resize is based on the same information as Init. Which means it retains the layout of the page as it is when Init is fired. If you change the layout of the page with Auto Layout, as in the Buddha page, Live Resize will keep the layout of the horizontal page, even if you switched to Portrait. When you change layout that way, it is recommended not to use live resize.

 

MoveOnly

That feature is very close to what some HTML pages do : move controls so they spread evenly on the page, but their size does not change. This is a boolean property you can set in the Inspector, or in code.

 

NoContentResizes

You may want to prevent the resize of the content for a particular control. For instance, in the demo, the RubberViews version indicated in the lower right corner. Simply add the name of the control to the NoContentResizes property :

 

RubberViews1.NoContentResizes = RubberViews1.NoContentResizes +_ "Label5"

 

Important : If you indicate only part of the control name that is common to several, for instance "Oval", all controls that have "Oval" in their name will be concerned. Make sure to separate that partial name from the others with a Return in the Inspector, or in code, as follows :

RubberViews1.NoContentResizes = NoContentResizes.KeepRatios +_ EndofLine + "Oval" + EndOfLine

If you enter only one item in the Inspector, make sure to click on the pencil right to the field and press Enter at the end of the item to have an EndOfLine in the field.

 

NoAutoLayout

Please check the special chapter about Auto Layout. This boolean property simply prevents it from happening. It can be useful to trigger Auto Layout manually, with the AutoLayoutDo() method.

 

SizeFonts

On the web, users do not expect the font size to change when they expand their browser size. So resizing font size within controls has been made optional. Set SizeFonts to True, in the Inspector or in code, to have text autoresize in controls that do not have a WebStyle set.

 

UseJustAutoLayout

This set to true prevents the standard RubberViews engine to do any resizing or moving of controls. Then you have to manage everything with AutoLayout. This mode can be switched on and off at any time by changing the property.

Methods

 

Because users can change the fonts and font size in their browser, and because rarely fonts are installed on web hosts, techniques such as Graphics.StringHeight from Desktop simply won't do unless you are using your own desktop box as server. So two new method have been added to RubberViewsWE :

getTextHeight(Label as WebLabel)
Now, a bit of explanation is in order. That method is asynchronous. In other words, it does not return immediately a value. The value will be available in an event later in the program, when the browser returns it.
The event ExecuteEvent with the same syntax as describe in extras/Websdk.pdf next to your Xojo executable has been added to RubberViews.
Check Parameters(0) for "textHeight", and the value will be in string form in Parameters(1)

Alternatively, you can use Rubbermodule.textHeight which is set automatically by RubberViewsWE.

An example is used in the demo project in the Shown event of Label1.

getTextWidth(Label as WebLabel)
Now, a bit of explanation is in order. That method is asynchronous. In other words, it does not return immediately a value. The value will be available in an event later in the program, when the browser returns it.
The event ExecuteEvent with the same syntax as describe in extras/Websdk.pdf next to your Xojo executable has been added to RubberViews.
Check Name or Parameters(0) for "textWidth", and the value will be in string form in Parameters(1)

Alternatively, you can use Rubbermodule.textWidth which is set automatically by RubberViewsWE.

An example is placed in the demo project in the Shown event of Label1 and in RubberViewsWE ExecuteEvent.

Why is that only available in WebLabels ? Because other controls such as TextField and TextArea make it very difficult. The workaround is to place a multiline label off WebPage (drag it above the webPage area) and use it for measurement purposes, by copying the Text property into it before using getWidth or getHeight. Using this technique, you can create autogrow (autosize in VB) controls which size depends on the content.


 

Extra classes

RubberWebCanvas

Resizing the regular WebCanvas revealed a random Xojo bug. Sometimes, after resizing WebCanvas, all painting simply disappears, effectively rendering the control invisible if it has no background color. That is the reason why RubberViewsWE just moves WebCanvas, but it cannot resize it, until the Xojo bug is fixed. If you need an equivalent, look at RubberWebCanvas, in the Classes and Modules folder within the RubberViewsWE folder. It is based on the HTML Img tag, so it does not suffer from the disappearing syndrome. Its Paint event works just the same.

 

WebColorProgressBar

WebProgressBar does not always display correctly, especially under low bandwidth conditions. WebColorProgressBar is in in the Classes and Modules folder within the RubberViewsWE folder. Based on RubberWebCanvas, it is more stable than the original control, plus it brings color.

Auto Layout


It is important to understand that RubberViews already provides a kind of Auto Layout, which can be just fine for a lot of programs. But the true Auto Layout is not simply based on proportional placement and sizing of controls based on the browser window size. A true Auto Layout sets the relationship between controls, as well as their minimum size and maximum size.

 

The simplest way to use Auto Layout is to let RubberViews do its job of placing and sizing controls, then introduce a few touches for a true tailor-made layout. A perfect example if on the main demo page, where the toolbar should not get less than 57 in height, or it starts eating up the buttons. Here is what is in the AutoLayout property :

 

ExampleToolBar.MinHeight = 57

ProgressWheel1.HorizontalCenter = Rectangle1.HorizontalCenter

ProgressWheel1.VerticalCenter = Rectangle1.VerticalCenter

 

This simply sets a minimum height the toolbar must not go under. It also keeps the ProgressWheel in the center of Rectangle1.

 

Auto Layout is much more powerful than one tweak here and there. In fact, it can manage an entire page layout. Since this will require setting constraints for every control, you will need to learn a bit. As developers familiar to iOS know, it does require learning. But it allows things that the basic autosize and autoposition features of RubberViewsWE do not offer. In general, you may want to start by using AutoLayout to tweak things a bit, while letting the standard autosize take place. Then, as you get more familiar with the fantastic possibilities and flexibility of Auto Layout, you can have it manage entirely the layout, by setting UseJustAutoLayout as True in the Inspector, or by code.

 

Pure Auto Layout. 5 minutes Start :

 

Just like Xojo iOS prepares most constraints for you, RubberViews Auto Layout can be largely automated, so you do not need to learn this whole chapter before starting. Here is what you do if you want to manage a window with only Auto Layout, in 5 minutes :

-       Copy an instance of RubberViews onto the window

-       In the Open event, enter :

RubberViews1.InitAutoLayout(self,1000,700)

 

As you see, the syntax is almost the same as RubberViews Desktop with the classic AutoSize feature.

Then, in the Resizing or/and Resized event, enter :

RubberViews1. AutoLayoutDo(self)

 

Now every control on the window will be automatically placed and resized, just like the standard RubberViews autosize.

 

But the inner working is quite different. Instead of being a largely unmodifiable black box, Auto Layout is a set of constraints you can modify at will to create conditional layout and things that autosize could not provide.

 

Just as an example, add a Rectangle1 to your window, then open the AutoLayout string property in RubberViews1 by clicking the pencil on its right, and type :

 

Portrait domagic

 

Domagic

Rectangle1.HorizontalCenter = Parent.HorizontalCenter

Rectangle1.VerticalCenter = Parent.VerticalCenter

 

Run the program. Everything seems as usual. Now resize the window so width gets less than height. The rectangle gets smack in the center of the window. Stretch the window again to Landscape, the Rectangle goes back to its design place.

 

That concludes the 5 minutes start. In that short moment, you have discovered the major feature of RubberViews Auto Layout : conditional layout. Instead of simply insuring that controls stay at their place, you can have them move around according to conditions like the minimum or maximum size, or like here, if the window is horizontal or vertical. A better example of how to use that feature is in the "Try Auto Layout" window of the demo, where buttons and label are placed differently in landscape or portrait.

 

For those accustomed to iOS, this will feel very familiar. In many ways, the web and iOS are similar. First, more than 50% of the web browsing today is conducted through portable devices, which have the very same requirements as iOS native applications. Second, although the RubberViews engine global reshaping and reposition is a very convenient way of dealing with changing browser window size and shape, it can show limits when a control becomes too small, too narrow or too wide, for instance, or when it is better to move it elsewhere upon resize, to take an example.

 

Xojo has said when iOS became available that Auto Layout would come to other platforms than iOS, but at the time this text is written, no date has been touched upon, and it seems it may be a while before it arrives. RubberViewsWE makes it happen today, and since it has been largely inspired by the way constraints work in Xojo iOS, it may not be too far from what may arrive natively one day. In the meantime, this brings Auto Layout to all versions of Xojo, since 2013R1, when nobody even talked about it !

 

Using RubberViewsWE with the three minutes start is extremely simple, and requires very little settings to get you going. Auto Layout, as users of Xojo iOS  know, is a bit more involved. So instead of throwing you right away into it, RubberViewsWE  first places all controls and resizes them, before executing. That prevents odd control placement and goofy layouts. A bit like training wheels on a bike. But when you master RubberViewsWE Auto Layout, it can become a very potent tool.

 

In iOS, the regular Left, Top, Width and Height properties are replaced in the Inspector by constraints, which are in fact formulas that describe the relationship of the control not only with the left side or the top of the view (WebPage, WebContainer), but also with other controls, and mathematical operations regarding that value : plus, minus, multiply, divide, and percentage. Since we are dealing here with the regular controls you have been using all along, RubberViewsWE constraints are all placed in a string property called AutoLayout, which contains exactly the same as the iOS Constraint Editor shows :

 

Here is what you will see on iOS, left, and RubberViews Web Edition, right :





















The content of the AutoLayout property is accessed by clicking the pencil on the right of it in the Inspector.

 

Notice the basic notation is similar enough so what you may already know in iOS can be readily applied in RubberViews.

 




The syntax of a constraint is very close to what you would do in Xojo code :

Control.Property = number or other control property <operator> other number or control property <extra addition or subtraction> number or other control property.

 

Rectangle2.Left = Rectangle3.Left*2+Rectangle2.Width-15

 

In total, you can set each property with up to three different terms ; you can add or subtract the second, multiply or divide by it. Then you can add or subtract another one.

 

Let us take an example of where Auto Layout may be very convenient. In the demo, the ProgressWheel is at the center of a rectangle. In code, you could do this in the Resized Event :

 

ProgressWheel1.HorizontalCenter = Rectangle1.HorizontalCenter

ProgressWheel1.VerticalCenter = Rectangle1.VerticalCenter

 

If you wanted the two to stay centered, you would have to make sure they remain that way, and execute this code as often as needed to keep them in line.

 

RubberViewsWE has a special string variable appropriately called AutoLayout , which contains that code, as constraints. Regular code executes only once. In a way, it is like a to do list. "Get a bottle of milk at the market". But what if instead you could say "Make sure there is always a bottle of milk in the fridge" ? Constraints are properties Auto Layout will maintain as relationship between controls. Let us imagine for instance Rectangle 1 is moved. ProgressWheel 1 will follow along.

 

But simply positioning two controls smack at the center of each other is very simple, and would not quite justify a special mechanism. Now, there are other constraints a bit less evident.

 

Say you got two controls you want to be spaced exactly at 20 points no matter the size of the window. The RubberViews engine will take the design value of 20 points, and make it bigger when the window grows, or smaller when it shrinks. With Auto Layout, you can make sure both controls will stay together at exactly 20 points distance :

 

ListBox2.Left = ListBox1.Right+20

 

Let us take another case where the automated size feature does not suffice : when a window shrinks, you may not want certain controls to become too small. Then you can fix boundaries within which the control can grow and shrink. For instance :

 

ListBox1.MinWidth = 100

 

So even if the window gets real small, ListBoxA will never get narrower than 100 points. Now, the problem is other controls will bump into it. So you will be able to set the distance at which they can be of your listbox. Since the window can be any size, a fixed width may not be the best way to go. So you can use a percentage :

 

TextField1.Left = ListBox1.Right+4%

 

This sets a relationship between the two controls. You can do the same for all current properties, and as you saw, a couple more : Right and Bottom. They are convenient to set the left of a control relative to the right of another, or the Top of one relative to the Bottom of another. They can also be set, for instance as in

 

Rectangle1.Bottom = Button1.Top-5%

 

Note that since points grow from top to bottom, setting a control above another requires a negative value.

 

Since Auto Layout can manage all controls in relation to each other, at least one must be set in relation to the border of the view, in this instance the browser window or the device screen. So other controls will form a grape with it.

 

You set that keystone control just like you would in the IDE

 

Rectangle1.Left = 10

Rectangle1.Top = 10

 

Now let us imagine you want a control to get taller as one grows wider. You can simply do :

 

Rectangle1.Width = TextField1.Width

 

You can also set that size as a fraction of the other.

 

Rectangle1.Width = TextField.Width(50%)

 

You can also set that size as a multiple of the other. In this case it just does the same as 50% :

 

Rectangle1.Width = TextField.Width*0.5

 

These are just quick examples of what you can start with, before applying the full strength of Auto Layout.

 

Here come a description of every constraint, and how to use it.

 

You may think of constraints as properties, or as boundaries, absolute (ex. 50) or relative (TextField1.Right)

 

They can be entered with the dot notation as in the IDE, or simply separated by a space, for instance :

 

TextField1 Right TextField7 left

 

Although absolutely not necessary, if you enter dot and the equal sign, there will be no error. It maybe more convenient for users accustomed to Xojo syntax.

 

TextField1.Right = TextField7.left

 

Please note that in no way RubberViews is trying to emulate or compete with the Xojo language in any sort of way, beyond making sure users employing Xojo syntax will not get errors. Actually, Auto Layout constraints are not an executable language, but simply indicate controls placement and dimensions. As a matter of fact, the quasi totality of these notations could very well be Visual Basic properties setting.

 

The goal of RubberViews Auto Layout is to provide users with an intelligent way of managing control placement and size in Web apps, especially for users of the iOS version of Xojo, with enough similarities to maintain an enjoyable experience. After all, what marks the Xojo Ecosystem is both power, and genuine concern for customer comfort.

Methods

 

AutoLayoutDo(Window, optional Constraints string,optional label)

This method applies the constraints in AutoLayout. That is the practical equivalent of SizAll.

It can be used at any time to apply new constraints by passing the Constraints parameter :

 

AutoLayoutDo(self, "Rectangle1.Left=0")

 

InitAutoLayout(Window, designWindowWidth,designWindowHeight)

Works just like the regular Init, except width and height are mandatory. This will set the AutoLayout property for the session, making sure all controls stay in place, like it would have been the case for the regular RubberViews engine. Then the constraints you have enteredin the AutoLayout property will be applied.

 

Constraints properties

 

Bottom

Pretty self-explanatory. Get or set the bottom of the control. It is important to note that contrary to Top, setting Bottom will not move the control. It will stretch of shrink vertically the control. This is a way to autosize controls via Auto Layout in a different way than the RubberViews engine.

 

Property available in Auto Layout only.

 

Height

Works just the same as the usual control property. Note that when it is used to set a WebImageView (Image Well) size, the picture it contains will be proportionally resized automatically. Attention : Content resize takes place only for the Picture property, not when URL is used.

 

HorizontalCenter

Get or set the center of the control, horizontally.

 

Init

This is a command. When Auto Layout encounters that, it performs InitAutoLayout(self, self.Width, self.Height) so subsequent resizes will take the new controls position into account. Init should be the last item in the list of constraints.

 

Landscape

This is not exactly a property or a variable, but it is a condition that happens when the device has been rotated to an horizontal position, or when the browser window has acquired an horizontal shape.

 

It lets you enter particular constraints to apply when this condition happens. Take for instance a device that has been rotated and becomes horizontal. So you created a constraints subset (see below) that will be applied when Landscape is used.

 

Landscape mySubset

 

mySubset is the label under which are listed the new constraints to apply.

 

An example of what can be done is on the merdeTry Auto Layout" page of the demo. When the browser window shape is vertical, or the device in Portrait mode, three buttons are laid out along the top of the view, with a label underneath. When the device is rotated to landscape, or the browser window shape horizontal, the buttons appear alongside the left edge of the view, with the label on their right. Now with RubberViewsWE, you have two ways to address Rotate : through the Session OrientationChanged event, or through this unique feature.

 

VERY IMPORTANT : Live Resize is based on the same information as Init. Which means it retains the layout of the page as it is when Init is fired. If you change the layout of the page with Auto Layout, as in the Buddha page, Live Resize will keep the layout of the horizontal page, event if you switched to Portrait. When you change layout that way, it is recommended not to use live resize.

 

Property available in Auto Layout only.

 

MaxHeight

This one is more interesting. It is the maximum height a control can have. So if you let the RubberViews engine manage controls, but wish one to stop growing after a point, just set it.

 

This is not only a boundary. It also lets you enter particular constraints to apply when this condition happens. Take for instance a device that has been rotated and becomes horizontal. You may want to limit the height of a TextField, but also make it wider. Which simple autosize won't do. So you created a constraints subset (see below) that will be applied when the MaxSize is reached.

 

TextArea1.MaxHeight 100 mySubset

 

mySubset is the label under which are listed the new constraints to apply.

 

Property available in Auto Layout only.

 

MaxLeft

This is not only a boundary. It also lets you enter particular constraints to apply when this condition happens. Take for instance a device that has been rotated and becomes horizontal. You may want to limit the left space before a TextField, but also make it wider. Which simple autosize won't do. So you created a constraints subset (see below) that will be applied when the MaxSize is reached.

 

TextArea1.MaxLeft 10 zozo

 

zozo is the label under which are listed the new constraints to apply.

 

Property available in Auto Layout only.

 

MaxTop

This is not only a boundary. It also lets you enter particular constraints to apply when this condition happens. Take for instance a device that has been rotated and becomes horizontal. You may want to limit the top space above a TextField. Which simple autosize won't do. So you created a constraints subset (see below) that will be applied when the MaxSize is reached.

 

TextArea1.MaxTop 10 maxthemenace

 

Property available in Auto Layout only.

 

maxthemenace is the label under which are listed the new constraints to apply.

 

MaxWidth

When the window gets larger, or the device is rotated, you can limit the width or the control. When this condition occurs, you can set a subset that will be applied.

 

Rectangle1.MaxWidth 200 bunnyrabbit

 

Property available in Auto Layout only.

 

MinHeight

When the window is shrinked, or the device is rotated, you can insure a minimum width or the control. When this condition occurs, you can set a subset that will be applied.

 

Rectangle1.MaxHeight 100 theturtle

 

When set for a parent WebPage, it is identical to the minHeight property in the inspector, used to enable scroll.

 

MinLeft

If you want the left side never to be under a certain value, that is what you use. As all Max and Min values, you can assign it a subset of constraints

 

TextArea1.MinLeft 10 myleftspace

 

Property available in Auto Layout only.

 

MinTop

If you want the top side never to be under a certain value, that is what you use. As all Max and Min values, you can assign it a subset of constraints

 

TextArea1.MinLeft 10 butterfly

 

Property available in Auto Layout only.

 

MinWidth

Useful when rotating to portrait, or shrinking a window, if you want width never to be under a certain value, that is what you use. As all Max and Min values, you can assign it a subset of constraints

 

TextArea1.MinLeft 10 thomas

 

When set for a parent WebPage, it is identical to the minWidth property in the inspector, used to enable scroll.

 

MoveOnlyList

HTML works a bit differently than desktop Rubberviews. Controls may spread out when the browser window is resized, but controls size and shape does not change. You can obtain the same behavior by adding the name of controls, or portion of their name so all Rectangle* will be affected, separated by Return (EndOfLine) in that string property, in the Inspector, or in code. This does the same as the global switch MoveOnly, but for individual, or group, of controls.

 

MoveOnly = MoveOnly + "Rectangle" // All rectangles move only

 

Parent.Width, Parent.Height, Parent Left, Parent.Right, Parent.Top, Parent.Bottom

Parent is somewhat equivalent to Self on a WebPage, but also to what would be Screen(0) on a device. That terminology is coming right from Xojo iOS Auto Layout constraints. Regular control location properties Left and Top are simply absolute relative to Parent.Left and Parent.Top.

 

Property available in Auto Layout only.

 

Portrait

This is not exactly a property or a variable, but it is a condition that happens when the device has been rotated to an vertical position, or when the browser window has acquired a vertical shape.

 

It lets you enter particular constraints to apply when this condition happens. Take for instance a device that has been rotated and becomes horizontal. So you create a constraints subset (see below) that will be applied when Landscape is used.

 

Portrait mySubset

 

mySubset is the label under which are listed the new constraints to apply.

 

An example of what can be done is on the "Try Auto Layout" page of the demo. When the browser window shape is vertical, or the device in Portrait mode, three buttons are laid out along the top of the view, with a label underneath. When the device is rotated to landscape, or the browser window shape horizontal, the buttons appear alongside the left edge of the view, with the label on their right. Now with RubberViewsWE, you have two ways to address Rotate : through the Session OrientationChanged event, or through this unique feature.

 

VERY IMPORTANT : Live Resize is based on the same information as Init. Which means it retains the layout of the page as it is when Init is fired. If you change the layout of the page with Auto Layout, as in the Buddha page, Live Resize will keep the layout of the horizontal page, event if you switched to Portrait. When you change layout that way, it is recommended not to use live resize.

 

Property available in Auto Layout only.

 

ProportionalScale(Pic as Picture, Width as integer, Height as Integer)

This is the method RubberViews uses to keep pictures in tune with the browser window size. You can use that method at any time to enlarge or shrink a picture before displaying it.

 

Right

Pretty self-explanatory. Get or set the right of the control. It is important to note that contrary to Left, setting Right will not move the control. It will stretch of shrink horizontally the control. This is a way to autosize controls via Auto Layout in a different way than the RubberViews engine.

 

Property available in Auto Layout only.

 

TopLayoutGuide

As default, the RubberViews engine assumes controls are relative to the view left 0, and Top, position zero.

 

But you may want it to start lower than that, for instance if a ToolBar is used. See the subset example below, where a TopLayoutGuide has been set lower, so controls do not bump into the toolbar when they grow. TopLayoutGuide is zero as default.

 

This constraint is directly inspired by iOS.

 

Property available in Auto Layout only.

 

VerticalCenter

Gets or sets the center of the control. Very convenient to align controls of different sizes.

 

Width

Quite the same thing as in Xojo. Note that when it is used to set a WebImageView (Image Well) size, the picture it contains will be proportionally resized automatically.

Attention : Content resize takes place only for the Picture property, not when URL is used.

 

The operators

 

These operators are used to set constraints relative to absolute values or other controls properties, making the constraints very flexible. See example of real constraints list in the subset description below.

 

Addition

Set a property with an absolute value or relative to a control, then add.

TextField1.Top = Toolbar.Bottom+20

 

Multiply

Set a property with a multiple of an absolute value or relative to a control

TextField1.Top = Toolbar.Bottom*1.2

 

Percent

Set a property and add an absolute value or relative to a control

TextField1.Top = Toolbar.Bottom+30

Can also be used to set a portion of another control property

TextField1.Top = Parent.Height(5%)

 

Subtraction

Set a property with an absolute value or relative to a control, then subtract.

TextField1.Top = Toolbar.Bottom-20

 

Labels and subsets

 

MaxWidth, MaxHeight, MinWidth, MinHeight and generally all boundaries, as well as the special condition Portrait and Landscape, let you enter as third term of a constraint a label, which will start a special set of constraints you want to apply only when this condition is reached.

 

Here is an actual AutoLayout property example :

 

ExampleToolbar MinHeight 56

ProgressWheel1.HorizontalCenter = Rectangle1.HorizontalCenter

ProgressWheel1.VerticalCenter = Rectangle1.VerticalCenter+10%

//HTMLViewer1 Height Rectangle1.Height

//HTMLViewer1 Width Rectangle1.Width*2

TopLayoutGuide 20

ExampleToolbar Top 0

Rectangle2.HorizontalCenter = ListBox1.Horizontalcenter

Rectangle2.Top = ListBox1.Bottom

Rectangle2.Right = HTMLViewer1.Left

ListBox1.MinWidth = 250

TextField1.Left = ListBox1.Right+4%

Rectangle1.Maxwidth = 110 toto

Portrait zozo

 

// This is my first label

toto

Listbox1.Width = 500

 

// This is my second label

zozo

ListBox1.Height = 800

Listbox1.Top = ExampleToolbar.bottom*1.1

 

Subsets are entered after the collection of regular constraints, starting with a word that serves RubberViews Auto Layout to find it. You can use pretty much any one word you want, except "Portrait" and "Landscape", which are reserved. Here, we got two subsets : toto and zozo.

 

Please note the comments above the labels, entered as usual with two slash bars.

 

Although RubberViewsWE will stop execution when it finds a label after the main constraints, it is much clearer to enter a space between the main constraints and the label, as above.

 

AutoLayoutDo(WPage, Constraints[,label])

 

In the IDE, you will find a string variable called AutoLayout. That is the one where you enter all the default constraints, such as the listing above shown for Subset. Simply click the pencil, and enter the data. Unfortunately, there is no autocomplete or colors in that editor, so it is recommended to prepare the work ahead of time on paper, or in a text editor.

 

At the end of SizAll(), RubberViewsWE calls that method with as Constraints AutoLayout. But you can call it yourself at any time, with other constraints properties, as long as you wish, or as short as you want. For instance

 

AutoLayoutDo(Self, "Listbox1.Width = 500")

 

Optionally, you can indicate to the method the label of a subset it should apply instead of the core constraint. In the above example, one could do

 

AutoLayoutDo(Self, "Listbox1.Width = 500")

 

and only toto would be applied.

 

UseJustAutolayout

 

The basic RubberViews engine always executes as default, kind of a safety net in case you did not manage all the controls through Auto Layout. But for elaborate constraints, you may not want to have the controls first autosize, then Auto Layout. If you just want to manage controls through AutoLayout, just set that property to True.

 

The order of constraints

 

This notion is very important. In the paragraph above, I touched upon the keystone control, the only one that must be made relative to the parent view so other controls can be made relative to it. Think of controls as christmas ornament elements. First you need the tree (the keystone control), then you add a garland, then hang glass balls, and next to them lights, and so on. You cannot add certain elements before some are already present.

 

Since the controls are set in the IDE and eventually be managed by the classic RubberViews engine, they will not go anywhere. But precisely, if you use Auto Layout, you want to make sure your assembly holds. As a general rule, you want to think of controls as elements of a patchwork. Better make sure to sew them in the right order.

 

This is one of the differences with Xojo iOS Auto Layout. In there, constraints are integrated within the control themselves, and the Auto Layout engine manages the order in which relations happen.

 

Should I really use Auto Layout, and when ?

 

At this point, you may feel a bit overwhelmed by Auto Layout. It is indeed much more complex than simply "turning on the key" with the Init() and SizAll() methods. In fact, you can perfectly well use RubberViewsWE without ever needing any Auto Layout.

 

But for all the apparent complexity of the constraints system, it is not as terrible as it looks. You do not have to write everything. RubberViewsWE will automatically create all the constraints needed to do the same job as SizAll() through the initAutoLayout() method which adds them on the fly to AutoLayout. So you dont start from scratch. Then you can tweak that set of constraints to get it to do extraordinary things. A good example is the Try Auto Layout page of the demo. When in Portrait, buttons are laid out alongside the top, with a multiline label underneath. In Landscape, buttons move alongside the left border of the view, and the label on their right.

 

In fact, Auto Layout Constraints are just a modern way of dealing with a control property. Instead of being relative only to the left and top borders of the view (or Parent, which is the terminology used in Xojo iOS for the screen), you can make a control relative to any other control on the page. That offers unprecedented possibilities. You can also fix maximum and minimum size, and optional new constraints when that condition is met.

 

Version 1

 

This is the first implementation of RubberViews Auto Layout. Already, it enables you to do amazing control shuffle around and resizing, without the need for much code but to know what goes where in relation to each other or to the parent (the browser window or device screen). I tried to put into it every useful aspect I know of what I discovered with Xojo iOS Auto Layout, plus some additional features, like subsets and the Portrait and Landscape constraints. The idea is to keep enough similarities with what some users are already familiar in iOS, while adding some features I would have liked to find there.

 

It does not mean everything is done. For instance, as of now, content (text size and images size) is not managed by Auto Layout, so you may need to do it in your code. See the ProportionalScale method for pictures. But it is a solid foundation onto which build stunning dynamic layout effects, until now possible only in Xojo iOS.

 

Future versions of RubberViews Auto Layout will probably bring more possibilities, no doubt inspired by the judicious suggestions of users.

 

 

Miscellaneous

 

Cross Platform
RubberViewsWEis cross platform and can be used on Mac, Windows and Linux projects.

Supported versions

RubberViewsWEis supported on all versions of Xojo since 2013R1. Modifying it to run on RealStudio may be possible, but quick tests with RS2012 have shown quite a bit of incompatibility. It is probably worse for older versions.

Known issues

Web Edition is far more complex than Desktop, and as such, exhibits problems of its own, related to the intricate process by which controls are created in the browser.

WebCanvas is based on HTML Canvas, a complex control that does not cope very well with being resized. Some preliminary tests have revealed a random Xojo bug where under certain circumstances, Paint simply does not do anything, so in practice, the control becomes invisible. A bug report has been filed, but pending resolution, RubberViewsWE cannot do anything but just move the control. Live Resize still works, but it will only crop the displayed image to make it fit within the layout. You may decide to resize that control in your code, but chances are you will experience the vanishing WebCanvas, so we do not recommend it.

The package contains a replacement, called RubberWebCanvas, which is based on HTML IMG Tag instead of HTML Canvas. Its paint event can be used the same way, but it will not exhibit the same disappearance.

The Xojo ProgressWheel tends to become unstable when moved. Great precautions have been taken to try and alleviate this issue, noticeably by making the control invisible during the move, but still, as it is JavaScript code continuously executing in the browser, it remains less stable than a regular control. The best solution is to simply replace it by an animated Gif, such as one available here : http://mentalized.net/activity-indicators/ You will find the picture spinner3-black.gif in the Pictures folder of the demo. See also http://www.ajaxload.info/ where you will be able to customize several different pictures with the color you like. See ProgressWheel.gif in the Pictures folder of the demo.

Such an animated gif is displayed in the demo project, left of the HTMLViewer. Please note that such a picture cannot be just dragged into the project. It has to be used as an URL, which means uploaded to a web space, and linked to in the URL property of the WebImageView. See ImageView2 in the demo project. Use your own URL if possible. We cannot guarantee the image will remain at the same place on our server forever.

The ProgressBar also exhibits some issues. Under certain circumstances, it does not display entirely, or only the border shows. Unfortunately, this is not so much a RubberViewsWE issue as what seems to be some problem with the control itself, especially when bandwidth is limited. You will find in the package a WebColorProgressBar class which contains a custom ProgressBar you can use as replacement.

There is a bug in WebPages Resized event : as you open WebPages from another, both WebPages event fire when the browser window is changed. If 4 pages are open from each other, all 4 fire if the last one is on screen. This is taken into account into RubberViewsWE methods, but you want to be careful when using that event.

For instance, in the demo project, the Resized event in WebPage1 displays WebPage1Portrait when the device is rotated, or when the window becomes taller than its width. The same Resized event is used the other way in WebPage1Portrait. Note that the code checks that RubberModule.dialogDisplayed is not true, to prevent that page switching to happen while a dialog is displayed.

Limitations

When pages are scrollable, browsers report height or width as identical to minWidth and minHeight, which makes all attempt to get the actual browser window size impossible. As a result, RubberViews keeps the design height or width, which often provides acceptable results, but when the window becomes smaller than design size, resizing becomes inadequate. Unfortunately, there is no way around that, beyond using just AutoLayout as is done in the "Auto Layout Only" page in Portrait mode.

Content resizing works pretty much the same way as in the desktop version of RubberViews for pictures. Attention : Content resize takes place only for the Picture property, not when URL is used. This is intentional. URL is the fastest way to display images in Xojo Web Edition. Resizing them would hinder performances. Besides, URL is the only way to display animated Gifs, and this would become impossible.

Some controls size cannot be changed. For instance the ProgressWheel, or ProgressBars. Actually, the latter height can be changed, but then the bar appears in a larger border frame. Looks odd. So in fact the ProgressBar sizes only horizontally. Some other controls like the WebMoviePlayer seem reluctant to change shape. I did my best to accommodate as elegantly as possible these peculiarities, but some fine tuning may be required if you use it a lot. Furthermore, since some browsers use custom controls, such as fireFox, their behavior may change.

WebCanvas has a bug which makes its content vanish at random when the size of the control is changed. Until that bug is fixed by Xojo, RubberViewsWE does not change its size. See RubberWebCanvas for a replacement, in the package. It is used in the demo project to display the Gioconda.

In some browsers, for instance Chrome and Microsoft Internet Explorer, the SearchField tends to display much wider than the width set in code. RubberViewsWE takes that into account to compensate in the browser where this problem manifest, so you will not need to worry about that. So far the browsers concerned by that effect are Chrome, Internet Explorer and Windows 10 Edge, where RubberViews compensates the excess width. The following browsers have been tested : Android browser, Chrome, Edge, FireFox, Internet Explorer, Opera, Safari. If you needed to support yet another one and saw this bug, you know where to compensate, but please report it, with if possible the User-Agent string of that particular browser, so it can be added.

Text resizing poses yet another challenge. In Web Edition, Xojo code does not have access directly to TextSize. That particular property is buried inside  WebStyle, together with other properties such as text justification, control colors, border shapes, and so on. So if a particular control has a WebStyle setting text size, but also BackColor, it should not be changed. As a consequence, there is no way to manage font size through the WebStyle system. The workaround was to use JavaScript to change text size. But what if, for instance, a web size contains exactly point 13 ? To avoid possible conflicts, RubberViewsWE resizes text size only within controls that have no WebStyle. You may want to prepare specific WebStyles with increasing text size you can set in the Resized event according to the view size. To be fair, on web pages, users do not expect font size to change when they resize the browser window. So this is optional, and happens only when SizeFonts is on.

RubberViewsWE resizes and positions all current controls based on WebControl, the base class for most controls. So custom controls are normally supported for placement and size. However, since the methods to display content vary widely, you may need to implement resizing of the content yourself if the methods are not standard.

If you need any assistance in using RubberViewsWEor about adapting the code, please contact me. I will be glad to help.

All suggestions to improve RubberViewsWE and comments are welcome. Send an email through the dedicated web site http://RubberViews.com or, if you have purchased, simply reply to our messages. Email is answered ASAP.

Michel Bujardet

Match Software
2207 Concord Pike #816
Wilmington, DE 19803


 

Properties of RubberViewsWE

 

Name

Type

Description

Ignore

String

List of the controls that must not be changed or moved by RubberViews.

KeepRatios

String

List of the controls that must keep their aspect ratio when all the controls are resized. Contrary to the SizAll Boolean parameter below, it lets you specify which controls should keep their aspect ratio.

LiveResize

 

Boolean

When true, upon resizing of the browser window, the controls will be visually resized in real time, before the RubberViews engine polishes up with content resize and Auto Layout.

MoveOnly

Boolean

When true, controls are repositioned, but their shape and size are unchanged.

NoAutoLayout

Boolean

Prevents AutoLayout from taking place, even if the Autolayout property contains constraints.

NoContentResizes

String

List of the controls that must keep their content untouched when all the controls are resized. Contrary to the NoContentResize SizAll Boolean parameter below, it lets you specify which controls should keep their content the same.

SizeFonts

Boolean

When True, text size is changed according to the size of the browser window, akin to DeskTop RubberViews. Since on the web, changing font size that way is not as frequent, this is optional.

Version

String

RubberViews current version.

ReleaseNotes

String

The history of this development


 


Methods and parameters

Name

Type

Description

AutoLayoutDo(WPage as Variant)

 

This method trigger the execution of Auto Layout separately from Sizall. It can be used for instance when noAutoLayout is true, and you want to move controls around afterward. It uses a Variant so WebPage, WebContainer and WebDialog can be passed.

Init(WPage as Variant, Optional DesignWidth as Integer, Optional DesignHeight as Integer)

 

This method must be called to initialize RubberViews so it knows all the controls sizes and positions. It uses a Variant so WebPage, WebContainer and WebDialog can be passed directly.

InitAutoLayout(WPage as Variant, Width as Integer, Height as Integer)

 

This method lets Auto Layout analyze all the controls on the page and generate constraints on the fly which will be added to the AutoLayout property for the session.It uses a Variant so WebPage, WebContainer and WebDialog can be passed directly.

WPage

WebPage or WebContainer

The WebPage or WebContainer or WebDialog onto which an instance of RubberViews has been dragged to manage controls size and position.

Width

Integer

The width of the window at design time

Height

Integer

The height of the window at design time

LiveResizeInit

 

This method must be called to initialize RubberViews LiveResize so it knows all the controls sizes and positions.

SizAll(WPage as Variant, NoContentResize as Boolean, KeepRatio as Boolean)

 

This method resizes all the contents and sizes when the browser window is resized, or the device rotated. It uses a Variant so WebPage, WebContainer and WebDialog can be passed.

WPage

WebView

The WebPage or WebContainer or WebDialog onto which an instance of RubberViewsWE has been dragged to manage controls size and position.

NoContentResize

Boolean

When True, all the content of controls, text or pictures, is not resized.

KeepRatio

Boolean

When True, all the content of controls are resized and positioned to match the window size change, but their aspect ratio remains the same.