package org.chartsy.main.utils;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentListener;
import java.awt.event.ContainerListener;
import java.awt.event.FocusListener;
import java.awt.event.HierarchyBoundsListener;
import java.awt.event.HierarchyListener;
import java.awt.event.InputMethodListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelListener;
import java.beans.PropertyChangeListener;
import java.beans.VetoableChangeListener;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.AncestorListener;
/**
*
* @author viorel.gheba
*/
public class HtmlRendererImpl extends JLabel implements HtmlRenderer.Renderer
{
protected static final Rectangle bounds = new Rectangle();
protected static final boolean swingRendering = true;
protected static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
public static enum Type {UNKNOWN, LIST};
protected static boolean noCacheGraphics = Boolean.getBoolean("nb.renderer.nocache");
protected static Reference<Graphics> scratchGraphics = null;
protected boolean centered = false;
protected boolean parentFocused = false;
protected Boolean html = null;
protected int indent = 0;
protected Border border = null;
protected boolean selected = false;
protected boolean leadSelection = false;
protected Dimension prefSize = null;
public Type type = Type.UNKNOWN;
protected int renderStyle = HtmlRenderer.STYLE_CLIP;
protected boolean enabled = true;
public void reset()
{
parentFocused = false;
setCentered(false);
html = null;
indent = 0;
border = null;
setIcon(null);
setOpaque(false);
selected = false;
leadSelection = false;
prefSize = null;
type = Type.UNKNOWN;
renderStyle = HtmlRenderer.STYLE_CLIP;
setFont(UIManager.getFont("controlFont"));
setIconTextGap(3);
setEnabled(true);
border = null;
EMPTY_INSETS.top = 0;
EMPTY_INSETS.left = 0;
EMPTY_INSETS.right = 0;
EMPTY_INSETS.bottom = 0;
}
public Component getListCellRendererComponent
(JList list, Object value, int index, boolean selected,
boolean leadSelection)
{
reset();
configureFrom(value, list, selected, leadSelection);
type = Type.LIST;
if (swingRendering && selected)
{
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
setOpaque(true);
}
if (HtmlLabelUI.isGTK())
{
if (index == -1)
{
Color borderC = UIManager.getColor("controlShadow");
borderC = borderC == null ? Color.GRAY : borderC;
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(borderC),
BorderFactory.createEmptyBorder(3, 2, 3, 2)));
}
else
{
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
}
return this;
}
protected void configureFrom
(Object value, JComponent target, boolean selected, boolean leadSelection)
{
if (value == null)
value = "";
setText((value == null) ? "" : value.toString());
setSelected(selected);
if (selected)
setParentFocused(checkFocused(target));
else
setParentFocused(false);
setEnabled(target.isEnabled());
setLeadSelection(leadSelection);
setFont(target.getFont());
}
protected boolean checkFocused(JComponent c)
{
Component focused
= KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner();
boolean result = c == focused;
if (!result)
result = c.isAncestorOf(focused);
return result;
}
public @Override void addNotify()
{
if (swingRendering)
super.addNotify();
}
public @Override void removeNotify()
{
if (swingRendering)
super.removeNotify();
}
public void setSelected(boolean val)
{
selected = val;
}
public void setParentFocused(boolean val)
{
parentFocused = val;
}
public void setLeadSelection(boolean val)
{
leadSelection = val;
}
public void setCentered(boolean val)
{
centered = val;
if (val)
setIconTextGap(5);
if (swingRendering)
{
if (val)
{
setVerticalTextPosition(JLabel.BOTTOM);
setHorizontalAlignment(JLabel.CENTER);
setHorizontalTextPosition(JLabel.CENTER);
}
else
{
setVerticalTextPosition(JLabel.CENTER);
setHorizontalAlignment(JLabel.LEADING);
setHorizontalTextPosition(JLabel.TRAILING);
}
}
}
public void setIndent(int pixels)
{
this.indent = pixels;
}
public void setHtml(boolean val)
{
Boolean wasHtml = html;
String txt = getText();
html = val ? Boolean.TRUE : Boolean.FALSE;
if (swingRendering && (html != wasHtml))
firePropertyChange("text", txt, getText());
}
public void setRenderStyle(int style)
{
renderStyle = style;
}
int getRenderStyle()
{
return renderStyle;
}
boolean isLeadSelection()
{
return leadSelection;
}
boolean isCentered()
{
return centered;
}
boolean isParentFocused()
{
return parentFocused;
}
boolean isHtml()
{
if (html == null)
{
String s = getText();
html = checkHtml(s);
}
return html.booleanValue();
}
protected Boolean checkHtml(String s)
{
Boolean result;
if (s == null)
result = Boolean.FALSE;
else if (s.startsWith("<html")
|| s.startsWith("<HTML"))
result = Boolean.TRUE;
else
result = Boolean.FALSE;
return result;
}
boolean isSelected()
{
return selected;
}
int getIndent()
{
return indent;
}
Type getType()
{
return type;
}
public @Override Dimension getPreferredSize()
{
if (!swingRendering)
{
if (prefSize == null)
prefSize = getUI().getPreferredSize(this);
return prefSize;
}
else
{
return super.getPreferredSize();
}
}
public @Override String getText()
{
String result = super.getText();
if (swingRendering
&& Boolean.TRUE.equals(html))
result = ensureHtmlTags(result);
else if (swingRendering
&& (html == null))
{
html = checkHtml(super.getText());
if (Boolean.TRUE.equals(html))
result = ensureHtmlTags(result);
}
return result;
}
protected String ensureHtmlTags(String s)
{
s = ensureLegalFontColorTags(s);
if (!s.startsWith("<HTML")
&& !s.startsWith("<html"))
s = "<html>" + s + "</html>";
return s;
}
protected static String ensureLegalFontColorTags(String s)
{
String check = s.toUpperCase();
int start = 0;
int fidx = check.indexOf("<FONT", start);
StringBuffer sb = null;
if ((fidx != -1)
&& (fidx <= s.length()))
{
while ((fidx != -1)
&& (fidx <= s.length()))
{
int cidx = check.indexOf("COLOR", start);
int tagEnd = check.indexOf('>', start);
start = tagEnd + 1;
if (tagEnd == -1)
break;
if (cidx != -1)
{
if (cidx < tagEnd)
{
int eidx = check.indexOf('=', cidx);
if (eidx != -1)
{
int bangIdx = check.indexOf('!', eidx);
if ((bangIdx != -1) && (bangIdx < tagEnd))
{
int colorStart = bangIdx + 1;
int colorEnd = tagEnd;
for (int i = colorStart; i < tagEnd; i++)
{
char c = s.charAt(i);
if (!Character.isLetter(c))
{
colorEnd = i;
break;
}
}
if (sb == null)
sb = new StringBuffer(s);
String colorString = s.substring(colorStart, colorEnd);
String converted = convertToStandardColor(colorString);
sb.replace(bangIdx, colorEnd, converted);
s = sb.toString();
check = s.toUpperCase();
}
}
}
}
fidx = check.indexOf("<FONT", start);
start = fidx;
}
}
if (sb != null)
return sb.toString();
else
return s;
}
protected static String convertToStandardColor(String colorString)
{
Color c = UIManager.getColor(colorString);
if (c == null)
c = Color.BLACK;
StringBuilder sb = new StringBuilder(7);
sb.append('#');
sb.append(hexString(c.getRed()));
sb.append(hexString(c.getGreen()));
sb.append(hexString(c.getBlue()));
return sb.toString();
}
protected static String hexString(int r)
{
String s = Integer.toHexString(r);
if (s.length() == 1)
s = '0' + s;
return s;
}
protected @Override final void firePropertyChange(String name, Object old, Object nue)
{
if (swingRendering)
{
if ("text".equals(name) && isHtml())
nue = getText();
super.firePropertyChange(name, old, nue);
}
}
public @Override Border getBorder()
{
Border result;
if ((indent != 0) && swingRendering)
result = BorderFactory.createEmptyBorder(0, indent, 0, 0);
else
result = border;
return result;
}
public @Override void setBorder(Border b)
{
Border old = border;
border = b;
if (swingRendering)
firePropertyChange("border", old, b);
}
public @Override Insets getInsets()
{
Insets result;
Border b = getBorder();
if (b == null)
result = EMPTY_INSETS;
else
result = b.getBorderInsets(this);
return result;
}
public @Override void setEnabled(boolean b)
{
enabled = b;
if (swingRendering)
super.setEnabled(b);
}
public @Override boolean isEnabled()
{
return enabled;
}
public @Override void updateUI()
{
if (swingRendering)
super.updateUI();
else
setUI(HtmlLabelUI.createUI(this));
}
public @Override Graphics getGraphics()
{
Graphics result = null;
if (isDisplayable())
result = super.getGraphics();
if (result == null)
result = scratchGraphics();
return result;
}
protected static final Graphics scratchGraphics()
{
Graphics result = null;
if (scratchGraphics != null)
{
result = scratchGraphics.get();
if (result != null)
result.setClip(null);
}
if (result == null)
{
result = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(1, 1).getGraphics();
if (!noCacheGraphics)
scratchGraphics = new SoftReference<Graphics>(result);
}
return result;
}
public @Override void setBounds(int x, int y, int w, int h)
{
if (swingRendering)
super.setBounds(x, y, w, h);
bounds.setBounds(x, y, w, h);
}
@Deprecated
public @Override void reshape(int x, int y, int w, int h)
{
if (swingRendering)
super.reshape(x, y, w, h);
}
public @Override int getWidth()
{
return bounds.width;
}
public @Override int getHeight()
{
return bounds.height;
}
public @Override Point getLocation()
{
return bounds.getLocation();
}
public @Override void validate()
{}
public @Override void repaint(long tm, int x, int y, int w, int h)
{}
public @Override void repaint()
{}
public @Override void invalidate()
{}
public @Override void revalidate()
{}
public @Override void addAncestorListener(AncestorListener l)
{
if (swingRendering)
super.addAncestorListener(l);
}
public @Override void addComponentListener(ComponentListener l)
{
if (swingRendering)
super.addComponentListener(l);
}
public @Override void addContainerListener(ContainerListener l)
{
if (swingRendering)
super.addContainerListener(l);
}
public @Override void addHierarchyListener(HierarchyListener l)
{
if (swingRendering)
super.addHierarchyListener(l);
}
public @Override void addHierarchyBoundsListener(HierarchyBoundsListener l)
{
if (swingRendering)
super.addHierarchyBoundsListener(l);
}
public @Override void addInputMethodListener(InputMethodListener l)
{
if (swingRendering)
super.addInputMethodListener(l);
}
public @Override void addFocusListener(FocusListener fl)
{
if (swingRendering)
super.addFocusListener(fl);
}
public @Override void addMouseListener(MouseListener ml)
{
if (swingRendering)
super.addMouseListener(ml);
}
public @Override void addMouseWheelListener(MouseWheelListener ml)
{
if (swingRendering)
super.addMouseWheelListener(ml);
}
public @Override void addMouseMotionListener(MouseMotionListener ml)
{
if (swingRendering)
super.addMouseMotionListener(ml);
}
public @Override void addVetoableChangeListener(VetoableChangeListener vl)
{
if (swingRendering)
super.addVetoableChangeListener(vl);
}
public @Override void addPropertyChangeListener(String s, PropertyChangeListener l)
{
if (swingRendering)
super.addPropertyChangeListener(s, l);
}
public @Override void addPropertyChangeListener(PropertyChangeListener l)
{
if (swingRendering)
super.addPropertyChangeListener(l);
}
}