
In part one of pimp my LWUIT we covered basic gradients and applying them throughout the application, this time we will try to make some of our top level controls rounded.
I talked previously about rounded buttons and the ways to achieve them so I won't dig into that again, I will however talk about making the dialogs/menus rounded since these are not as intuitive to customize especially not in this context.
I would also like to make the dialogs semi transparent allowing an even deeper feel of the applications depth and context.
Note that the current version of LWUIT has a couple of minor border rendering glitches, these will be fixed in the next drop of LWUIT.
Lets begin by making our dialogs more "modern" lets make them look round and semi translucent. This is relatively easy to do as demonstrated by the previous post although there are some minor "gotchas" here. First, is the fact that the title and dialog body are technically separate components. The solution is to use the round border on the dialog body and ignore its title, just never use the title and all will end well (there is a more elaborate trick of creating a "half" round rectangle for the title and the bottom half for the body, but that I will leave as an exercise for you guys).
This is trivial to workaround:
helloForm.addCommand(new Command("Show Dialog") {No title...
public void actionPerformed(ActionEvent ev) {
Dialog.show(null, "Rounded Dialog Body", "OK", null);
}
});
The second gotcha is the static dialog show methods, they include the body using a TextArea component. Since its opaque and ugly we must theme it to match the dialog.
To solve this we might as well create a default theme of colors to match the common colors, this is much easier than other alternatives for themeing (save maybe for using the resource editor).
To support round dialogs we can just use the getComponentStyle/setComponentStyle pair to set the style we want for the dialog which produces the results you see here.
public PimpLookAndFeel() {We can also round the menu, using this technique (or even simpler using the resource editor) but that wouldn't be "cool enough"...
Hashtable themeProps = new Hashtable();
themeProps.put("fgColor", "dddddd");
themeProps.put("SoftButton.fgColor", "0");
themeProps.put("Title.fgColor", "0");
themeProps.put("fgSelectionColor", "ffffff");
themeProps.put("bgColor", "0");
themeProps.put("bgSelectionColor", "0");themeProps.put("transparency", "0");
themeProps.put("border", Border.getEmpty());
UIManager.getInstance().setThemeProps(themeProps);
s = UIManager.getInstance().getComponentStyle("Dialog");
s.setBorder(Border.createRoundBorder(10, 10));
s.setBgTransparency(100);
s.setBgColor(0);
s.setFgColor(0xffffff);
UIManager.getInstance().setComponentStyle("Dialog", s);
}
Lets extend the linear gradient example from last time into a Border implementation and make it into a rounded gradient border:
/**Now to use this in the code all we have to do is update the PimpLookAndFeel as such:
* A simple border that can draw a linear gradient as the background of any component.
* The gradient is cached in a mutable image for performance.
*
* @author Shai Almog
*/
public class RoundedBorderLinearGradient extends Border {
private int sourceColor;
private int destColor;
private boolean horizontal;
private Image cache;
private int arcWidth;
private int arcHeight;
private int borderColor;
public RoundedBorderLinearGradient(int sourceColor, int destColor, boolean horizontal, int borderColor, int arcWidth, int arcHeight) {
this.sourceColor = sourceColor;
this.destColor = destColor;
this.horizontal = horizontal;
this.arcHeight = arcHeight;
this.arcWidth = arcWidth;
this.borderColor = borderColor;
}
public boolean isBackgroundPainter() {
return true;
}
public void paintBorderBackground(Graphics g, Component c) {
int x = c.getX();
int y = c.getY();
int height = c.getHeight();
int width = c.getWidth();
if(cache == null || width != cache.getWidth() || height != cache.getHeight()) {
cache = Image.createImage(width, height);
Graphics current = cache.getGraphics();
current.setColor(0);
current.fillRoundRect(0, 0, width, height, arcWidth, arcHeight);
int[] rgb = cache.getRGB();
current.fillLinearGradient(sourceColor, destColor, 0, 0, width, height, horizontal);
int[] rgb2 = cache.getRGB();
for(int iter = 0 ; iter < rgb.length ; iter++) {
if(rgb[iter] == 0xffffffff) {
rgb2[iter] = 0;
}
}
cache = Image.createImage(rgb2, width, height);
}
g.drawImage(cache, x, y);
}
public void paint(Graphics g, Component c) {
int oldColor = g.getColor();
g.setColor(borderColor);
g.drawRoundRect(c.getX(), c.getY(), c.getWidth(), c.getHeight(), arcWidth, arcHeight);
g.setColor(oldColor);
}
}
public class PimpLookAndFeel extends DefaultLookAndFeel {
private Painter formPainer = new RadialGradientPainter(0x999999, 0);
public PimpLookAndFeel() {
Hashtable themeProps = new Hashtable();
themeProps.put("fgColor", "dddddd");
themeProps.put("SoftButton.fgColor", "0");
themeProps.put("Title.fgColor", "0");
themeProps.put("fgSelectionColor", "ffffff");
themeProps.put("bgColor", "0");
themeProps.put("bgSelectionColor", "0");
themeProps.put("transparency", "0");
themeProps.put("border", Border.getEmpty());
UIManager.getInstance().setThemeProps(themeProps);
Style s = UIManager.getInstance().getComponentStyle("Menu");
s.setBorder(new RoundedBorderLinearGradient(0xff0000, 0xffffff, true, 0xff, 10, 10));
s.setBgTransparency(255);
UIManager.getInstance().setComponentStyle("Menu", s);
s = UIManager.getInstance().getComponentStyle("Dialog");
s.setBorder(Border.createRoundBorder(10, 10));
s.setBgTransparency(100);
s.setBgColor(0);
s.setFgColor(0xffffff);
UIManager.getInstance().setComponentStyle("Dialog", s);
}
public void bind(Component c) {
if(c instanceof Form) {
if(!(c instanceof Dialog)) {
c.getStyle().setBgPainter(formPainer);
}
Form f = (Form)c;
f.getTitleStyle().setBgPainter(new LinearGradientPainter(0xffffff, 0xaaaaaa, false));
f.getSoftButtonStyle().setBgPainter(new LinearGradientPainter(0xaaaaaa, 0xffffff, false));
}
}
}

0 comments:
Post a Comment