Creating customizable application designs
You can make your own application designs customizable by understanding what actually makes a design customizable and using some design principles around this topic. Here we highlight the steps in doing so.
Creating a design plugin
A design can only be customizable when it is deployed as OpenWGA plugin. So the first step is setting up a design suitable as OpenWGA plugin in OpenWGA Developer Studio:
- Open the "New...." wizard (button to the most top-left) and choose "WGA Plugin Project" from the "OpenWGA" Category
- Choose a unique name for your plugin.
- Choose a WGA runtime project where you want to test your plugin design. The developer studio will create a link inside this runtime to your new project, so the plugin project will get connected as regular plugin in the runtime. You may as well do this later by right-clicking on some runtime, choose "OpenWGA -> Add external design" from the menu and there choose your plugin project.
- Click finish
Open the design configuration for your newly created plugin (double-click file "design.xml") then change the following
- On tab "Design Configuration" choose an anymous access level "READER". Your design must be freely accessible, at least for reading-access, in order to be used as design provjder
- Change to tab "Plugin Configuration
- Give your plugin a title
- Check the checkbox "Usage as: Design Provider"
- Normally it is also good to check "Do not execute init/connect functionalities" if your plugin will really be just a design provider
What a customizable design actually is
A customizable design is a normal design directory which:
- Has a publisher option "OverlaySupport" identifying it as a customizable design. You can set that on the "Advanced" tab of your design configuration. The contents of this option may be "optional", if your design also can be used uncustomized, or "mandatory" if your design necessarily needs to be customized to be used in any meaningful way.
- Uses a special folder named "overlay" to identify design resources which should be customizable. These design resources then need to adhere to some special rules when addressing other design resources
The by far larger of both points is point number two. Below any root folder for design resources in a design directory there may be a folder named "overlay":
OpenWGA regards the resources inside those folders as customizable resources. These are the resources that get copied to the overlay folder when using a customizable design with overlay folder. But as you know they do not get copied with their "overlay" parent directory but only the part below it. Therefor the designer who customizes your design does not know about the extra "overlay" folder. He can just use his overlay design directory like a regular design directory.
That is why addressing design resources in an overlay resource must be a bit different than normally. The contents of all "overlay" directories in your design directory actually forms a separate design directory, which just happens to be built into your design, and will always behave like that.
This will even be the case if your user chooses not to customize your customizable design. When your "OveraySupport" is "optional" and the user chooses "none" for a customization directory, then your overlay resources will just get loaded from the base design. They nevertheless will behave like they belong to an external overlay design. More on that in the next chapter.
Overlay resources and base resources
The main process in creating a customizable design is to divide up all design resources into base resources, which should not be customizable and overlay resources which should be, and then glueing both together to a working design.
You make a resource an overlay resource simply by creating an "overlay" directory at one of the places mentioned above and placing your resource in there or into a subfolder of it.
Imagine the following minimal design directory with the following WebTML modules:
The file "outer_standard.tml" is a base resource while the file "layout.tml" is an overlay resource. It may be used to define a general layout of the application which the customizing user may want to modify. When using this design with an overlay directory OpenWGA will copy the module to this location inside this overlay directory:
Now in most situations you will need to refer overlay resources from your base resources. For example "outer_standard.tml" needs to include "overlay/layout.tml". You do this straight forwardly just by specifying its "real" design name:
In the case of a customized design this will automatically fetch the resource from the overlay directory. If your design is customizable, but your user chose to not customize it (possible with OverlaySupport="optional"), then OpenWGA will directly fetch it from your base design, as usual.
Now that is one part of the trick. The real question is: How to reference other resources from your overlay resource. Remember, you are now in a module which will behave like it was in a separate design directory. There it is a module directly at root of "/tml/html".
Addressing overlay to overlay
One possible situation would be if you wanted to include another WebTML module inside the "overlay" folder from your "layout.tml". For example:
Both, "header.tml" and "layout.tml" are "root modules" from the perspective of an overlay directory. So you could just reference the header like that from "layout.tml":
You of course also could use a local reference, which actually would also work if "overlay" was a normal subdirectory:
But that would be misleading here.
This not only occurs to WebTML modules. Imagine a TMLScript module "/scripts/tmlscript/overlay/createpage.tmlscript". You could call this as action just like it was in root of your "virtual" overlay directory:
<tml:button clickaction="createpage">Create page</tml:button>
<script src="<tml:url type="js" name="homepage:js"></script>
So basically you are just leaving out the "overlay" prefix directory in any case.
A special word about WebTML labels in overlays: This works the
same as with all other resources. Using a WebTML label inside an overlay
resource will automatically use labels defined in your overlay
directory. These however then must be in file container folders "files/overlay/labels_en", "files/overlay/labels_de" and the such. You may instead want to keep your labels non-customizable in the base design. More on how to use that in the next chapter.
Addressing overlay to base
The case is a bit different if you want to include resources of your base design (outside the "overlay" folders) from an overlay resource. As overlay resources behave like they were in a separate design directory there is no straight-forward way to "go back" to the base design just by specifying a design name.
Imagine we have the following WebTML modules that form parts of the layout to be customized:
The overlay resource "layout.tml" should include these, so the user can customize their positions, but they themselves should not be customizable.
The trick to address those from the overlay is to use their normal design name but append the suffix "@base" to the design name:
And that's about all. You can use this suffix everywhere a design resource is addressed to denote, you want back into your base design.
In your included base design resource now everything works again as expected. You may as well include back into your overlay resources there using the same methodology already learned.
Again some special word about WebTML labels: If you want to reference WebTML labels from your base design in your overlay design (or in other words: Your designs should be customizable, your labels should not), then you again here must append "@base" to the design resource: The label container "labels" in that case:
<tml:label container="labels@base" key="mylabel"/>
But as it is rather uncommon to specify the label container when using labels - since "labels" is the default and something different is seldomly used - you can also use the "@base" suffix on the label key here as a special comfort function:
The effect will be the same. This also applies to all other label-fetching functionalities.