Thursday, March 26, 2009

Painting custom commands

Commands should be the last elements drawn on the screen. This way the user will always know his options for that screen.
We are using the height of commands area as the default font height, so we need to override getHeight method:
private boolean hasCommands () {
   return (this.leftCommand != null) || (this.rightCommand != null);
}
public int getHeight () {
   int height = super.getHeight();
   
   if (hasCommands()) 
      height -= Font.getDefaultFont().getHeight();

   return height;
}
A simple way to implement command drawing is:
protected paint (Graphics g) {
   // draw other elements

   if (hasCommands()) {
      int commandHeight = Font.getDefaultFont().getHeight();

      // clear command area
      g.setColor(0xffffff); // white
      g.fillRect(0, super.getHeight() - commandHeight, getWidth(), commandHeight);
      g.setColor(0); // black
      g.setFont(Font.getDefaultFont());
      if (this.leftCommand != null) {
         g.drawString(this.leftCommand.getLabel(), 0, super.getHeight(), Graphics.LEFT | Graphics.BOTTOM);
      }
      if (this.rightCommand != null) {
         g.drawString(this.rightCommand.getLabel(), getWidth(), super.getHeight(), Graphics.RIGHT | Graphics.BOTTOM);
      }
   }
}
At LWUIT there is a simple implementation as this at DefaultLookAndFeel class.
A better approach is to give visual feedback on keyPressed calls, for example, changing the font color before painting a command.
Lets define two new attributes and add keyPressed method:
private boolean leftCommandPressed;
private boolean rightCommandPressed;
protected void keyPressed (int keyCode) {
   if (keyCode == this.leftCommandKey && this.leftCommand != null) {
      this.leftCommandPressed = true;
      this.repaint();
   } else if (keyCode == this.rightCommandKey && this.rightCommand != null) {
      this.rightCommandPressed = true;
      this.repaint();
   }
}
Now we change paint method to set command color according to these new attributes.
protected paint (Graphics g) {
   if (hasCommands()) {
      if (this.leftCommand != null) {
         if (this.leftCommandPressed) {
            g.setColor(0x080808); // gray
         } else {
            g.setColor(0); // black
         }
         g.drawString(this.leftCommand.getLabel(), 0, super.getHeight(), Graphics.LEFT | Graphics.BOTTOM);
      }
      if (this.rightCommand != null) {
         if (this.rightCommandPressed) {
            g.setColor(0x080808); // gray
         } else {
            g.setColor(0); // black
         }
         g.drawString(this.rightCommand.getLabel(), getWidth(), super.getHeight(), Graphics.RIGHT | Graphics.BOTTOM);
      }
   }
}
And change keyReleased to reset the attributes:
protected void keyReleased (int keyCode) {
   if (this.commandListener != null){
      if (keyCode == this.leftCommandKey && this.leftCommand != null) {
         this.leftCommandPressed = false;
         this.commandListener.commandAction(this.leftCommand, this);
      } else if (keyCode == this.rightCommandKey && this.rightCommand != null) {
         this.rightCommandPressed = false;
         this.commandListener.commandAction(this.rightCommand, this);
      }
   }
}

No comments: