/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.sun.lwuit;
import com.sun.lwuit.geom.*;
import com.sun.lwuit.plaf.DefaultLookAndFeel;
import com.sun.lwuit.plaf.LookAndFeel;
import com.sun.lwuit.plaf.Style;
import com.sun.lwuit.plaf.UIManager;
import java.util.Hashtable;
/**
* Allows displaying labels and images with different alignment options, this class
* is a base class for several components allowing them to declare alignement/icon
* look in a similar way.
*
* @author Chen Fishbein
*/
public class Label extends Component {
private String text = "";
private Image icon;
private int valign = BOTTOM;
private int textPosition = RIGHT;
private int gap = 2;
private int shiftText = 0;
private boolean tickerRunning = false;
private static boolean defaultTickerEnabled = true;
private boolean tickerEnabled = defaultTickerEnabled;
private long tickerStartTime;
private long tickerDelay;
private boolean rightToLeft;
private boolean endsWith3Points = true;
/**
* Constructs a new label with the specified string of text, left justified.
*
* @param text the string that the label presents.
*/
public Label(String text) {
setUIID("Label");
this.text = text;
localize();
setFocusable(false);
endsWith3Points = UIManager.getInstance().getLookAndFeel().isDefaultEndsWith3Points();
}
Label(String text, String uiid) {
this.text = text;
localize();
setFocusable(false);
// moved this to the UIManager initializations
//setAlignment(CENTER);
setUIID(uiid);
}
/**
* Construct an empty label
*/
public Label() {
this("");
}
/**
* Constructs a new label with the specified icon
*
* @param icon the image that the label presents.
*/
public Label(Image icon) {
this("");
this.icon = icon;
}
/**
* @inheritDoc
*/
public int getBaselineResizeBehavior() {
switch(valign) {
case TOP:
return BRB_CONSTANT_ASCENT;
case BOTTOM:
return BRB_CONSTANT_DESCENT;
case CENTER:
return BRB_CENTER_OFFSET;
}
return BRB_OTHER;
}
/**
* Sets the Label text
*
* @param text the string that the label presents.
*/
public void setText(String text){
this.text = text;
localize();
setShouldCalcPreferredSize(true);
repaint();
}
private void localize() {
this.text = UIManager.getInstance().localize(text, text);
}
/**
* @inheritDoc
*/
void initComponentImpl() {
super.initComponentImpl();
if(hasFocus()) {
LookAndFeel lf = UIManager.getInstance().getLookAndFeel();
if(lf instanceof DefaultLookAndFeel) {
((DefaultLookAndFeel)lf).focusGained(this);
}
}
// solves the case of a user starting a ticker before adding the component
// into the container
if(isTickerEnabled() && isTickerRunning() && !isCellRenderer()) {
getComponentForm().registerAnimatedInternal(this);
}
}
/**
* Returns the label text
*
* @return the label text
*/
public String getText(){
return text;
}
/**
* Sets the Label icon, if the icon is unmodified a repaint would not be triggered
*
* @param icon the image that the label presents.
*/
public void setIcon(Image icon){
if(this.icon == icon) {
return;
}
this.icon = icon;
setShouldCalcPreferredSize(true);
checkAnimation();
repaint();
}
void checkAnimation() {
super.checkAnimation();
if(icon != null && icon.isAnimation()) {
Form parent = getComponentForm();
if(parent != null) {
// animations are always running so the internal animation isn't
// good enough. We never want to stop this sort of animation
parent.registerAnimated(this);
}
}
}
/**
* Returns the labels icon
*
* @return the labels icon
*/
public Image getIcon(){
return icon;
}
/**
* Sets the Alignment of the Label to one of: CENTER, LEFT, RIGHT
*
* @param align alignment value
* @see #CENTER
* @see #LEFT
* @see #RIGHT
* @deprecated use Style.setAlignment instead
*/
public void setAlignment(int align){
getSelectedStyle().setAlignment(align);
getUnselectedStyle().setAlignment(align);
}
/**
* Sets the vertical alignment of the Label to one of: CENTER, TOP, BOTTOM
*
* @param valign alignment value
* @see #CENTER
* @see #TOP
* @see #BOTTOM
*/
public void setVerticalAlignment(int valign) {
if(valign != CENTER && valign != TOP && valign != BOTTOM){
throw new IllegalArgumentException("Alignment can't be set to " + valign);
}
this.valign = valign;
}
/**
* Returns the vertical alignment of the Label, this will only work when the icon
* is in the side of the text and not above or bellow it.
*
* @return the vertical alignment of the Label one of: CENTER, TOP, BOTTOM
* @see #CENTER
* @see #TOP
* @see #BOTTOM
*/
public int getVerticalAlignment(){
return valign;
}
/**
* Returns the alignment of the Label
*
* @return the alignment of the Label one of: CENTER, LEFT, RIGHT
* @see #CENTER
* @see #LEFT
* @see #RIGHT
* @deprecated use Style.getAlignment instead
*/
public int getAlignment(){
return getStyle().getAlignment();
}
/**
* Sets the position of the text relative to the icon if exists
*
* @param textPosition alignment value (LEFT, RIGHT, BOTTOM or TOP)
* @see #LEFT
* @see #RIGHT
* @see #BOTTOM
* @see #TOP
*/
public void setTextPosition(int textPosition) {
if (textPosition != LEFT && textPosition != RIGHT && textPosition != BOTTOM && textPosition != TOP) {
throw new IllegalArgumentException("Text position can't be set to " + textPosition);
}
this.textPosition = textPosition;
}
/**
* Returns The position of the text relative to the icon
*
* @return The position of the text relative to the icon, one of: LEFT, RIGHT, BOTTOM, TOP
* @see #LEFT
* @see #RIGHT
* @see #BOTTOM
* @see #TOP
*/
public int getTextPosition(){
return textPosition;
}
/**
* Set the gap in pixels between the icon/text to the Label boundaries
*
* @param gap the gap in pixels
*/
public void setGap(int gap) {
this.gap = gap;
}
/**
* Returns the gap in pixels between the icon/text to the Label boundaries
*
* @return the gap in pixels between the icon/text to the Label boundaries
*/
public int getGap() {
return gap;
}
/**
* @inheritDoc
*/
protected String paramString() {
return super.paramString() + ", text = " +getText() + ", gap = " + gap;
}
/**
* @inheritDoc
*/
public void paint(Graphics g) {
UIManager.getInstance().getLookAndFeel().drawLabel(g, this);
}
/**
* @inheritDoc
*/
protected Dimension calcPreferredSize(){
return UIManager.getInstance().getLookAndFeel().getLabelPreferredSize(this);
}
/**
* Simple getter to return how many pixels to shift the text inside the Label
* @return number of pixels to shift
*/
public int getShiftText() {
return shiftText;
}
/**
* This method shifts the text from it's position in pixels.
* The value can be positive/negative to move the text to the right/left
*
* @param shiftText The number of pixels to move the text
*/
public void setShiftText(int shiftText) {
this.shiftText = shiftText;
}
/**
* Returns true if a ticker should be started since there is no room to show
* the text in the label.
*
* @return true if a ticker should start running
*/
public boolean shouldTickerStart() {
if(!tickerEnabled){
return false;
}
Style style = getStyle();
int txtW = style.getFont().stringWidth(getText());
int textSpaceW = getAvaliableSpaceForText();
return txtW > textSpaceW && textSpaceW > 0;
}
Image getIconFromState() {
return getIcon();
}
int getAvaliableSpaceForText() {
Style style = getStyle();
int textSpaceW = getWidth() - style.getPadding(isRTL(), Label.RIGHT) - style.getPadding(isRTL(), Label.LEFT);
Image icon = getIconFromState();
if (icon != null && (getTextPosition() == Label.RIGHT || getTextPosition() == Label.LEFT)) {
textSpaceW = textSpaceW - icon.getWidth();
}
return textSpaceW;
}
/**
* This method will start the text ticker
*/
public void startTicker() {
startTicker(UIManager.getInstance().getLookAndFeel().getTickerSpeed(), true);
}
/**
* This method will start the text ticker
*
* @param delay the delay in millisecods between animation intervals
* @param rightToLeft if true move the text to the left
*/
public void startTicker(long delay, boolean rightToLeft){
//return if ticker is not enabled
if(!tickerEnabled){
return;
}
if(!isCellRenderer()){
Form parent = getComponentForm();
if(parent != null) {
parent.registerAnimatedInternal(this);
}
}
tickerStartTime = System.currentTimeMillis();
tickerDelay = delay;
tickerRunning = true;
this.rightToLeft = rightToLeft;
if (isRTL()) {
this.rightToLeft = !this.rightToLeft;
}
}
/**
* Stops the text ticker
*/
public void stopTicker(){
tickerRunning = false;
setShiftText(0);
deregisterAnimatedInternal();
}
/**
* @inheritDoc
*/
void tryDeregisterAnimated() {
}
/**
* Returns true if the ticker is running
*
* @return true if the ticker is running
*/
public boolean isTickerRunning() {
return tickerRunning;
}
/**
* Sets the Label to allow ticking of the text.
* By default is true
*
* @param tickerEnabled
*/
public void setTickerEnabled(boolean tickerEnabled) {
this.tickerEnabled = tickerEnabled;
}
/**
* This method return true if the ticker is enabled on this Label
*
* @return tickerEnabled
*/
public boolean isTickerEnabled() {
return tickerEnabled;
}
/**
* If the Label text is too long fit the text to the widget and add "..."
* points at the end.
* By default this is set to true
*
* @param endsWith3Points true if text should add "..." at the end
*/
public void setEndsWith3Points(boolean endsWith3Points){
this.endsWith3Points = endsWith3Points;
}
/**
* Simple getter
*
* @return true if this Label adds "..." when the text is too long
*/
public boolean isEndsWith3Points() {
return endsWith3Points;
}
/**
* @inheritDoc
*/
public boolean animate() {
boolean animateTicker = false;
if(tickerRunning && tickerStartTime + tickerDelay < System.currentTimeMillis()){
tickerStartTime = System.currentTimeMillis();
if(rightToLeft){
shiftText-=2;
}else{
shiftText+=2;
}
animateTicker = true;
}
// if we have an animated icon then just let it do its thing...
boolean val = icon != null && icon.isAnimation() && icon.animate();
boolean parent = super.animate();
return val || parent || animateTicker;
}
/**
* Allows disabling/enabling tickers globally
*
* @return the defaultTickerEnabled
*/
public static boolean isDefaultTickerEnabled() {
return defaultTickerEnabled;
}
/**
* Allows disabling/enabling tickers globally
* @param aDefaultTickerEnabled the defaultTickerEnabled to set
*/
public static void setDefaultTickerEnabled(boolean aDefaultTickerEnabled) {
defaultTickerEnabled = aDefaultTickerEnabled;
}
}