Skip to main content
Version: 9.0.2

Reusable Graphical Components

Storyboard Designer allows developers to create re-usable design components that can be shared among multiple projects. Components combine model elements, such as groups and controls, together with graphical assets such as fonts and images plus interaction rules such as events and animations. The ease with which these re-usable elements can be created based on custom graphical design elements makes them significantly different than traditional widgets that offer a fixed behavior and are difficult to create.

A component is created by selecting a Storyboard Designer group or control model element in the Storyboard editor or the Application View and right clicking and selecting Create New Component. A dialog will will open with a choice for a Control Component or Legacy Control Component (deprecated). This section describes the newer Control Component option, to read more about the legacy components, see the section for Reusable Graphical Components (Legacy).

A dialog will prompt for a component name, description. Components are saved by default in the project's @ directory. Components are specialized sub-projects with their own .gde file and events/fonts/images/scripts directories.

Components are required to follow a set of guidelines in order to be discovered. A component is given a name, with no spaces or periods and the name must be shared by the following items:

  • Directory name

  • SBSpec name field.

  • GDE file name

  • Layer name

  • Control name

  • Script name (optional)

If the above criteria is met, then the root application will be able to reference the component as a dependency and the Component will be added into the Components View, availble to be dragged into the Application Model View or the GDE Model Editor to create instances of the Component.

sbspec.yaml

The main use for sbspec files is to describe the dependencies of an application.

  • name - The name of the component

  • description - A textual description of the component

  • dependencies - A list of components which this application or component depends on

    • required - Forces the dependency to propagate all the way to the root application (default is false when omitted)

Here's an example of a minimal sbspec.yaml file.

name: MinimalExample

Here's an example of an sbspec.yaml file with description, version and dependencies

name: LabelledToggleButton version: 1.0.0 description: | This an example sbpec.yaml file for a ToggleButton that is accompanied by a SimpleLabel which propagates the Theme component up to the root application. dependencies: SimpleLabel: ToggleButton: Theme: required: true

Components located in the @ directory are not automatically loaded into the Components View unless they are included in an application's dependencies. To add a dependency without manually modifying the sbspec.yaml file, we can select the Application in the Application Model View and from the Properties View, we can see the list of specified dependencies and add new dependencies.

ApplicationProperties_Dependencies.png

To use a component simply drag the component into the Storyboard Editor into a visual design context. When a component is used within an application, a link is established between the component definition and each instance where that component is used within the application. This association allows components to be changed and for those changes to be applied as updates to any existing instance of the component. Since Components may be nested within other components, the propagation can occur through several levels as necessary.

Component Instances may make local changes to the model, changes made at the instance level will take precedence and will persist throughout updates from the dependencies. It's recommended to avoid making drastic changes to the model structure of a component instance (such as adding/removing controls or render extensions) because it may affect the ability to consolidate changes between the components and the instances of the component.

Creation Guidelines and Conventions

Components provide a lot of freedom to users with regards to packaging re-usable content. However, there are some guidelines that if followed will reduce the potential for confusion when your component is applied to a number of projects.

Favor Controls over Groups Control Components must be created from Controls, not Groups.

The Component name needs to be used consistently In order for a Component to be discovered and fully usable, the following items need to be named the same as the Component.

  • Directory name

  • SBSpec name field

  • GDE file name

  • Layer name

  • Control Name

  • Script Name

Components are intended to be created in the context of one project and then shared and used in other projects. However, since a component packages all of its images, fonts, scripts and animations with it, there is always the potential for name conflicts to occur. To minimize the change of conflict it is suggested that you name all of resources with a prefix that links them to component. For example Crank provided components use following naming convention:

  • Event names should use the Component name as a namespace (e.g. PushButton.pressed

  • All animation definitions should use the Component name as a prefix with a period separator (e.g., PushButton.grow )

  • Lua scripts - A new syntax has been added to facilitate calling require on a component's scripts.

    • Calling require("@PushButton") is equivalent to calling require("@.PushButton.scripts.PushButton, which will load ./@/PushButton/scripts/PushButton.lua

    • Calling require("@PushButton.extras") is equivalent to calling require("@.PushButton.scripts.extras") which will load ./@/PushButton/scripts/extras.lua

Component Application Scripts Execution

When Component applications are simulated in Storyboard, the simulator is launched with a command line option -olua,script=@ComponentName. This means that only the primary component script (with the same name as the component) will be loaded and executed by Storyboard on initialization. The gre.SCRIPT variable is available and contains the value passed to -olua,script. It's recommended to be used to initialize the Component when launched in a standalone manner, which is useful during Component development.

An example snippet for a component named @Slider. Performing this check ensures that the initialization code only happens when the Component application is launched in standalone.

if (gre.SCRIPT == "@Slider") then
-- Launched as a standalone
gre.add_event_listener("gre.init", function()
local slider = Slider.new("Slider.Slider", 0, 0, 100, 1, function(slider)
print("Slider:", slider.value)
end)
end)
end

Editing Components and Propagating Changes

The recommended method for updating components is to open the Component's GDE and make changes in the typical fashion changes would be made for any standard application.

When opening GDE files in the editor, it may immediately show a dirty indicator. This is generally because some changes in a dependency causes the application to synchronize component instances.

Changes at the Component Instance level will take precedence over changes propagating from the Component template or one of its dependencies. This allows for a simple Object-Oriented inheritence-like behavior in the Storyboard Application Model, making it straightforward to customize any component and immediately begin using it throughout an application.

Compare Instance with Definition

By right clicking on a component in the Application Model view, you can compare the component instance with the definition by selecting ‘Components’ -> ‘Compare Component with Definition’. This will open a comparison view similar to the GDE model comparator, showing what is different between the two and allowing you to copy changes back into the instance from the definition if you like (see ‘Comparing and Merging Model Files’).

compare_instance_with_def.png