Post on 22-May-2015
Theming GWT Applications with the
Appearance Pattern Colin Alworth / Sencha Inc. colin.alworth@sencha.com
Three years ago Cell API and Appearance Pattern
Two years ago SenchaCon 2011, GXT 3 Preview released
Just over a year ago GXT 3.0.0 uses Cell API in Fields, Appearance
everywhere
Three main responsibilities !
• render initial content • update content based on changes, interaction • answer questions about rendered content
Theming GWTAppearance pattern
Examples
• render text, icon, decoration •update for changes •update for hover, focus, mousedown •find focus element, find menu element
Theming GWTButton Appearance
• render with value, options •update for value, options •update for empty, focus, value •find focus element
Theming GWTText Field
• render static content •update to hide/show header, collapse/expand panel
•ask for icons on buttons, elements to hold title, tools, body, buttons
Theming GWTPanel
•appearance controls rendered html •widget deals with all logic •appearance implementation can choose to use or ignore state changes
Theming GWTAppearance contract
•ColorPalette/DatePicker - widget needs to know relative positions of items
•Grid/Tree - needs to guarantee fast creation/lookups
Theming GWTAppearance contract - exceptions
Implementations should be stateless: !•Ensures that appearances will behave for cells •Enables compiler to rewrite methods to static, inline into owning widget if possible !
Theming GWTAppearance contract
• Widgets should invoke GWT.create on the appearance interface
• Module files can declare replace-with rules to specify an implementation !!
Theming GWTConstructing appearances
<replace-with class="com.sencha.gxt...NeptuneInfoAppearance"> <when-type-is class="com.sencha.gxt...Info.InfoAppearance" /> </replace-with> !!
Theming GWTModule rules
<replace-with class="com.sencha.gxt...NeptuneInfoAppearance"> <when-type-is class="com.sencha.gxt...Info.InfoAppearance" /> <when-property-is name="gxt.theme" value="neptune" /> </replace-with> !!
Theming GWTMultiple themes in one app?
•Widgets should expose an appearance constructor •Enables individual cases to use a custom appearance
•Widget’s appearance field should be private/final •Avoids issues with changing appearance without changing dom structure
•Widgets should expose an appearance getter for subclasses !!
Theming GWTGeneral API tips
•Helpful have default appearance implementations that are easy to extend, changing minor details like styles
•Appearances shouldn’t use generics, since they are created by GWT.create, lose any typesafety !!
Theming GWTGeneral API tips
• render method - SafeHtmlBuilder or SafeHtml, either XTemplates, SafeHtmlTemplates, or hand-written Java !<div class='{style.infoWrap}'> <div class='{style.info}'></div> </div> !public void render(SafeHtmlBuilder sb) { sb.append(template.render(styles)); } !!
Theming GWTImplementing appearances
• find, update methods based on that structure !@Override public Element getContentElement(Element parent) { return parent.getFirstChildElement(); } !!
Theming GWTImplementing appearances
•Declare a default constructor (for GWT.create and replace-with)
• If it makes sense, ensure type can be extended !!
Theming GWTImplementing appearances
•consistent set of appearances •defined as a module made of of replace-with declarations
• in GXT 3.1 comes with a gxt.theme property for permutation switching of themes !!
Theming GWTComposing a theme
Automating theme generation
•Early GXT 3 tried few constants in one file, CssResource to reference these in all appearances
•Works when no images need to be created... !!
Theming GWTAutomating theme generation
Base it on •CSS3 gradients •CSS3 rounded corners •SVG vector images •Starts us with a language we already know (rather than inventing new)
•Enables us to use CSS3 right away (in browsers that support it) !!!
Theming GWTLegacy browser image generation
Info Example
Info.display("Hello world","Testing info popup");
Theming GWT
<div class='{style.infoWrap}'>! <div class='{style.info}'></div>!</div>!.infoWrap {! border-style: none;! border-radius: 8px;! background-color: #000000;! opacity: .8;! margin: 2px 0 0 0;!}!.info {! padding: 10px;!}!!
Theming GWTCSS3 html and css
Theming GWTSlicing Corners
Theming GWTSlicing Edges
<div class="{style.contentArea}"> <div class="{style.content}"> <div class="{style.info}"> </div> </div> <div class="{style.topLeft}"></div> <div class="{style.top}"></div> <div class="{style.topRight}"></div> <div class="{style.bottomLeft}"></div> <div class="{style.bottom}"></div> <div class="{style.bottomRight}"></div> <div class="{style.left}"></div> <div class="{style.right}"></div> </div>
Theming GWTLegacy 9-box html
TabPanel Example !
Theming GWTTabPanelExample
Theming GWTTabPanelExample
Theming GWTTabPanelExample
•start with a CSS3 implementation, render in a browser
•specify images that need images •collect from browser positions, borders, corner radius, gradient direction
•decide which images - background, corners, sides •decide which images to stretch •take a screenshot •slice images from screenshot based on positions !
Theming GWTAutomating image generation
Theming GWT
• takes about 5 seconds, most of which is starting browser and launching sample page !
Theming GWTAutomating image generation
•CSS3 can be transformed to images • images + legacy css used for older browsers
•HTML structure different as well •nothing common except for a few values, sizes - where do we store those?
Theming GWTBack to theme generation
theme {! name = "themeName"! basePackage = "com.company.theme"! ! details {! panel {! }! tabs {! }! //...! }!}!!
Theming GWTTheme config
theme {! details {! info {! backgroundColor = "#ffffff"! borderRadius = 8! opacity = 1.0! border = util.border('solid', '#cccccc', 2)! headerText = util.fontStyle("Tahoma, Arial, Verdana, sans-serif", '15px', '#555555', 'bold');! messageText = util.fontStyle("Tahoma, Arial, Verdana, sans-serif", '14px', '#555555');! margin = util.margins(2,0,0,0)! padding = util.padding(2,7)! }! }!}!!!
Theming GWTTheme config
•namespaced properties for easier organization
•values can be string, int, double •some expressions supported •values can be referenced by path •basic set of util methods
Theming GWTTheme config
$ bin/themer.sh !Command missing config files!usage: ThemeBuilder [options] [config ...]! -f,--force force output overwrite! -gen <path> directory to generate code to! -generateConfig <outputFile> Generate sample configuration! -h,--help print this message! -imageFile <path> captured image used for slicing images! -manifestFile <manifestFile> json manifest file of the captured image! -out <jar> path to jar file to generate. Default is! a jar named <theme.name>.jar in the! current directory! -warDir <warDir> directory to compile the css3-based theme! to before images are sliced from it!!
Theming GWTRunning the themed
$ themebuilder/bin/themer.sh themebuilder/examples/quick-start/quick-start.theme!template generation started!template generation complete!image generation started!generating tool icons!!...!!slice complete!packaging started!packaging complete!!
Theming GWTExample config
•quick-start.theme •skeleton-config.theme •maven-jar/ •maven-source/
Theming GWTIncluded samples