12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262 |
- /*
- @ITMillApache2LicenseForJavaFiles@
- */
-
- package com.itmill.toolkit.ui;
-
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.Locale;
- import java.util.Map;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
-
- import com.itmill.toolkit.Application;
- import com.itmill.toolkit.event.EventRouter;
- import com.itmill.toolkit.event.MethodEventSource;
- import com.itmill.toolkit.terminal.ErrorMessage;
- import com.itmill.toolkit.terminal.PaintException;
- import com.itmill.toolkit.terminal.PaintTarget;
- import com.itmill.toolkit.terminal.Resource;
- import com.itmill.toolkit.terminal.Terminal;
-
- /**
- * An abstract class that defines default implementation for the
- * {@link Component} interface. Basic UI components that are not derived from an
- * external component can inherit this class to easily qualify as a IT Mill
- * Toolkit component. Most components in the toolkit do just that.
- *
- * @author IT Mill Ltd.
- * @version
- * @VERSION@
- * @since 3.0
- */
- public abstract class AbstractComponent implements Component, MethodEventSource {
-
- /* Private members */
-
- /**
- * Style names.
- */
- private ArrayList styles;
-
- /**
- * Caption text.
- */
- private String caption;
-
- /**
- * Application specific data object. The component does not use or modify
- * this.
- */
- private Object applicationData;
-
- /**
- * Icon to be shown together with caption.
- */
- private Resource icon;
-
- /**
- * Is the component enabled (its normal usage is allowed).
- */
- private boolean enabled = true;
-
- /**
- * Is the component visible (it is rendered).
- */
- private boolean visible = true;
-
- /**
- * Is the component read-only ?
- */
- private boolean readOnly = false;
-
- /**
- * Description of the usage (XML).
- */
- private String description = null;
-
- /**
- * The container this component resides in.
- */
- private Component parent = null;
-
- /**
- * The EventRouter used for the event model.
- */
- private EventRouter eventRouter = null;
-
- /**
- * The internal error message of the component.
- */
- private ErrorMessage componentError = null;
-
- /**
- * Immediate mode: if true, all variable changes are required to be sent
- * from the terminal immediately.
- */
- private boolean immediate = false;
-
- /**
- * Locale of this component.
- */
- private Locale locale;
-
- /**
- * List of repaint request listeners or null if not listened at all.
- */
- private LinkedList repaintRequestListeners = null;
-
- /**
- * Are all the repaint listeners notified about recent changes ?
- */
- private boolean repaintRequestListenersNotified = false;
-
- private String testingId;
-
- /* Sizeable fields */
-
- private float width = SIZE_UNDEFINED;
- private float height = SIZE_UNDEFINED;
- private int widthUnit = UNITS_PIXELS;
- private int heightUnit = UNITS_PIXELS;
- private static final Pattern sizePattern = Pattern
- .compile("^(-?\\d+(\\.\\d+)?)(%|px|em|ex|in|cm|mm|pt|pc)?$");
-
- private ComponentErrorHandler errorHandler = null;
-
- /* Constructor */
-
- /**
- * Constructs a new Component.
- */
- public AbstractComponent() {
- }
-
- /* Get/Set component properties */
-
- /**
- * Gets the UIDL tag corresponding to the component.
- *
- * @return the component's UIDL tag as <code>String</code>
- */
- public abstract String getTag();
-
- public void setDebugId(String id) {
- testingId = id;
- }
-
- public String getDebugId() {
- return testingId;
- }
-
- /**
- * Gets style for component. Multiple styles are joined with spaces.
- *
- * @return the component's styleValue of property style.
- * @deprecated Use getStyleName() instead; renamed for consistency and to
- * indicate that "style" should not be used to switch client
- * side implementation, only to style the component.
- */
- public String getStyle() {
- return getStyleName();
- }
-
- /**
- * Sets and replaces all previous style names of the component. This method
- * will trigger a
- * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent
- * RepaintRequestEvent}.
- *
- * @param style
- * the new style of the component.
- * @deprecated Use setStyleName() instead; renamed for consistency and to
- * indicate that "style" should not be used to switch client
- * side implementation, only to style the component.
- */
- public void setStyle(String style) {
- setStyleName(style);
- }
-
- /*
- * Gets the component's style. Don't add a JavaDoc comment here, we use the
- * default documentation from implemented interface.
- */
- public String getStyleName() {
- String s = "";
- if (styles != null) {
- for (final Iterator it = styles.iterator(); it.hasNext();) {
- s += (String) it.next();
- if (it.hasNext()) {
- s += " ";
- }
- }
- }
- return s;
- }
-
- /*
- * Sets the component's style. Don't add a JavaDoc comment here, we use the
- * default documentation from implemented interface.
- */
- public void setStyleName(String style) {
- if (style == null || "".equals(style)) {
- styles = null;
- requestRepaint();
- return;
- }
- if (styles == null) {
- styles = new ArrayList();
- }
- styles.clear();
- styles.add(style);
- requestRepaint();
- }
-
- public void addStyleName(String style) {
- if (style == null || "".equals(style)) {
- return;
- }
- if (styles == null) {
- styles = new ArrayList();
- }
- if (!styles.contains(style)) {
- styles.add(style);
- requestRepaint();
- }
- }
-
- public void removeStyleName(String style) {
- styles.remove(style);
- requestRepaint();
- }
-
- /*
- * Get's the component's caption. Don't add a JavaDoc comment here, we use
- * the default documentation from implemented interface.
- */
- public String getCaption() {
- return caption;
- }
-
- /**
- * Sets the component's caption <code>String</code>. Caption is the visible
- * name of the component. This method will trigger a
- * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent
- * RepaintRequestEvent}.
- *
- * @param caption
- * the new caption <code>String</code> for the component.
- */
- public void setCaption(String caption) {
- this.caption = caption;
- requestRepaint();
- }
-
- /*
- * Don't add a JavaDoc comment here, we use the default documentation from
- * implemented interface.
- */
- public Locale getLocale() {
- if (locale != null) {
- return locale;
- }
- if (parent != null) {
- return parent.getLocale();
- }
- final Application app = getApplication();
- if (app != null) {
- return app.getLocale();
- }
- return null;
- }
-
- /**
- * Sets the locale of this component.
- *
- * @param locale
- * the locale to become this component's locale.
- */
- public void setLocale(Locale locale) {
- this.locale = locale;
- }
-
- /*
- * Gets the component's icon resource. Don't add a JavaDoc comment here, we
- * use the default documentation from implemented interface.
- */
- public Resource getIcon() {
- return icon;
- }
-
- /**
- * Sets the component's icon. This method will trigger a
- * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent
- * RepaintRequestEvent}.
- *
- * @param icon
- * the icon to be shown with the component's caption.
- */
- public void setIcon(Resource icon) {
- this.icon = icon;
- requestRepaint();
- }
-
- /*
- * Tests if the component is enabled or not. Don't add a JavaDoc comment
- * here, we use the default documentation from implemented interface.
- */
- public boolean isEnabled() {
- return enabled && (parent == null || parent.isEnabled()) && isVisible();
- }
-
- /*
- * Enables or disables the component. Don't add a JavaDoc comment here, we
- * use the default documentation from implemented interface.
- */
- public void setEnabled(boolean enabled) {
- if (this.enabled != enabled) {
- boolean wasEnabled = isEnabled();
- this.enabled = enabled;
- // don't repaint if ancestor is disabled
- if (wasEnabled != isEnabled()) {
- requestRepaint();
- }
- }
- }
-
- /*
- * Tests if the component is in the immediate mode. Don't add a JavaDoc
- * comment here, we use the default documentation from implemented
- * interface.
- */
- public boolean isImmediate() {
- return immediate;
- }
-
- /**
- * Sets the component's immediate mode to the specified status. This method
- * will trigger a
- * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent
- * RepaintRequestEvent}.
- *
- * @param immediate
- * the boolean value specifying if the component should be in the
- * immediate mode after the call.
- * @see Component#isImmediate()
- */
- public void setImmediate(boolean immediate) {
- this.immediate = immediate;
- requestRepaint();
- }
-
- /*
- * Tests if the component is visible. Don't add a JavaDoc comment here, we
- * use the default documentation from implemented interface.
- */
- public boolean isVisible() {
- return visible;
- }
-
- /*
- * Sets the components visibility. Don't add a JavaDoc comment here, we use
- * the default documentation from implemented interface.
- */
- public void setVisible(boolean visible) {
-
- if (this.visible != visible) {
- this.visible = visible;
- // Instead of requesting repaint normally we
- // fire the event directly to assure that the
- // event goes through event in the component might
- // now be invisible
- fireRequestRepaintEvent(null);
- }
- }
-
- /**
- * <p>
- * Gets the component's description. The description can be used to briefly
- * describe the state of the component to the user. The description string
- * may contain certain XML tags:
- * </p>
- *
- * <p>
- * <table border=1>
- * <tr>
- * <td width=120><b>Tag</b></td>
- * <td width=120><b>Description</b></td>
- * <td width=120><b>Example</b></td>
- * </tr>
- * <tr>
- * <td><b></td>
- * <td>bold</td>
- * <td><b>bold text</b></td>
- * </tr>
- * <tr>
- * <td><i></td>
- * <td>italic</td>
- * <td><i>italic text</i></td>
- * </tr>
- * <tr>
- * <td><u></td>
- * <td>underlined</td>
- * <td><u>underlined text</u></td>
- * </tr>
- * <tr>
- * <td><br></td>
- * <td>linebreak</td>
- * <td>N/A</td>
- * </tr>
- * <tr>
- * <td><ul><br>
- * <li>item1<br>
- * <li>item1<br>
- * </ul></td>
- * <td>item list</td>
- * <td>
- * <ul>
- * <li>item1
- * <li>item2
- * </ul>
- * </td>
- * </tr>
- * </table>
- * </p>
- *
- * <p>
- * These tags may be nested.
- * </p>
- *
- * @return component's description <code>String</code>
- */
- public String getDescription() {
- return description;
- }
-
- /**
- * Sets the component's description. See {@link #getDescription()} for more
- * information on what the description is. This method will trigger a
- * {@link com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent
- * RepaintRequestEvent}.
- *
- * @param description
- * the new description string for the component.
- */
- public void setDescription(String description) {
- this.description = description;
- requestRepaint();
- }
-
- /*
- * Gets the component's parent component. Don't add a JavaDoc comment here,
- * we use the default documentation from implemented interface.
- */
- public Component getParent() {
- return parent;
- }
-
- /*
- * Sets the parent component. Don't add a JavaDoc comment here, we use the
- * default documentation from implemented interface.
- */
- public void setParent(Component parent) {
-
- // If the parent is not changed, don't do anything
- if (parent == this.parent) {
- return;
- }
-
- if (parent != null && this.parent != null) {
- throw new IllegalStateException("Component already has a parent.");
- }
-
- // Send detach event if the component have been connected to a window
- if (getApplication() != null) {
- detach();
- }
-
- // Connect to new parent
- this.parent = parent;
-
- // Send attach event if connected to a window
- if (getApplication() != null) {
- attach();
- }
- }
-
- /**
- * Gets the error message for this component.
- *
- * @return ErrorMessage containing the description of the error state of the
- * component or null, if the component contains no errors. Extending
- * classes should override this method if they support other error
- * message types such as validation errors or buffering errors. The
- * returned error message contains information about all the errors.
- */
- public ErrorMessage getErrorMessage() {
- return componentError;
- }
-
- /**
- * Gets the component's error message.
- *
- * @link Terminal.ErrorMessage#ErrorMessage(String, int)
- *
- * @return the component's error message.
- */
- public ErrorMessage getComponentError() {
- return componentError;
- }
-
- /**
- * Sets the component's error message. The message may contain certain XML
- * tags, for more information see
- *
- * @link Component.ErrorMessage#ErrorMessage(String, int)
- *
- * @param componentError
- * the new <code>ErrorMessage</code> of the component.
- */
- public void setComponentError(ErrorMessage componentError) {
- this.componentError = componentError;
- fireComponentErrorEvent();
- requestRepaint();
- }
-
- /*
- * Tests if the component is in read-only mode. Don't add a JavaDoc comment
- * here, we use the default documentation from implemented interface.
- */
- public boolean isReadOnly() {
- return readOnly;
- }
-
- /*
- * Sets the component's read-only mode. Don't add a JavaDoc comment here, we
- * use the default documentation from implemented interface.
- */
- public void setReadOnly(boolean readOnly) {
- this.readOnly = readOnly;
- requestRepaint();
- }
-
- /*
- * Gets the parent window of the component. Don't add a JavaDoc comment
- * here, we use the default documentation from implemented interface.
- */
- public Window getWindow() {
- if (parent == null) {
- return null;
- } else {
- return parent.getWindow();
- }
- }
-
- /*
- * Notify the component that it's attached to a window. Don't add a JavaDoc
- * comment here, we use the default documentation from implemented
- * interface.
- */
- public void attach() {
- requestRepaint();
- }
-
- /*
- * Detach the component from application. Don't add a JavaDoc comment here,
- * we use the default documentation from implemented interface.
- */
- public void detach() {
- }
-
- /*
- * Gets the parent application of the component. Don't add a JavaDoc comment
- * here, we use the default documentation from implemented interface.
- */
- public Application getApplication() {
- if (parent == null) {
- return null;
- } else {
- return parent.getApplication();
- }
- }
-
- /* Component painting */
-
- /* Documented in super interface */
- public void requestRepaintRequests() {
- repaintRequestListenersNotified = false;
- }
-
- /*
- * Paints the component into a UIDL stream. Don't add a JavaDoc comment
- * here, we use the default documentation from implemented interface.
- */
- public final void paint(PaintTarget target) throws PaintException {
- if (!target.startTag(this, getTag()) || repaintRequestListenersNotified) {
-
- // Paint the contents of the component
-
- // Only paint content of visible components.
- if (isVisible()) {
-
- if (getHeight() >= 0) {
- target.addAttribute("height", "" + getCSSHeight());
- }
- if (getWidth() >= 0) {
- target.addAttribute("width", "" + getCSSWidth());
- }
-
- if (styles != null && styles.size() > 0) {
- target.addAttribute("style", getStyle());
- }
- if (isReadOnly()) {
- target.addAttribute("readonly", true);
- }
-
- if (isImmediate()) {
- target.addAttribute("immediate", true);
- }
- if (!isEnabled()) {
- target.addAttribute("disabled", true);
- }
- if (getCaption() != null) {
- target.addAttribute("caption", getCaption());
- }
- if (getIcon() != null) {
- target.addAttribute("icon", getIcon());
- }
-
- if (getDescription() != null && getDescription().length() > 0) {
- target.addAttribute("description", getDescription());
- }
-
- paintContent(target);
-
- final ErrorMessage error = getErrorMessage();
- if (error != null) {
- error.paint(target);
- }
- } else {
- target.addAttribute("invisible", true);
- }
- } else {
-
- // Contents have not changed, only cached presentation can be used
- target.addAttribute("cached", true);
- }
- target.endTag(getTag());
-
- repaintRequestListenersNotified = false;
- }
-
- /**
- * Build CSS compatible string representation of height.
- *
- * @return CSS height
- */
- private String getCSSHeight() {
- if (getHeightUnits() == UNITS_PIXELS) {
- return ((int) getHeight()) + UNIT_SYMBOLS[getHeightUnits()];
- } else {
- return getHeight() + UNIT_SYMBOLS[getHeightUnits()];
- }
- }
-
- /**
- * Build CSS compatible string representation of width.
- *
- * @return CSS width
- */
- private String getCSSWidth() {
- if (getWidthUnits() == UNITS_PIXELS) {
- return ((int) getWidth()) + UNIT_SYMBOLS[getWidthUnits()];
- } else {
- return getWidth() + UNIT_SYMBOLS[getWidthUnits()];
- }
- }
-
- /**
- * Paints any needed component-specific things to the given UIDL stream. The
- * more general {@link #paint(PaintTarget)} method handles all general
- * attributes common to all components, and it calls this method to paint
- * any component-specific attributes to the UIDL stream.
- *
- * @param target
- * the target UIDL stream where the component should paint itself
- * to
- * @throws PaintException
- * if the paint operation failed.
- */
- public void paintContent(PaintTarget target) throws PaintException {
-
- }
-
- /* Documentation copied from interface */
- public void requestRepaint() {
-
- // The effect of the repaint request is identical to case where a
- // child requests repaint
- childRequestedRepaint(null);
- }
-
- /* Documentation copied from interface */
- public void childRequestedRepaint(Collection alreadyNotified) {
- // Invisible components do not need repaints
- if (!isVisible()) {
- return;
- }
-
- fireRequestRepaintEvent(alreadyNotified);
- }
-
- /**
- * Fires the repaint request event.
- *
- * @param alreadyNotified
- */
- private void fireRequestRepaintEvent(Collection alreadyNotified) {
- // Notify listeners only once
- if (!repaintRequestListenersNotified) {
- // Notify the listeners
- if (repaintRequestListeners != null
- && !repaintRequestListeners.isEmpty()) {
- final Object[] listeners = repaintRequestListeners.toArray();
- final RepaintRequestEvent event = new RepaintRequestEvent(this);
- for (int i = 0; i < listeners.length; i++) {
- if (alreadyNotified == null) {
- alreadyNotified = new LinkedList();
- }
- if (!alreadyNotified.contains(listeners[i])) {
- ((RepaintRequestListener) listeners[i])
- .repaintRequested(event);
- alreadyNotified.add(listeners[i]);
- repaintRequestListenersNotified = true;
- }
- }
- }
-
- // Notify the parent
- final Component parent = getParent();
- if (parent != null) {
- parent.childRequestedRepaint(alreadyNotified);
- }
- }
- }
-
- /* Documentation copied from interface */
- public void addListener(RepaintRequestListener listener) {
- if (repaintRequestListeners == null) {
- repaintRequestListeners = new LinkedList();
- }
- if (!repaintRequestListeners.contains(listener)) {
- repaintRequestListeners.add(listener);
- }
- }
-
- /* Documentation copied from interface */
- public void removeListener(RepaintRequestListener listener) {
- if (repaintRequestListeners != null) {
- repaintRequestListeners.remove(listener);
- if (repaintRequestListeners.isEmpty()) {
- repaintRequestListeners = null;
- }
- }
- }
-
- /* Component variable changes */
-
- /*
- * Invoked when the value of a variable has changed. Don't add a JavaDoc
- * comment here, we use the default documentation from implemented
- * interface.
- */
- public void changeVariables(Object source, Map variables) {
- }
-
- /* General event framework */
-
- private static final Method COMPONENT_EVENT_METHOD;
-
- static {
- try {
- COMPONENT_EVENT_METHOD = Component.Listener.class
- .getDeclaredMethod("componentEvent",
- new Class[] { Component.Event.class });
- } catch (final java.lang.NoSuchMethodException e) {
- // This should never happen
- throw new java.lang.RuntimeException(
- "Internal error finding methods in AbstractComponent");
- }
- }
-
- /**
- * <p>
- * Registers a new listener with the specified activation method to listen
- * events generated by this component. If the activation method does not
- * have any arguments the event object will not be passed to it when it's
- * called.
- * </p>
- *
- * <p>
- * For more information on the inheritable event mechanism see the
- * {@link com.itmill.toolkit.event com.itmill.toolkit.event package
- * documentation}.
- * </p>
- *
- * @param eventType
- * the type of the listened event. Events of this type or its
- * subclasses activate the listener.
- * @param object
- * the object instance who owns the activation method.
- * @param method
- * the activation method.
- */
- public void addListener(Class eventType, Object object, Method method) {
- if (eventRouter == null) {
- eventRouter = new EventRouter();
- }
- eventRouter.addListener(eventType, object, method);
- }
-
- /**
- * <p>
- * Convenience method for registering a new listener with the specified
- * activation method to listen events generated by this component. If the
- * activation method does not have any arguments the event object will not
- * be passed to it when it's called.
- * </p>
- *
- * <p>
- * This version of <code>addListener</code> gets the name of the activation
- * method as a parameter. The actual method is reflected from
- * <code>object</code>, and unless exactly one match is found,
- * <code>java.lang.IllegalArgumentException</code> is thrown.
- * </p>
- *
- * <p>
- * For more information on the inheritable event mechanism see the
- * {@link com.itmill.toolkit.event com.itmill.toolkit.event package
- * documentation}.
- * </p>
- *
- * <p>
- * Note: Using this method is discouraged because it cannot be checked
- * during compilation. Use {@link #addListener(Class, Object, Method)} or
- * {@link #addListener(com.itmill.toolkit.ui.Component.Listener)} instead.
- * </p>
- *
- * @param eventType
- * the type of the listened event. Events of this type or its
- * subclasses activate the listener.
- * @param object
- * the object instance who owns the activation method.
- * @param methodName
- * the name of the activation method.
- */
- public void addListener(Class eventType, Object object, String methodName) {
- if (eventRouter == null) {
- eventRouter = new EventRouter();
- }
- eventRouter.addListener(eventType, object, methodName);
- }
-
- /**
- * Removes all registered listeners matching the given parameters. Since
- * this method receives the event type and the listener object as
- * parameters, it will unregister all <code>object</code>'s methods that are
- * registered to listen to events of type <code>eventType</code> generated
- * by this component.
- *
- * <p>
- * For more information on the inheritable event mechanism see the
- * {@link com.itmill.toolkit.event com.itmill.toolkit.event package
- * documentation}.
- * </p>
- *
- * @param eventType
- * the exact event type the <code>object</code> listens to.
- * @param target
- * the target object that has registered to listen to events of
- * type <code>eventType</code> with one or more methods.
- */
- public void removeListener(Class eventType, Object target) {
- if (eventRouter != null) {
- eventRouter.removeListener(eventType, target);
- }
- }
-
- /**
- * Removes one registered listener method. The given method owned by the
- * given object will no longer be called when the specified events are
- * generated by this component.
- *
- * <p>
- * For more information on the inheritable event mechanism see the
- * {@link com.itmill.toolkit.event com.itmill.toolkit.event package
- * documentation}.
- * </p>
- *
- * @param eventType
- * the exact event type the <code>object</code> listens to.
- * @param target
- * target object that has registered to listen to events of type
- * <code>eventType</code> with one or more methods.
- * @param method
- * the method owned by <code>target</code> that's registered to
- * listen to events of type <code>eventType</code>.
- */
- public void removeListener(Class eventType, Object target, Method method) {
- if (eventRouter != null) {
- eventRouter.removeListener(eventType, target, method);
- }
- }
-
- /**
- * <p>
- * Removes one registered listener method. The given method owned by the
- * given object will no longer be called when the specified events are
- * generated by this component.
- * </p>
- *
- * <p>
- * This version of <code>removeListener</code> gets the name of the
- * activation method as a parameter. The actual method is reflected from
- * <code>target</code>, and unless exactly one match is found,
- * <code>java.lang.IllegalArgumentException</code> is thrown.
- * </p>
- *
- * <p>
- * For more information on the inheritable event mechanism see the
- * {@link com.itmill.toolkit.event com.itmill.toolkit.event package
- * documentation}.
- * </p>
- *
- * @param eventType
- * the exact event type the <code>object</code> listens to.
- * @param target
- * the target object that has registered to listen to events of
- * type <code>eventType</code> with one or more methods.
- * @param methodName
- * the name of the method owned by <code>target</code> that's
- * registered to listen to events of type <code>eventType</code>.
- */
- public void removeListener(Class eventType, Object target, String methodName) {
- if (eventRouter != null) {
- eventRouter.removeListener(eventType, target, methodName);
- }
- }
-
- /**
- * Sends the event to all listeners.
- *
- * @param event
- * the Event to be sent to all listeners.
- */
- protected void fireEvent(Component.Event event) {
- if (eventRouter != null) {
- eventRouter.fireEvent(event);
- }
-
- }
-
- /* Component event framework */
-
- /*
- * Registers a new listener to listen events generated by this component.
- * Don't add a JavaDoc comment here, we use the default documentation from
- * implemented interface.
- */
- public void addListener(Component.Listener listener) {
- if (eventRouter == null) {
- eventRouter = new EventRouter();
- }
-
- eventRouter.addListener(Component.Event.class, listener,
- COMPONENT_EVENT_METHOD);
- }
-
- /*
- * Removes a previously registered listener from this component. Don't add a
- * JavaDoc comment here, we use the default documentation from implemented
- * interface.
- */
- public void removeListener(Component.Listener listener) {
- if (eventRouter != null) {
- eventRouter.removeListener(Component.Event.class, listener,
- COMPONENT_EVENT_METHOD);
- }
- }
-
- /**
- * Emits the component event. It is transmitted to all registered listeners
- * interested in such events.
- */
- protected void fireComponentEvent() {
- fireEvent(new Component.Event(this));
- }
-
- /**
- * Emits the component error event. It is transmitted to all registered
- * listeners interested in such events.
- */
- protected void fireComponentErrorEvent() {
- fireEvent(new Component.ErrorEvent(getComponentError(), this));
- }
-
- /**
- * Sets the data object, that can be used for any application specific data.
- * The component does not use or modify this data.
- *
- * @param data
- * the Application specific data.
- * @since 3.1
- */
- public void setData(Object data) {
- applicationData = data;
- }
-
- /**
- * Gets the application specific data. See {@link #setData(Object)}.
- *
- * @return the Application specific data set with setData function.
- * @since 3.1
- */
- public Object getData() {
- return applicationData;
- }
-
- /* Sizeable and other size related methods */
-
- public float getHeight() {
- return height;
- }
-
- public int getHeightUnits() {
- return heightUnit;
- }
-
- public float getWidth() {
- return width;
- }
-
- public int getWidthUnits() {
- return widthUnit;
- }
-
- public void setHeight(float height) {
- this.height = height;
- requestRepaint();
- }
-
- /**
- * Sets the height property units.
- *
- * @param units
- * the units used in height property.
- * @deprecated Consider setting height and unit simultaneously using
- * {@link #setHeight(String)} or {@link #setHeight(float, int)},
- * which is less error-prone.
- */
- public void setHeightUnits(int unit) {
- heightUnit = unit;
- requestRepaint();
- }
-
- /**
- * Sets the height of the object. Negative number implies unspecified size
- * (terminal is free to set the size).
- *
- * @param height
- * the height of the object in units specified by heightUnits
- * property.
- * @deprecated Consider using {@link #setHeight(String)} or
- * {@link #setHeight(float, int)} instead. This method works,
- * but is error-prone since the unit must be set separately (and
- * components might have different default unit).
- */
- public void setHeight(float height, int unit) {
- this.height = height;
- heightUnit = unit;
- requestRepaint();
- }
-
- public void setSizeFull() {
- height = 100;
- width = 100;
- heightUnit = UNITS_PERCENTAGE;
- widthUnit = UNITS_PERCENTAGE;
- requestRepaint();
- }
-
- public void setSizeUndefined() {
- height = -1;
- width = -1;
- heightUnit = UNITS_PIXELS;
- widthUnit = UNITS_PIXELS;
- requestRepaint();
- }
-
- /**
- * Sets the width of the object. Negative number implies unspecified size
- * (terminal is free to set the size).
- *
- * @param width
- * the width of the object in units specified by widthUnits
- * property.
- * @deprecated Consider using {@link #setWidth(String)} instead. This method
- * works, but is error-prone since the unit must be set
- * separately (and components might have different default
- * unit).
- */
- public void setWidth(float width) {
- this.width = width;
- requestRepaint();
- }
-
- /**
- * Sets the width property units.
- *
- * @param units
- * the units used in width property.
- * @deprecated Consider setting width and unit simultaneously using
- * {@link #setWidth(String)} or {@link #setWidth(float, int)},
- * which is less error-prone.
- */
- public void setWidthUnits(int unit) {
- widthUnit = unit;
- requestRepaint();
- }
-
- public void setWidth(float width, int unit) {
- this.width = width;
- widthUnit = unit;
- requestRepaint();
- }
-
- public void setWidth(String width) {
- float[] p = parseStringSize(width);
- this.width = p[0];
- widthUnit = (int) p[1];
- requestRepaint();
- }
-
- public void setHeight(String height) {
- float[] p = parseStringSize(height);
- this.height = p[0];
- heightUnit = (int) p[1];
- requestRepaint();
- }
-
- /*
- * Returns array with size in index 0 unit in index 1. Null or empty string
- * will produce {-1,UNITS_PIXELS}
- */
- private static float[] parseStringSize(String s) {
- float[] values = { -1, UNITS_PIXELS };
- if (s == null) {
- return values;
- }
- s = s.trim();
- if ("".equals(s)) {
- return values;
- }
-
- Matcher matcher = sizePattern.matcher(s);
- if (matcher.find()) {
- values[0] = Float.parseFloat(matcher.group(1));
- if (values[0] < 0) {
- values[0] = -1;
- } else {
- String unit = matcher.group(3);
- if (unit == null) {
- values[1] = UNITS_PIXELS;
- } else if (unit.equals("px")) {
- values[1] = UNITS_PIXELS;
- } else if (unit.equals("%")) {
- values[1] = UNITS_PERCENTAGE;
- } else if (unit.equals("em")) {
- values[1] = UNITS_EM;
- } else if (unit.equals("ex")) {
- values[1] = UNITS_EX;
- } else if (unit.equals("in")) {
- values[1] = UNITS_INCH;
- } else if (unit.equals("cm")) {
- values[1] = UNITS_CM;
- } else if (unit.equals("mm")) {
- values[1] = UNITS_MM;
- } else if (unit.equals("pt")) {
- values[1] = UNITS_POINTS;
- } else if (unit.equals("pc")) {
- values[1] = UNITS_PICAS;
- }
- }
- } else {
- throw new IllegalArgumentException("Invalid size argument: \"" + s
- + "\" (should match " + sizePattern.pattern() + ")");
- }
- return values;
- }
-
- public interface ComponentErrorEvent extends Terminal.ErrorEvent {
- }
-
- public interface ComponentErrorHandler {
- /**
- * Handle the component error
- *
- * @param event
- * @return True if the error has been handled False, otherwise
- */
- public boolean handleComponentError(ComponentErrorEvent event);
- }
-
- /**
- * Gets the error handler for the component.
- *
- * The error handler is dispatched whenever there is an error processing the
- * data coming from the client.
- *
- * @return
- */
- public ComponentErrorHandler getErrorHandler() {
- return errorHandler;
- }
-
- /**
- * Sets the error handler for the component.
- *
- * The error handler is dispatched whenever there is an error processing the
- * data coming from the client.
- *
- * If the error handler is not set, the application error handler is used to
- * handle the exception.
- *
- * @param errorHandler
- * AbstractField specific error handler
- */
- public void setErrorHandler(ComponentErrorHandler errorHandler) {
- this.errorHandler = errorHandler;
- }
-
- /**
- * Handle the component error event.
- *
- * @param error
- * Error event to handle
- * @return True if the error has been handled False, otherwise. If the error
- * haven't been handled by this component, it will be handled in the
- * application error handler.
- */
- public boolean handleError(ComponentErrorEvent error) {
- if (errorHandler != null) {
- return errorHandler.handleComponentError(error);
- }
- return false;
-
- }
-
- }
|