Styling User Interfaces

funny quotes sayings funny quotes

In this tutorial we'll grab the code from the very first tutorial and play with mobl styling a little bit. Note that mobl styling is a still somewhat experimental feature and therefore some IDE features, such as code completion may not always be up to par.

The application we will be styling is our tip calculator application. Here's the code that we ended up with:

application tipcalculator
import mobl::ui::generic
screen root() {
  var amount     =  20
  var percentage =  10
  header("Tip calculator")
  group {
    item { numField(amount, label="amount") }
    item { numField(percentage, label="percentage") }
    item { "$" label(amount * (1 + percentage/100)) }
  }
}

As you can tell from the import statement, we are using the mobl::ui::generic set of controls. This set of controls has the nice feature of having some style constants that we can override. Let's try that now, shall we?

Let's open the config.mobl module, or create it if you didn't have one yet. We're going to override the $baseColor styling variable. Styling variables are all prefixed with a $. Add the following line to your config.mobl file and save it:

style $baseColor = rgb(60, 150, 30)

Just for the purpose of demonstration, I added a button at the bottom of the tip calculator, it doesn't do anything. It's just there to show off how the colors work.

Now, by simply redefining the $baseColor, we can change the basic color scheme:

Pretty nifty, right? Of course, we can also choose our own, custom color. Pick any rgb values you like, a gray one, for instance:

style $baseColor = rgb(100, 100, 100)

We can get more granular than this, however. For instance, colors for buttons and shadows are derived from the $baseColor by default, but can be overridden in a similar fashion. Here are the default values for these variables:

style $buttonFromColor       = rgb($baseColor.r+170,
                                   $baseColor.g+170,
                                   $baseColor.b+170)
style $buttonToColor         = rgb($baseColor.r+120,
                                   $baseColor.g+120,
                                   $baseColor.b + 120)
style $buttonPushedFromColor = rgb($baseColor.r+100,
                                   $baseColor.g+100,
                                   $baseColor.b+100)
style $buttonPushedToColor   = rgb($baseColor.r+50,
                                   $baseColor.g+50,
                                   $baseColor.b+50)
style $textButtonColor       = rgb($baseColor.r~50,
                                   $baseColor.g~50,
                                   $baseColor.b~50)
style $textButtonShadowColor = rgb($baseColor.r+100,
                                   $baseColor.g+100,
                                   $baseColor.b+100)

As you can tell, it is possible to do simple calculations in these values. Operators that are supported are +, *, / and ~ (for subtraction, using - would be ambiguous with CSS). Each of these individual style variables can be overridden.

But what if we want something completely different, a different style for one particular button, for instance? Well, that's possible too.

Custom styles

The button control has two optional styling arguments: style and pushedStyle. The latter is used to render the button when it is, well, pushed. Before we set those, however, we have to define new versions of these styles. Therefore, we add the following new styles to our ui.mobl:

style myButtonStyle {
  border: 1px solid #000;
  padding: 10px;
  background-color: #ccc;
  line-height: 3em;
  margin: 5px;
}
style myButtonPushedStyle {
  border: 1px solid #000;
  padding: 10px;
  background-color: #777;
  line-height: 3em;
  margin: 5px;
}

To those familiar with CSS this will immediately look familiar. The body of the style is pure CSS, with a few additional features that we will get to later. As can be seen, a style has a name and a body. Since all top-level definitions in a module share the same namespace it is good practice to end a style name with Style. Now, from our tipcalculator.mobl file we can create a button that uses this style:

button("A button", style=myButtonStyle,
                   pushedStyle=myButtonPushedStyle)

Save the file and run the application to see the resulting, simple plain button:

Looks kind of ugly though. It would be much improved if the button had rounded corners. Although the border-radius property is part of CSS3, it has not been implemented in many browser with that name. In webkit browser this property is named -webkit-border-radius and in Firefox it's -moz-border-radius. To do it well, to create borders we basically would have to repeat ourselves a few times:

-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;

Obviously, that is sub-optimal. To prevent repeating yourself, mobl offers style mixins. A few useful ones are defined in the mobl::ui::stylemixin module. Here's the definition of the borderRadiusMixin:

style mixin borderRadiusMixin($radius) {
  -moz-border-radius: $radius;
  -webkit-border-radius: $radius;
  border-radius: $radius;
}

It can be used as follows:

style myButtonStyle {
  ...
  margin: 5px;
  borderRadiusMixin(5px);
}

Which will be expanded by the compiler to:

style myButtonStyle {
  ...
  margin: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

The button now has rounded corners!

Background gradients also look nice on buttons, let's add one of those using the backgroundGradient mixin:

style myButtonStyle {
  border: 1px solid #000;
  padding: 10px;
  line-height: 3em;
  margin: 5px;
  borderRadiusMixin(5px);
  backgroundGradientMixin(#ddd, #bbb);
}
style myButtonPushedStyle {
  border: 1px solid #000;
  padding: 10px;
  line-height: 3em;
  margin: 5px;
  borderRadiusMixin(5px);
  backgroundGradientMixin(#aaa, #999);
}

Now we have buttons with a nice, subtle gradient:

There is still a fair bit of duplication in the pushed and non-pushed version of the style. Let's git rid of that as well, using a mixin:

style mixin myButtonStyleMixin($fromColor, $toColor) {
  border: 1px solid #000;
  padding: 10px;
  line-height: 3em;
  margin: 5px;
  borderRadiusMixin(5px);
  backgroundGradientMixin($fromColor, $toColor);
}
style myButtonStyle {
  myButtonStyleMixin(#ddd, #bbb);
}
style myButtonPushedStyle {
  myButtonStyleMixin(#aaa, #999);
}

Wohoo!

Conclusion

Mobl's styling language is designed to be flexible as well as powerful. CSS is an excellent language to style applications and mobl embraces its features. However, CSS does miss a few useful features, such as style variables and mixins. Custom languages like Sass add some of these features, but require an additional tool in the tool chain. Mobl borrows some of Sass's features and integrates them into its styling language.

When styling an application a first step may be to adapt the $baseColor variable and other styling variables. Then, to style particular controls, control-specific styles can be defined and used.

tutorial/styling.txt · Last modified: 2013/10/01 02:29 (external edit)