Style sheets are now supported in the Curl GUI Toolkit. (In version 6.0 they were available as an external library. This older note describes how to use styled sheets in version 6.0: Using Style Sheets - Curl 6.0 .)
You can create and use one or more style sheet files in a Curl application. You can also create your StyleSheet objects directly in the Curl code. In general, follow these basic rules:
" Each style sheet consists style rules and nested style sheets.
" A nested style sheet can be defined in a curl file and imported by giving the url for the file.
" Any nested style sheets must appear before the style rules.
" A style rule consists of a selector string followed by any number of option settings.
" If two rules specify the same option, the rule that comes later overrides the earlier rule.
" If you set an option directly on an object, it cannot be overridden by a style rule.
Style Sheet Syntax
In Curl, a
StyleSheet contains a set of rules that affect the look of the GUI objects the rules apply to. Each
StyleRule uses a pattern, or "selector", to identify the controls or GUI components that are affected by the rule.
Let's examine a example style sheet definition.
Code:
let ss:StyleSheet
{StyleSheet
{StyleRule VBox.panel-vbox
background = blue,
margin = 2px,
spacing = 4px
}
}
where:
" ss a variable that defines the StyleSheet
" VBox.panel-vbox is the selector
" VBox is the
style-element
" panel-vbox is the
style-class
This selector has two components. For the rule to apply, the first component must match the
style-element property of an object and the second component must match the
style-class property. If either component is omitted, then it doesn't apply. (So ".panel-vbox" would apply to any object with a
style-class that includes the string "panel-vbox".)
Using the Style Sheet
Once you have a
StyleSheet defined, you can use the definitions after it has been installed. For example:
Code:
{install-style-sheet ss}
In our example code, each time we call
VBox, we have the option of specifiying the
style-class of panel-vbox. For example:
Code:
{value
let my-panel:VBox =
{VBox
style-class = panel-vbox,
{Frame Top content},
{Frame Bottom content}
}
}
Using a StyleSheet in the Login Example
Let's pull together these concepts and apply them to our login example. We created a style sheet common-style-sheet that contains definitions for common properties (widths) specified in the login screen. We can use these styles by specifying the style-class.
Code:
{curl 7.0 applet}
|| Identify a StyleSheet
|| The common StyleSheet sets up some rules (primarily widths) common to the
|| different versions of the login form.
{let common-style-sheet:StyleSheet =
{StyleSheet
{StyleRule "CommandButton.ok",
width = 1.75cm
},
{StyleRule "TextField.login",
width = 2cm
},
{StyleRule "PasswordField.login",
width = 2cm
},
{StyleRule "GroupBox.dialog",
width = 4.5cm
}
}
}
|| Form creation procs
{define-proc {login-dialog
tf:TextField, pf:PasswordField, cb:CommandButton
}:Graphic
{return
{GroupBox
style-class="dialog",
label = "",
{Dialog
use-look-and-feel? = false,
{Table
{row
{cell {Label"Username:"}}
{cell {value tf}}
},
{row
{cell {Label "Password: "}}
{cell {value pf}}
},
{row
{cell
colspan = 2,
halign = "center",
{value cb}
}
}
},
{validate-with {DialogValidator}}
}
}
}
}
{value
let tf:TextField =
{TextField
style-class="login",
width = 2cm,
{validate-with ValidationPattern.email-address, required? = true}
}
let pf:PasswordField =
{PasswordField
style-class="login",
width = 2cm,
{validate-with {StringValidator}, required? = true}
}
let cb:CommandButton =
{CommandButton
style-class = "ok",
label = "Submit",
{on Action at cb:CommandButton do
{if-non-null dlg = cb.dialog then
{if {validate-dialog dlg} then
let dlg:Dialog =
{Dialog
{GroupBox
width = 4.5cm,
label = "",
{hcenter
{VBox
halign = "center",
spacing = 0.1cm,
{Label "Submitted"},
{ok-button}
}
}
}
}
{dlg.show title = "Validated"}
}
}
}
}
|| NOTE: In this case it is a composite of the styled controls StyleSheet,
|| another StyleSheet, and an additional StyleRule.
let ss:StyleSheet =
{StyleSheet
common-style-sheet,
{get-default-style-sheet}
}
|| Install the StyleSheet.
{install-style-sheet ss}
|| Create the UI.
{Frame
{login-dialog tf, pf, cb}
}
}
Creating the Style Sheet File
Defining style sheet rules directly in your source code is a good approach for testing your rules. Once you are satisfied with the
StyleRules, you can place them in one or more style sheet files. The default style sheet is a prime example of this implementation in which it has rules that implement a new look for all of the Curl GUI Toolkit controls. Let's first examine the the contents of the files that define the default style sheet. They are contained within two files: default-style.scurl and dss-defs.scurl (dss-defs.scurl is included in default-style.scurl). These files are located in the Curl install directory. For example, on Windows it is C:\Program Files\Curl Corporation\Surge\8\ide\gui\controls\styled-controls.
One thing to recognize is that a style sheet in Curl is simply a file containing Curl code. The file extension is *.scurl and the last expression in this file must return a StyleSheet object. Aside from that, the file can include any Curl code that is needed to implement the style. In particular, you may need to import packages such as CURL.GUI.STANDARD in order to implement your style.
Our style sheet file resembles the following:
Code:
|| StyleSheet
{import * from CURL.GUI.STANDARD}
{StyleSheet
{StyleRule CommandButton.ok,
width = 1.75cm
},
{StyleRule TextField.login,
width = 2cm
},
{StyleRule PasswordField.login,
width = 2cm
},
{StyleRule GroupBox.dialog,
width = 4.5cm
}
}
In our login example, reference the
StyleSheet file using the
url.
Code:
{let common-style-sheet:StyleSheet =
{url styles/my-styles/common-style-b.scurl}
}
Code:
{curl 7.0 applet}
{let common-style-sheet:StyleSheet =
{url "styles/my-styles/common-style-b.scurl"}
}
|| Form creation procs
{define-proc {login-dialog
tf:TextField, pf:PasswordField, cb:CommandButton
}:Graphic
{return
{GroupBox
style-class="dialog",
label = "",
{Dialog
use-look-and-feel? = false,
{Table
{row
{cell {Label"Username:"}}
{cell {value tf}}
},
{row
{cell {Label "Password: "}}
{cell {value pf}}
},
{row
{cell
colspan = 2,
halign = "center",
{value cb}
}
}
},
{validate-with {DialogValidator}}
}
}
}
}
{value
let tf:TextField =
{TextField
style-class="login",
width = 2cm,
{validate-with ValidationPattern.email-address, required? = true}
}
let pf:PasswordField =
{PasswordField
style-class="login",
width = 2cm,
{validate-with {StringValidator}, required? = true}
}
let cb:CommandButton =
{CommandButton
style-class = "ok",
label = "Submit",
{on Action at cb:CommandButton do
{if-non-null dlg = cb.dialog then
{if {validate-dialog dlg} then
let dlg:Dialog =
{Dialog
{GroupBox
width = 4.5cm,
label = "",
{hcenter
{VBox
halign = "center",
spacing = 0.1cm,
{Label "Submitted"},
{ok-button}
}
}
}
}
{dlg.show title = "Validated"}
}
}
}
}
|| NOTE: In this case it is a composite of the styled controls StyleSheet,
|| another StyleSheet, and an additional StyleRule.
let ss:StyleSheet =
{StyleSheet
common-style-sheet,
{get-default-style-sheet}
}
|| Install the StyleSheet.
{install-style-sheet ss}
|| Create the UI.
{Frame
{login-dialog tf, pf, cb}
}
}
Code:
Customization of Login Screen
The following code defines the customization of controls displayed in the "Custom" selection of our example applet. In the following applet we have customized the look and feel using a style sheet defined in the custom-style-sheet.scurl file. used in this applet can be viewed by selecting this link:
custom-style.scurl (Size: 11.93 KB / Downloads: 1,146)
Code:
{curl 7.0 applet}
|| Identify the StyleSheets.
|| The common StyleSheet sets up some rules (primarily widths) common to the
|| different versions of the login form.
{let common-style-sheet:StyleSheet =
{url "styles/my-styles/common-style.scurl"}
}
|| The "custom" StyleSheet sets up rules for an appearance that is different
|| from the "default" StyleSheet.
{let custom-style-sheet:StyleSheet =
{url "styles/my-styles/custom-style.scurl"}
}
|| Form creation procs
{define-proc {login-dialog
tf:TextField, pf:PasswordField, cb:CommandButton
}:Graphic
{return
{GroupBox
label = "",
{Dialog
{Table
{row-prototype
{cell-prototype
{TextDisplay
|| Specify the style-class you want applied.
style-class = "login",
value = "Username: "
}
},
{cell-prototype tf}
},
{row-prototype
{cell-prototype
{TextDisplay
|| Specify the style-class you want applied.
style-class = "login",
value = "Password: "
}
},
{cell-prototype pf}
},
{row-prototype
{cell-prototype
colspan = 2,
halign = "center",
cb
}
}
}
}
}
}
}
{value
let tf:TextField =
{new TextField,
style-class = "login",
{on v:Validate at tf:TextField do
{if not v.partial? then
{if tf.value != "CurlUser" then
let dlg:Dialog =
{new Dialog,
{GroupBox
label = "",
{hcenter
{VBox
halign = "center",
{Fill height = 0.1cm},
{TextFlowBox
paragraph-justify =
"center",
"The correct " &
"username is " &
"'CurlUser'."
},
{Fill height = 0.1cm},
{CommandButton
label = "OK",
style-class = "ok",
{on Action at cb:CommandButton
do
{cb.dialog.close
"ok"
}
}
},
{Fill height = 0.1cm}
}
}
}
}
{dlg.show title = "Validate"}
{tf.mark-invalid}
set tf.style-class = "validation-error"
else
set tf.style-class = "TextField"
}
}
}
}
let pf:PasswordField = {new PasswordField}
let cb:CommandButton =
{CommandButton
label = "Submit",
{on Action at cb:CommandButton do
{if-non-null dlg = cb.dialog then
{if {validate-dialog dlg} then
let dlg:Dialog =
{new Dialog,
{GroupBox
label = "",
{VBox
halign = "center",
{Fill height = 0.1cm},
{TextFlowBox
text-breakable? = false,
"Submitted"
},
{Fill height = 0.1cm},
{CommandButton
label = "OK",
style-class = "ok",
{on Action at
cb:CommandButton
do
{cb.dialog.close
"ok"
}
}
},
{Fill height = 0.1cm}
}
}
}
{dlg.show title = "Validate"}
}
}
}
}
|| Create a StyleSheet
|| NOTE: In this case it is a composite of the common StyleSheet, and the
|| custom StyleSheet.
let ss:StyleSheet =
{new StyleSheet,
common-style-sheet,
custom-style-sheet
}
|| Install the StyleSheet.
{install-style-sheet ss}
|| Create the UI.
{Frame
{StandardActiveTraversalContainer
halign = "center",
margin = 1cm,
{login-dialog tf, pf, cb}
}
}
}
For more information regarding paragraph formats, please refer to the Curl Styled Controls Library User's Guide that you installed in the Curl Documentation