/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine is distributed in the hope that it will *
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.ui;
import totalcross.ui.font.*;
import totalcross.ui.gfx.*;
/**
* <code>AlignedLabelsContainer</code> is a <code>Container</code> used to align all controls to the maximum width of a set of labels. You can
* define the label alignment. The controls that you add to this container are placed at the right of the labels. Here's a sample of how to use it:
*
* <pre>
* String[] labels =
* {
* "Name",
* "Born date",
* "Telephone",
* "Address",
* "City",
* "Country",
* "",
* };
* AlignedLabelsContainer c = new AlignedLabelsContainer(labels);
* c.setBorderStyle(BORDER_LOWERED);
* c.labelAlign = RIGHT;
* c.foreColors = new int[]{Color.RED,Color.BLACK,Color.BLACK,Color.BLACK,Color.BLACK,Color.BLACK,Color.BLACK,};
* c.setInsets(2,2,2,2);
* c.setFont(font.asBold()); // labels are bold
* c.childrenFont = font; // but controls are normal
* add(c,LEFT+2,TOP+2,FILL-2,PREFERRED+4);
* for (int i =0; i < labels.length-2; i++)
* c.add(new Edit(),LEFT+2,AFTER+(i==0?2:0));
* c.add(new ComboBox(new String[]{"Brazil","France"}),LEFT+2,AFTER);
* c.add(new Button("Insert data"),RIGHT,SAME);
* c.add(new Button("Clear data"),RIGHT,AFTER,SAME,PREFERRED);
* </pre>
* @since TotalCross 1.01
*/
public class AlignedLabelsContainer extends Container // guich@tc110_86
{
/**
* The label captions.
*/
protected String[] labels;
/**
* The computed widths for the labels.
*/
protected int[] widths;
/**
* Sets this member to the font you want to set to the controls that are added to this container.
*
* @since TotalCross 1.25
*/
public Font childrenFont;
/**
* Sets an array with the same number of labels and the colors you want to show for each label. If the number of labels differs, you will get an
* exception. It can be used to hide a label: just set its foreground color to the background color.
*
* @since TotalCross 1.2
*/
public int[] foreColors; // guich@tc120_53
private int maxw,vgap,ileft;
/**
* The alignment of the labels. Defaults to <code>LEFT</code>.
*
* @see #LEFT
* @see #CENTER
* @see #RIGHT
*/
public int labelAlign = LEFT;
/**
* Creates a new <code>AlignedLabelsContainer</code> without labels. You may call <code>setLabels()</code> to set the labels.
*
* @see #AlignedLabelsContainer(String[])
* @see #AlignedLabelsContainer(String[], int)
* @see #setLabels(String[], int)
*/
public AlignedLabelsContainer()
{
setLabels(null,0);
}
/**
* Creates a new <code>AlignedLabelsContainer</code> with the given labels.
*
* @param labels The strings that represents the labels. You may pass <code>null</code>, but be sure to call <code>setLabels()</code> to set the
* labels.
*
* @see #AlignedLabelsContainer(String[], int)
* @see #setLabels(String[], int)
*/
public AlignedLabelsContainer(String[] labels)
{
setLabels(labels,0);
}
/**
* Creates a new <code>AlignedLabelsContainer</code> with the given labels.
*
* @param labels The strings that represents the labels. You may pass <code>null</code>, but be sure to call <code>setLabels()</code> to set the
* labels.
* @param vgap The extra gap between rows. May be negative.
*
* @see #AlignedLabelsContainer(String[])
* @see #setLabels(String[], int)
*/
public AlignedLabelsContainer(String[] labels, int vgap)
{
setLabels(labels, vgap);
}
/**
* Sets the labels and the extra gap between rows (which may be 0).
*
* @param labels The strings that represents the labels. You may pass <code>null</code>, but be sure to call <code>setLabels()</code> again to
* set the labels with a valid value.
* @param vgap The extra gap between rows. May be negative.
*
* @since TotalCross 1.2
* @see #AlignedLabelsContainer(String[])
* @see #AlignedLabelsContainer(String[], int)
*/
public void setLabels(String[] labels, int vgap)
{
if (labels == null) labels = new String[0];
this.labels = labels;
widths = new int[labels.length];
onFontChanged();
this.vgap = vgap;
}
/**
* Called after a <code>setFont()</code>
*/
public void onFontChanged()
{
maxw = 0;
for (int i =0; i < labels.length; i++)
{
widths[i] = fm.stringWidth(labels[i]);
if (widths[i] > maxw)
maxw = widths[i];
}
super.setInsets(maxw+ileft,insets.right, insets.top, insets.bottom); // guich@tc114_3: set the insets again
}
/**
* Since this is an <code>AlignedLabelsContainer</code>, use this to add a label.
*/
public void add(Control c)
{
super.add(c);
if (childrenFont != null)
c.setFont(childrenFont);
}
/**
* Sets the insets value to match the given ones.
*
* @param left The left border value.
* @param right The right border value.
* @param top The top border value.
* @param bottom The bottom border value.
*/
public void setInsets(int left, int right, int top, int bottom)
{
ileft=left;
super.setInsets(maxw+left,right,top,bottom);
}
/**
* Returns the preferred width of this control.
*
* @return The preferred width of this control.
*/
public int getPreferredWidth()
{
return maxw+insets.left+insets.right;
}
/**
* Returns the preferred height of this control.
*
* @return The preferred height of this control.
*/
public int getPreferredHeight()
{
return getLineY(labels.length) + insets.bottom;
}
/**
* Draws the border (if any).
*
* @param g The graphics object for drawing.
*/
public void onPaint(Graphics g)
{
super.onPaint(g);
int left = insets.left - maxw;
int yy = getLineY(0);
int inc = getLineHeight() + getGap(vgap);
yy += Edit.prefH/2; // guich@tc114_5
for (int i =0; i < labels.length; i++, yy += inc)
{
g.foreColor = foreColor;
if (foreColors != null)
g.foreColor = foreColors[i];
switch (labelAlign)
{
case LEFT: g.drawText(labels[i],left,yy, textShadowColor != -1, textShadowColor); break;
case CENTER: g.drawText(labels[i],left+(maxw-widths[i])/2,yy, textShadowColor != -1, textShadowColor); break;
case RIGHT: g.drawText(labels[i],left+maxw-widths[i],yy, textShadowColor != -1, textShadowColor); break;
}
}
}
/**
* Given a line (staring from 0), returns the y position. Can be used to easily align the controls. Note that the line number may be greater than
* the number of assigned Labels.
*
* <pre>
* add(chCasado = new Check("Married"),LEFT,getLineY(4)+2);
* </pre>
*
* @since TotalCross 1.14
*/
public int getLineY(int line) // guich@tc114_4
{
int y0 = insets.top + Edit.prefH + getGap(vgap)-1;
int inc = getLineHeight() + getGap(vgap);
return y0 + inc * line;
}
/**
* Returns the height of a line.
*
* @return The height of a line.
*
* @since TotalCross 1.14
*/
public int getLineHeight() // guich@tc114_4
{
return fmH + Edit.prefH;
}
/**
* Returns the left inset. To be able to center a control, you have to do like this:
*
* <pre>
* control.setRect(CENTER-getLeftInset()/2,...);
* </pre>
*
* @return The left inset.
*/
public int getLeftInset()
{
return maxw;
}
}