Thursday, April 15, 2010

Sample code for GWT TabLayoutPanel - overriding the default CSS styles

If you are lucky like me, you have a designer who creates your screen mockups for you. This is great, because I suck at creating roundy-border type stuff that actually looks good on a web page. Its all great, until you have to figure out how to build the stuff they design.

This post is about styling a GWT TabLayoutPanel in a way that will make your designer friend happy. Well, as much as one of those guys can ever  be happy.

Here is what I have built. Notice how the tabs are styled – much better than the default styles you get out of the box.

gwt_tabcontrol_css_styled

This sample uses the GWT SDK 2.03. It employs UiBinder, but this technique can be used without it as well.

Approach – Build a Custom Theme

There are references out there that indicate that you may be override the default GWT styles in your own custom CSS stylesheet. They seem to indicate that this will take precedence over the styles defined by the CSS in the standard theme.

I never got that to work, as I could see in Firebug that the theme CSS files were loading later than my custom CSS file. No matter how I rearranged in the includes in my HTML file.

So I took a different tack – I created a custom theme based off of a standard theme. Upon creating the custom theme, I changed the default styles for tab controls. This approach was both easy and effective. Note that it won’t work well for cases in which you have multiple tab controls in your project and need to style them differently. You will need to something with adding styles – details for which I don’t have.

For reference, you can find some links out there on creating custom themes. I used the official GWT docs for this, and they were good:

Sample Code

The code below shows the different snippets required to make this happen.

Theme CSS

I will not include everything you need here, as you will use a standard theme CSS as your base for working. Do a search in the SDK to find the base theme you want – standard.css, dark.css, or chrome.css. For Eclipse users, the SDK is found in a location such as:

eclipse/plugins/com.google.gwt.eclipse.sdkbundle.2.0.3/gwt-2.0.3

Once you find your base CSS, copy it into your war directory in your project. Open the file, and search for the Tab styles. Beyond this, it is an exercise in CSS and Firebug to get your tabs looking exactly how you need. For me, mine are defined like this:

.gwt-TabLayoutPanel
{
    height: 300px;
}

.gwt-TabLayoutPanel .gwt-TabLayoutPanelTabs {
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelContent {
  border-color: #e6e7e8;
  border-style: solid;
  border-width: 3px 2px 2px;
  overflow: hidden;
  padding: 6px;
  background: #FFFFFF; 
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab {
  margin-left: 6px;
  padding: 3px 8px 3px 8px;
  cursor: pointer;
  cursor: hand;
  color: black;
  font-size: 1.2em;
  color: #8bc53d;
  text-align: center;
  background: #458818;
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab-selected {
  cursor: default;
  background: #8bc53d;
  font-size: 1.2em;
  color: #FFFFFF;
}

Configure Theme in Rewards.gwt.xml File

Find your *.gwt.xml file, usually in the top level directory of your packages. In here, you will need to disable any standard theme you are using, and inherit the basic CSS style objects into your project. Check the reference in the GWT docs listed above for more info.

<!--  <inherits name='com.google.gwt.user.theme.standard.Standard'/>-->
<!--  <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!--  <inherits name='com.google.gwt.user.theme.dark.Dark'/>     -->
<inherits name='com.google.gwt.user.theme.standard.StandardResources'/>   

Include Custom Theme in Rewards.html

Next, add in your theme’s css file into your UI by including it in the host page. Your html file will be in your war directory. Update it to include your custom .css file, like:

<link type="text/css" rel="stylesheet" href="rewards.css">
<link type="text/css" rel="stylesheet" href="tendril_theme.css">

UiBinder Page

The next thing to do is actually define your TabLayoutPanel in your UI. I use UiBinder for this, but you can do this programmatically as well. Notice that I don’t declare style info for the tab widgets – they automatically consume the custom theme styles.

<g:TabLayoutPanel ui:field="programsTabPanel" barHeight="2" barUnit="EM">
    <g:tab>
        <g:header>Available</g:header>
        <g:HorizontalPanel styleName='program_tab'>
            <g:cell width="35%">
                    CONTENT GOES HERE 
            </g:cell>
            <g:cell width='65%'>
                    CONTENT GOES HERE 
            </g:cell>
        </g:HorizontalPanel>
    </g:tab>
    <g:tab>
        <g:header>Demand Response</g:header>
        <g:HorizontalPanel>
            <g:cell width="35%">
                    CONTENT GOES HERE 
            </g:cell>
            <g:cell width='65%'>
                    CONTENT GOES HERE 
            </g:cell>
        </g:HorizontalPanel>
    </g:tab>
    <g:tab>
        <g:header>Energy Efficiency</g:header>
        <g:HorizontalPanel styleName='program_tab'>
            <g:cell width="35%">
                    CONTENT GOES HERE 
            </g:cell>
            <g:cell width='65%'>
                   CONTENT GOES HERE 
            </g:cell>
        </g:HorizontalPanel>
    </g:tab>
</g:TabLayoutPanel>

Now, the next time you refresh the browser your tabs should look pretty.

Technorati Tags: ,,,,

2 comments: