====== XScalaWT Stylesheets ====== Tonight I finished a first cut at adding style sheet support to XScalaWT. I'm interested in peoples' thoughts/suggestions on the syntax and so forth. Here's how to define a style sheet in XScalaWT: val WHITE = Display.getDefault.getSystemColor(SWT.COLOR_WHITE) val RED = Display.getDefault.getSystemColor(SWT.COLOR_RED) val INVALID_INPUT="INVALID_INPUT" object loginStyles extends Stylesheet( $[Control] ( // all Controls have a white background _.setBackground(WHITE) ), $class[Control](INVALID_INPUT) ( _.setForeground(RED) ) ) Here we're defining a login dialog box. We want the entire background to be white, and we want to define a style class that can be used to control how things look when there's invalid input in the dialog. (Note that I changed the dollar-sign syntax to mean $tyle, rather than to be the generic object construction syntax. We will see the new generic object construction syntax next.) Here is how we can use this style sheet: var passwordLabel : Label = null val window = shell("Please log in", group("User information", setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)), setLayout(new GridLayout(1, false)), label("Username"), text ( setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)) ), label(""), label("Password", passwordLabel = _), *[Text](SWT.BORDER | SWT.PASSWORD) ( // The manual, "specify everything" syntax setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)) ) ), // OK/Cancel buttons composite ( setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)), setLayout(new GridLayout(2, true)), button("OK", { e : SelectionEvent => passwordLabel.setStyleClass(INVALID_INPUT) }), button("Cancel", { e : SelectionEvent => e.widget.asInstanceOf[Button].getShell.close() } ) ) ) loginStyles.apply(window) Here we actually lay out our login dialog. We apply the style sheet to the dialog on the last line of code. And to prove that we can update a given widget's style class after the fact and have it automatically update, we make the OK button set the password label's style. The result is that clicking "OK" will turn the password label red. (This is accomplished by using Scala implicits to type-safe add the setStyleClass method to Widget and all of its subclasses.) The XScalaWT style sheet support is implemented in exactly 100 lines of Scala, including white space--another illustration of how flexible and expressive Scala is. As usual, full XScalaWT source code is available at [[http://bitbucket.org/djo/xscalawt/]] For reference, here is the source code to the entire example: object LoginBoxStyled { def main(args : Array[String]) : Unit = { val WHITE = Display.getDefault.getSystemColor(SWT.COLOR_WHITE) val RED = Display.getDefault.getSystemColor(SWT.COLOR_RED) var passwordLabel : Label = null val INVALID_INPUT="INVALID_INPUT" object loginStyles extends Stylesheet( $[Control] ( _.setBackground(WHITE) ), $class[Control](INVALID_INPUT) ( _.setForeground(RED) ) ) val window = shell("Please log in", group("User information", setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)), setLayout(new GridLayout(1, false)), label("Username"), text ( setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)) ), label(""), label("Password", passwordLabel = _), *[Text](SWT.BORDER | SWT.PASSWORD) ( // The manual, "specify everything" syntax setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)) ) ), // OK/Cancel buttons composite ( setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)), setLayout(new GridLayout(2, true)), button("OK", { e : SelectionEvent => passwordLabel.setStyleClass(INVALID_INPUT) }), button("Cancel", { e : SelectionEvent => e.widget.asInstanceOf[Button].getShell.close() } ) ) ) loginStyles.apply(window) window.pack val size = window.getSize() window.setSize(250, size.y) runEventLoop(window) } } ~~LINKBACK~~ ~~DISCUSSION~~