/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.smart.dataui;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.net.URL;
import java.util.StringTokenizer;
import javax.swing.GrayFilter;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.IconUIResource;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.IModeManager;
import com.servoy.j2db.IScriptExecuter;
import com.servoy.j2db.MediaURLStreamHandler;
import com.servoy.j2db.component.ComponentFactory;
import com.servoy.j2db.persistence.Media;
import com.servoy.j2db.ui.IDataRenderer;
import com.servoy.j2db.ui.IEventExecutor;
import com.servoy.j2db.ui.ILabel;
import com.servoy.j2db.ui.ISupportCachedLocationAndSize;
import com.servoy.j2db.ui.scripting.AbstractHTMLSubmitRuntimeLabel;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.HtmlUtils;
import com.servoy.j2db.util.ISkinnable;
import com.servoy.j2db.util.ImageLoader;
import com.servoy.j2db.util.UIUtils;
import com.servoy.j2db.util.Utils;
import com.servoy.j2db.util.gui.MyImageIcon;
import com.servoy.j2db.util.gui.SpecialMatteBorder;
/**
* @author jcompagner
*/
public abstract class AbstractScriptLabel extends JLabel implements ISkinnable, ILabel, ISupportCachedLocationAndSize
{
private static final long serialVersionUID = 1L;
private int rotation;
private int mediaOption;
private int textTransformMode;
private boolean specialPaint = false;
protected IApplication application;
private boolean borderPainted = true;
protected EventExecutor eventExecutor;
protected final AbstractHTMLSubmitRuntimeLabel<ILabel> scriptable;
private MouseAdapter actionMouseAdapter = null;
private MouseAdapter doubleClickMouseAdapter = null;
private MouseAdapter rightclickMouseAdapter = null;
private MouseAdapter rolloverMouseAdapter = null;
public AbstractScriptLabel(IApplication app, AbstractHTMLSubmitRuntimeLabel<ILabel> scriptable)
{
this.scriptable = scriptable;
application = app;
eventExecutor = new EventExecutor(this);
}
public final AbstractHTMLSubmitRuntimeLabel<ILabel> getScriptObject()
{
return scriptable;
}
/**
* Fix for bad font rendering (bad kerning == strange spacing) in java 1.5 see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5097047
*/
@Override
public FontMetrics getFontMetrics(Font font)
{
if (application != null)//getFontMetrics can be called in the constructor super call before application is assigned
{
boolean isPrinting = Utils.getAsBoolean(application.getRuntimeProperties().get("isPrinting")); //$NON-NLS-1$
if (isPrinting)
{
Graphics g = (Graphics)application.getRuntimeProperties().get("printGraphics"); //$NON-NLS-1$
if (g != null)
{
String text = getText();
// only return print graphics font metrics if text does not start with 'W',
// because of left side bearing issue
if (!(text != null && text.length() > 0 && text.charAt(0) == 'W')) return g.getFontMetrics(font);
}
}
}
return super.getFontMetrics(font);
}
/**
* Fix for bad font rendering (bad kerning == strange spacing) in java 1.5 see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5097047
*/
@Override
protected void paintComponent(Graphics g)
{
boolean isPrinting = Utils.getAsBoolean(application.getRuntimeProperties().get("isPrinting")); //$NON-NLS-1$
if (isPrinting && getText() != null && !HtmlUtils.startsWithHtml(getText()) && isEnabled() && getIcon() == null && !isOpaque() &&
isEmptyBorder(getBorder()))
{
FontMetrics fm = getFontMetrics(getFont());
Insets insets = getInsets(new Insets(0, 0, 0, 0));
Rectangle paintTextR = new Rectangle();
Rectangle paintViewR = new Rectangle();
Rectangle paintIconR = new Rectangle();
paintViewR.x = insets.left;
paintViewR.y = insets.top;
paintViewR.width = getWidth() - (insets.left + insets.right);
paintViewR.height = getHeight() - (insets.top + insets.bottom);
paintTextR.x = paintTextR.y = paintTextR.width = paintTextR.height = 0;
SwingUtilities.layoutCompoundLabel(this, fm, getText(), null, this.getVerticalAlignment(), this.getHorizontalAlignment(),
this.getVerticalTextPosition(), this.getHorizontalTextPosition(), paintViewR, paintIconR, paintTextR, this.getIconTextGap());
int textX = paintTextR.x;
int textY = paintTextR.y + fm.getAscent();
g.drawString(getText(), textX, textY);
}
else
{
// metal and windows laf do not sets the font, they rely on the setting of the font
// by the container, when rendering the child, but that is not working in case of
// table views where the label is not a child, so lets just set the component font
// on the graphics
g.setFont(getFont());
super.paintComponent(g);
}
}
private boolean isEmptyBorder(Border border)
{
if (border == null) return true;
if (border instanceof EmptyBorder)
{
Insets i = ((EmptyBorder)border).getBorderInsets();
if (i != null)
{
return (i.bottom == 0 && i.top == 0 && i.left == 0 && i.right == 0);
}
}
return false;
}
@Override
public void setToolTipText(String tip)
{
if (!Utils.stringIsEmpty(tip))
{
if (!Utils.stringContainsIgnoreCase(tip, "<html")) //$NON-NLS-1$
{
super.setToolTipText(tip);
}
else if (HtmlUtils.hasUsefulHtmlContent(tip))
{
super.setToolTipText(tip);
}
}
else
{
super.setToolTipText(null);
}
}
//fix for incorrect clipping
@Override
public void print(Graphics g)
{
Shape saveClip = g.getClip();
try
{
int w = getWidth();
int h = getHeight();
if (saveClip != null)
{
g.setClip(saveClip.getBounds().intersection(new Rectangle(0, 0, w, h)));
}
else
{
g.setClip(0, 0, w, h);
}
super.print(g);
}
finally
{
g.setClip(saveClip);
}
}
/**
* Created this method in order to not remove this piece of code, but make it take into account rotation.
*/
private void superModifiedPaint(Graphics g)
{
if (application.getModeManager().getMode() == IModeManager.PREVIEW_MODE)
{
// don't remember what this code is suppose to fix (why is condition based on PREVIEW_MODE and not on application.getRuntimeProperty("isprinting"));
// also it seems that super.paint(g) would call this "htmlView.setSize(r.width, r.height)" anyway if needed so this entire "if" statement could be unnecessary;
// however, if there was a problem on some OS/java version/L&F, it might be that the condition needs to be changed to "isprinting"
View htmlView = getViewThatIsAbleToWrap();
if (htmlView != null)
{
Rectangle r = getTextBoundsForSize(new Dimension(getWidth(), getHeight())); // these will take into account rotation because of the getHeight/getWidth methods
htmlView.setSize(r.width, r.height);
}
}
super.paint(g);
}
@Override
public void paint(Graphics g)
{
if (rotation == 0)
{
superModifiedPaint(g);
}
else
{
borderPainted = false;
AffineTransform at = ((Graphics2D)g).getTransform();
AffineTransform save = (AffineTransform)at.clone();
try
{
int w = getWidth();
int h = getHeight();
if (rotation >= 45 && rotation <= 135)
{
specialPaint = true;
at.rotate(Math.toRadians(rotation), w / 2, w / 2);
}
else if (rotation >= 135 && rotation <= 225)
{
at.rotate(Math.toRadians(rotation), w / 2, h / 2);
}
else
{
specialPaint = true;
at.rotate(Math.toRadians(rotation), h / 2, h / 2);
}
((Graphics2D)g).setTransform(at);
superModifiedPaint(g);
}
finally
{
specialPaint = false;
((Graphics2D)g).setTransform(save);
// now paint the border
borderPainted = true;
paintBorder(g);
borderPainted = false;
}
}
}
@Override
protected void paintBorder(Graphics g)
{
if (borderPainted)
{
super.paintBorder(g);
}
}
@Override
public int getWidth()
{
if (specialPaint)
{
return super.getHeight();
}
else
{
return super.getWidth();
}
}
@Override
public int getHeight()
{
if (specialPaint)
{
return super.getWidth();
}
else
{
return super.getHeight();
}
}
private int preferredWidth = -1;
public void setPreferredWidth(int preferredWidth)
{
this.preferredWidth = preferredWidth;
}
@Override
public Dimension getPreferredSize()
{
Dimension size = getSize();
Insets insets = getInsets();
Dimension preferred;
if (preferredWidth < 0)
{
preferred = super.getPreferredSize(); // use the preferred width, change the height
}
else
{
preferred = new Dimension();
preferred.width = preferredWidth;
size.width = preferredWidth;
}
View htmlView = getViewThatIsAbleToWrap();
if (htmlView == null)
{
return super.getPreferredSize();
}
Rectangle r = getTextBoundsForSize(size);
htmlView.setSize(r.width, r.height);
preferred.height = (int)htmlView.getPreferredSpan(View.Y_AXIS) + insets.top + insets.bottom;
return preferred;
}
private View getViewThatIsAbleToWrap()
{
View htmlView = (View)getClientProperty(BasicHTML.propertyKey);
if (htmlView != null)
{
htmlView = htmlView.getView(0);
}
return htmlView;
}
private Rectangle getTextBoundsForSize(Dimension size)
{
Insets insets = getInsets();
Rectangle vr = new Rectangle(insets.left, insets.top, size.width - insets.right - insets.left, size.height - insets.bottom - insets.top);
Rectangle r = new Rectangle();
SwingUtilities.layoutCompoundLabel(this, getFontMetrics(getFont()), getText(), getIcon(), getVerticalAlignment(), getHorizontalAlignment(),
getVerticalTextPosition(), getHorizontalTextPosition(), vr, new Rectangle(), r, getIconTextGap());
return r;
}
@Override
public void setUI(ComponentUI ui)
{
super.setUI(ui);
}
public void setFocusPainted(boolean showFocus)
{
if (showFocus)
{
final SpecialMatteBorder border = new SpecialMatteBorder(1, 1, 1, 1, Color.BLACK, Color.BLACK, Color.BLACK, Color.BLACK);
border.setDashPattern(new float[] { 1 });
addFocusListener(new FocusListener()
{
public void focusGained(FocusEvent e)
{
if (getBorder() == null) setBorder(border);
}
public void focusLost(FocusEvent e)
{
if (getBorder() == border) setBorder(null);
}
});
}
}
/*
* _____________________________________________________________ Methods for javascript
*/
public void setImageURL(String text_url)
{
this.text_url = text_url;
try
{
if (text_url == null)
{
setIcon((Icon)null);
}
else
{
URL url = new URL(text_url);
setIcon(new ImageIcon(url));
}
}
catch (Exception e)
{
Debug.error(e);
}
}
private String text_url;
public String getImageURL()
{
return text_url;
}
public void setRolloverImageURL(String image_url)
{
this.rollover_url = image_url;
try
{
if (image_url != null) setRolloverIcon(new ImageIcon(new URL(image_url)));
else setRolloverIcon((ImageIcon)null);
}
catch (Exception e)
{
Debug.error(e);
}
}
private String rollover_url;
public String getRolloverImageURL()
{
return rollover_url;
}
public String getParameterValue(String param)
{
// TODO catch the submit of a html that is displayed.
return null;
}
public byte[] getThumbnailJPGImage(int width, int height)
{
return AbstractScriptButton.getThumbnailJPGImage(this, width, height, getIcon());
}
public void setComponentVisible(boolean b_visible)
{
if (viewable)
{
setVisible(b_visible);
}
}
public void setComponentEnabled(final boolean b)
{
if (accessible)
{
super.setEnabled(b);
}
}
private boolean accessible = true;
public void setAccessible(boolean b)
{
if (!b) setComponentEnabled(b);
accessible = b;
}
private boolean viewable = true;
public void setViewable(boolean b)
{
if (!b) setComponentVisible(b);
this.viewable = b;
}
public boolean isViewable()
{
return viewable;
}
public int getAbsoluteFormLocationY()
{
Container parent = getParent();
while ((parent != null) && !(parent instanceof IDataRenderer))
{
parent = parent.getParent();
}
if (parent != null)
{
return ((IDataRenderer)parent).getYOffset() + getLocation().y;
}
return getLocation().y;
}
private Point cachedLocation;
public Point getCachedLocation()
{
return cachedLocation;
}
public void setCachedLocation(Point location)
{
this.cachedLocation = location;
}
public void setCachedSize(Dimension size)
{
this.cachedSize = size;
}
private Dimension cachedSize;
public Dimension getCachedSize()
{
return cachedSize;
}
private IconUIResource disabledIcon;
@Override
public Icon getDisabledIcon()
{
if (disabledIcon != null) return disabledIcon;
if (getIcon() instanceof MyImageIcon)
{
MyImageIcon icon = (MyImageIcon)getIcon();
icon.getIconWidth();
ImageIcon scaledIcon = icon.getScaledIcon(0, 0);
if (scaledIcon != null)
{
disabledIcon = new IconUIResource(new ImageIcon(GrayFilter.createDisabledImage(scaledIcon.getImage())));
return disabledIcon;
}
}
return super.getDisabledIcon();
}
public int getMediaIcon()
{
return mediaId;
}
private int mediaId;
public void setMediaIcon(int mediaId)
{
this.mediaId = mediaId;
try
{
setIcon(ComponentFactory.loadIcon(application.getFlattenedSolution(), new Integer(mediaId)));
Media media = application.getFlattenedSolution().getMedia(mediaId);
if (media != null) text_url = MediaURLStreamHandler.MEDIA_URL_DEF + media.getName();
}
catch (Exception ex)
{
Debug.error(ex);
}
}
/**
* processed on background thread and makes it scale if to-big/small
*/
@Override
public void setIcon(Icon icon)
{
if (normalIcon == null && icon == null)
{
// no change or not initialized yet
super.setIcon(icon);
}
else
{
setIconDirect(icon, getNextSeq());
}
}
/**
* processed on background thread and makes it scale if to-big/small
*/
public void setIcon(byte[] data)
{
setIconDirect(data, getNextSeq());
}
public void setIconDirect(byte[] data, int seq)
{
if (imageSeq == seq)
{
ComponentFactory.deregisterIcon(normalIcon);
if (data != null)
{
disabledIcon = null;
// media option 1 == crop so no scaling
if (mediaOption != 1)
{
normalIcon = new MyImageIcon(application, this, data, mediaOption);
}
else
{
normalIcon = ImageLoader.getIcon(data, -1, -1, true);
}
ComponentFactory.registerIcon(normalIcon);
}
else
{
normalIcon = null;
}
if (application.getI18NMessage("servoy.imageMedia.loadingImage").equals(getText())) //$NON-NLS-1$
{
setText(null);
}
try
{
application.invokeAndWait(new Runnable()
{
public void run()
{
AbstractScriptLabel.super.setIcon(normalIcon);
}
});
}
catch (Exception e)
{
Debug.error(e);
}
}
}
/**
* show processed on background thread, is put on event thread
*/
public void setIconDirect(Icon icon, int seq)
{
if (imageSeq == seq)
{
ComponentFactory.deregisterIcon(normalIcon);
disabledIcon = null;
// media option 1 == crop so no scaling
if (mediaOption != 1 && icon instanceof ImageIcon)
{
normalIcon = new MyImageIcon(application, this, (ImageIcon)icon, mediaOption);
}
else
{
normalIcon = icon;
}
ComponentFactory.registerIcon(normalIcon);
if (application.getI18NMessage("servoy.imageMedia.loadingImage").equals(getText())) //$NON-NLS-1$
{
setText(null);
}
try
{
application.invokeAndWait(new Runnable()
{
public void run()
{
AbstractScriptLabel.super.setIcon(normalIcon);
}
});
}
catch (Exception e)
{
Debug.error(e);
}
}
}
private int imageSeq = 1;
int getNextSeq()
{
imageSeq++;
return imageSeq;
}
private Icon normalIcon;
private Icon rolloverIcon;
public void setRolloverIcon(byte[] data)
{
ComponentFactory.deregisterIcon(rolloverIcon);
if (mediaOption != 1 && data != null)
{
rolloverIcon = new MyImageIcon(application, this, data, mediaOption);
}
else
{
rolloverIcon = ImageLoader.getIcon(data, -1, -1, true);
}
if (rolloverIcon != null)
{
ComponentFactory.registerIcon(rolloverIcon);
addRolloverListener();
}
}
public void setRolloverIcon(ImageIcon icon)
{
ComponentFactory.deregisterIcon(rolloverIcon);
if (mediaOption != 1 && icon != null)
{
rolloverIcon = new MyImageIcon(application, this, icon, mediaOption);
}
else
{
rolloverIcon = icon;
}
if (rolloverIcon != null) ComponentFactory.registerIcon(rolloverIcon);
addRolloverListener();
}
private void addRolloverListener()
{
if (rolloverMouseAdapter == null)
{
rolloverMouseAdapter = new MouseAdapter()
{
@Override
public void mouseEntered(MouseEvent e)
{
AbstractScriptLabel.super.setIcon(rolloverIcon);
}
@Override
public void mouseExited(MouseEvent e)
{
AbstractScriptLabel.super.setIcon(normalIcon);
}
};
addMouseListener(rolloverMouseAdapter);
}
}
/**
* @see com.servoy.j2db.ui.ILabel#setRolloverIcon(int)
*/
public void setRolloverIcon(int rollOverMediaId)
{
try
{
setRolloverIcon(ComponentFactory.loadIcon(application.getFlattenedSolution(), new Integer(rollOverMediaId)));
}
catch (Exception ex)
{
Debug.error(ex);
}
}
@Override
public String toString()
{
return scriptable.toString();
}
/**
* @return
*/
public int getRotation()
{
return rotation;
}
/**
* @param i
*/
public void setRotation(int i)
{
rotation = i;
}
/**
* @return Returns the mediaOption.
*/
public int getMediaOption()
{
return mediaOption;
}
/**
* @param mediaOption The mediaOption to set.
*/
public void setMediaOption(int mediaOption)
{
this.mediaOption = mediaOption;
}
public void addScriptExecuter(IScriptExecuter el)
{
eventExecutor.setScriptExecuter(el);
}
public boolean hasActionCommand()
{
return eventExecutor.hasActionCmd();
}
private Timer clickTimer;
/**
* @see com.servoy.j2db.ui.ILabel#setActionCommand(java.lang.String, Object[])
*/
public void setActionCommand(String id, Object[] args)
{
eventExecutor.setActionCmd(id, args);
if (id != null && actionMouseAdapter == null)
{
setFocusable(true);
setRequestFocusEnabled(true);
actionMouseAdapter = new MouseAdapter()
{
private boolean armed = false;
// simulates multiClickThreshhold of button
private long lastPressedTimestamp = 0;
private boolean shouldDiscardRelease = false;
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseAdapter#mouseEntered(java.awt.event.MouseEvent)
*/
@Override
public void mouseEntered(MouseEvent e)
{
armed = true;
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseAdapter#mouseExited(java.awt.event.MouseEvent)
*/
@Override
public void mouseExited(MouseEvent e)
{
armed = false;
}
/*
* @see java.awt.event.MouseAdapter#mousePressed(java.awt.event.MouseEvent)
*/
@Override
public void mousePressed(MouseEvent e)
{
if (SwingUtilities.isLeftMouseButton(e)) requestFocus();
armed = true;
if (doubleClickMouseAdapter != null)
{
long lastTime = lastPressedTimestamp;
long currentTime = lastPressedTimestamp = e.getWhen();
if (currentTime - lastTime < UIUtils.getClickInterval())
{
shouldDiscardRelease = true;
return;
}
}
}
@Override
public void mouseReleased(final MouseEvent e)
{
if (shouldDiscardRelease)
{
shouldDiscardRelease = false;
return;
}
if (SwingUtilities.isLeftMouseButton(e) && isEnabled() && armed)
{
if (doubleClickMouseAdapter != null)
{
clickTimer = new Timer(UIUtils.getClickInterval(), new ActionListener()
{
public void actionPerformed(ActionEvent ev)
{
eventExecutor.fireActionCommand(true, AbstractScriptLabel.this, e.getModifiers(), e.getPoint());
}
});
clickTimer.setRepeats(false); //after expiring once, stop the timer
clickTimer.start();
}
else
{
eventExecutor.fireActionCommand(true, AbstractScriptLabel.this, e.getModifiers(), e.getPoint());
}
}
}
};
addMouseListener(actionMouseAdapter);
}
}
public void setDoubleClickCommand(String id, Object[] args)
{
eventExecutor.setDoubleClickCmd(id, args);
if (id != null && doubleClickMouseAdapter == null)
{
doubleClickMouseAdapter = new MouseAdapter()
{
@Override
public void mouseReleased(MouseEvent e)
{
// Don't allow double click with other buttons except left button.
if ((e.getClickCount() == 2) && SwingUtilities.isLeftMouseButton(e) && isEnabled())
{
if (clickTimer != null) clickTimer.stop();
eventExecutor.fireDoubleclickCommand(true, AbstractScriptLabel.this, e.getModifiers(), e.getPoint());
}
}
};
addMouseListener(doubleClickMouseAdapter);
}
}
public void setRightClickCommand(String id, Object[] args)
{
eventExecutor.setRightClickCmd(id, args);
if (id != null && rightclickMouseAdapter == null)
{
rightclickMouseAdapter = new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent e)
{
if (e.isPopupTrigger()) handle(e);
}
@Override
public void mouseReleased(MouseEvent e)
{
if (e.isPopupTrigger()) handle(e);
}
private void handle(MouseEvent e)
{
if (isEnabled())
{
eventExecutor.fireRightclickCommand(true, AbstractScriptLabel.this, e.getModifiers(), e.getPoint());
}
}
};
addMouseListener(rightclickMouseAdapter);
}
}
public void setValidationEnabled(boolean b)
{
eventExecutor.setValidationEnabled(b);
}
public boolean isReadOnly()
{
return true;
}
/**
* @see com.servoy.j2db.ui.ILabel#setTextTransform(int)
*/
public void setTextTransform(int mode)
{
this.textTransformMode = mode;
}
/**
* @see javax.swing.JLabel#setText(java.lang.String)
*/
@Override
public void setText(String text)
{
if (text != null && text.length() > 0)
{
if (textTransformMode == ILabel.CAPITALIZE)
{
StringBuffer sb = new StringBuffer(text.length());
StringTokenizer st = new StringTokenizer(text);
while (st.hasMoreTokens())
{
String word = st.nextToken();
sb.append(Character.toUpperCase(word.charAt(0)));
sb.append(word.substring(1));
sb.append(' ');
}
text = sb.substring(0, sb.length() - 1);
}
else if (textTransformMode == ILabel.LOWERCASE)
{
text = text.toLowerCase();
}
else if (textTransformMode == ILabel.UPPERCASE)
{
text = text.toUpperCase();
}
}
super.setText(text);
}
public String getId()
{
return (String)getClientProperty("Id"); //$NON-NLS-1$
}
public IEventExecutor getEventExecutor()
{
return eventExecutor;
}
public int getFontSize()
{
return 0;
}
}