package net.xoetrope.swing;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.text.View;
import javax.swing.JLabel;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.text.html.HTMLDocument;
import net.xoetrope.xui.XAttributedComponentEx;
import net.xoetrope.xui.XProject;
import net.xoetrope.xui.XProjectManager;
import net.xoetrope.xui.XTextHolder;
import net.xoetrope.xui.XTextRenderer;
import net.xoetrope.xui.build.BuildProperties;
/**
* Draws text. The text may be wrapped over multiple lines.
* <p>Copyright (c) Xoetrope Ltd., 1998-2004<br>
* License: see license.txt
* @version 1.0
*/
public class XLabel extends JLabel implements XTextHolder, XAttributedComponentEx, Scrollable
{
private XProject currentProject;
public XLabel()
{
super();
currentProject = XProjectManager.getCurrentProject();
}
/**
* The renderer that will paint the component
*/
protected XTextRenderer renderer = new XTextRenderer();//null;
protected boolean antiAlias;
/**
* Update the component
* @param g the graphcis context
*/
public void update( Graphics g )
{
paint(g);
}
/**
* Repaint the component once it has been created
*/
public void addNotify()
{
super.addNotify();
repaint( 0 );
}
/**
* Render the text
* @param g the graphcis context
*/
public void paintComponent( Graphics g )
{
Graphics2D g2d = (Graphics2D)g;
Object oldHint = null;
if ( !BuildProperties.BUILD_JDK_118 ) {
oldHint = g2d.getRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING );
g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, antiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF );
}
View v = (View)getClientProperty( "html" );
if ( v != null ) {
Dimension sz = getSize();
Rectangle textRect = new Rectangle( 0, 0, sz.width, sz.height );
v.paint( g, textRect );
}
else if ( renderer != null ) {
renderer.setTransparent( !isOpaque());
Insets insets = new Insets(0, 0, 0, 0);
if ( getBorder() != null )
insets = getBorder().getBorderInsets(this);
renderer.paintText( this, g, insets, getText());
}
else
super.paintComponent( g );
if ( !BuildProperties.BUILD_JDK_118 )
g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, oldHint );
}
/**
* Get the horizontal alignment style constant, the function is same to getHorizontalAlignment()
* @return the horizontal alignment value
*/
public int getAlignment()
{
return this.getHorizontalAlignment();
}
/**
* Set one or more attributes of the component. The function is same to setHorizontalAlignment(int). Attributes include <br>
* align (left|right|center ) or<br>
* alignment (left|right|center )<br>
* buffered (true|false) double buffering<br>
* @param align 1 to right align the text, 0 for left alignment and 2 for centered text
*/
public void setAlignment( int align )
{
this.setHorizontalAlignment( align );
}
/**
* Get the horizontal alignment style constant
* @return the horizontal alignment value
*/
public int getHorizontalAlignment()
{
if ( renderer != null )
return renderer.getHorizontalAlignment();
return super.getHorizontalAlignment();
}
/**
* Set one or more attributes of the component. Attributes include <br>
* halign (left|right|center ) or<br>
* horizontalalignment (left|right|center )<br>
* @param align 1 to right align the text, 0 for left alignment and 2 for centered text
*/
public void setHorizontalAlignment( int align )
{
if ( renderer != null )
renderer.setHorizontalAlignment( align );
else
super.setHorizontalAlignment( align );
}
/**
* Get the vertical alignment style constant
* @return the alignment value
*/
public int getVerticalAlignment()
{
if ( renderer != null )
return renderer.getVerticalAlignment();
return super.getVerticalAlignment();
}
/**
* Set one or more attributes of the component. Attributes include <br>
* valign (top|bottom|center ) or<br>
* verticalalignment (top|bottom|center )<br>
* @param align 1 to right align the text, 0 for left alignment and 2 for centered text
*/
public void setVerticalAlignment( int align )
{
if ( renderer != null )
renderer.setVerticalAlignment( align );
else
super.setVerticalAlignment( align );
}
/**
* Sets the transparency of the text.
* @param b true to make text transparent
*/
public void setTransparent( boolean b )
{
renderer.setTransparent( b );
}
/**
* Set one or more attributes of the component.
* <OL>
* <LI>align (left|right|center ) or</LI>
* <LI>alignment (left|right|center )</LI>
* <LI>opaque (true|false) set the component opaque property</LI>
* <LI>tooltip, value=the tooltip text</LI>
* <LI>buffered, value=(true|false) turn double buffering on or off</LI>
* <LI>antialias, value=(true|false) override the page antialiasing setting</LI>
* </OL>
* @param attribName the attribute name
* @param attribValue the attribute value
* @return 0 for success, non zero for failure or to require some further action
*/
public int setAttribute( String attribName, Object attribValue )
{
return setAttribute( null, attribName, attribValue );
}
/**
* Set one or more attributes of the component.
* <OL>
* <LI>align (left|right|center ) or</LI>
* <LI>alignment (left|right|center )</LI>
* <LI>opaque (true|false) set the component opaque property</LI>
* <LI>tooltip, value=the tooltip text</LI>
* <LI>buffered, value=(true|false) turn double buffering on or off</LI>
* <LI>antialias, value=(true|false) override the page antialiasing setting</LI>
* </OL>
* @param project the current project or null
* @param attribName the attribute name
* @param attribValue the attribute value
* @return 0 for success, non zero for failure or to require some further action
*/
public int setAttribute( XProject project, String attribName, Object attribValue )
{
String attribNameLwr = attribName.toLowerCase();
String attribValueStr = (String)attribValue;
String attribValueLwr = null;
if ( attribValue != null )
attribValueLwr = attribValueStr.toLowerCase();
if ( attribNameLwr.equals( "align" ) || attribNameLwr.equals( "alignment" )) {
if ( attribValueLwr.equals( "right" )) {
if ( renderer != null )
setAlignment( XTextRenderer.RIGHT );
else
super.setHorizontalAlignment( SwingConstants.RIGHT );
}
else if ( attribValueLwr.equals( "center" )) {
if ( renderer != null )
setAlignment( XTextRenderer.CENTER );
else
super.setHorizontalAlignment( SwingConstants.CENTER );
}
else {
if ( renderer != null )
setAlignment( XTextRenderer.LEFT );
else
super.setHorizontalAlignment( SwingConstants.LEFT );
}
}
else if ( attribNameLwr.equals( "buffered" ))
setDoubleBuffered( attribValueLwr.equals( "true" ));
else if ( attribNameLwr.equals( "opaque" ))
setOpaque( attribValue.equals( "true" ));
else if ( attribNameLwr.equals( "tooltip" ))
setToolTipText( (String)attribValue );
else if ( attribNameLwr.equals( "antialias" ))
antiAlias = attribValue.equals( "true" );
else if ( attribNameLwr.equals( "userenderer" ))
renderer = new XTextRenderer();
else if ( attribNameLwr.equals( "content" )) {
String s = attribValue.toString();
if ( project != null )
s = project.getTranslator().translate( s );
setText( s );
}
else
return -1;
return 0;
}
/**
* Gets the preferred size of this component.
* @return a dimension object indicating this component's preferred size
* @see #getMinimumSize
* @see LayoutManager
*/
public Dimension getPreferredSize()
{
String text = getText();
if (( text != null ) && ( text.length() > 0 ))
return super.getPreferredSize();
View v = (View)getClientProperty( "html" );
if ( v != null )
return super.getPreferredSize();
Dimension d = renderer.getPreferredSize( this, text );
if ( getBorder() != null ) {
Insets insets = getBorder().getBorderInsets( this );
d.setSize( d.getWidth() + insets.left + insets.right,
d.getHeight() + insets.top + insets.bottom);
}
return d;
}
// Scrollable interface-------------------------------------------------------
// Allow the component to expan vertically within a scroll pane but not horizontally
/**
* Returns the preferred size of the viewport for a view component.
* For example, the preferred size of a <code>JList</code> component
* is the size required to accommodate all of the cells in its list.
* However, the value of <code>preferredScrollableViewportSize</code>
* is the size required for <code>JList.getVisibleRowCount</code> rows.
* A component without any properties that would affect the viewport
* size should just return <code>getPreferredSize</code> here.
*
* @return the preferredSize of a <code>JViewport</code> whose view
* is this <code>Scrollable</code>
* @see JViewport#getPreferredSize
*/
public Dimension getPreferredScrollableViewportSize()
{
return getPreferredSize();
}
/**
* Components that display logical rows or columns should compute
* the scroll increment that will completely expose one new row
* or column, depending on the value of orientation. Ideally,
* components should handle a partially exposed row or column by
* returning the distance required to completely expose the item.
* <p>
* Scrolling containers, like JScrollPane, will use this method
* each time the user requests a unit scroll.
*
* @param visibleRect The view area visible within the viewport
* @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
* @param direction Less than zero to scroll up/left, greater than zero for down/right.
* @return The "unit" increment for scrolling in the specified direction.
* This value should always be positive.
* @see JScrollBar#setUnitIncrement
*/
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction)
{
return 10;
}
/**
* Components that display logical rows or columns should compute
* the scroll increment that will completely expose one block
* of rows or columns, depending on the value of orientation.
* <p>
* Scrolling containers, like JScrollPane, will use this method
* each time the user requests a block scroll.
*
* @param visibleRect The view area visible within the viewport
* @param orientation Either SwingConstants.VERTICAL or SwingConstants.HORIZONTAL.
* @param direction Less than zero to scroll up/left, greater than zero for down/right.
* @return The "block" increment for scrolling in the specified direction.
* This value should always be positive.
* @see JScrollBar#setBlockIncrement
*/
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction)
{
return 100;
}
/**
* Return true if a viewport should always force the width of this
* <code>Scrollable</code> to match the width of the viewport.
* For example a normal
* text view that supported line wrapping would return true here, since it
* would be undesirable for wrapped lines to disappear beyond the right
* edge of the viewport. Note that returning true for a Scrollable
* whose ancestor is a JScrollPane effectively disables horizontal
* scrolling.
* <p>
* Scrolling containers, like JViewport, will use this method each
* time they are validated.
*
* @return True if a viewport should force the Scrollables width to match its own.
*/
public boolean getScrollableTracksViewportWidth()
{
return true;
}
/**
* Return true if a viewport should always force the height of this
* Scrollable to match the height of the viewport. For example a
* columnar text view that flowed text in left to right columns
* could effectively disable vertical scrolling by returning
* true here.
* <p>
* Scrolling containers, like JViewport, will use this method each
* time they are validated.
*
* @return True if a viewport should force the Scrollables height to match its own.
*/
public boolean getScrollableTracksViewportHeight()
{
return false;
}
// End Scrollable interface---------------------------------------------------
}