001 
002 /*
003  *  JScripter Standard 1.0 - To Script In Java
004  *  Copyright (C) 2008-2011  J.J.Liu<jianjunliu@126.com> <http://www.jscripter.org>
005  *  
006  *  This program is free software: you can redistribute it and/or modify
007  *  it under the terms of the GNU Affero General Public License as published by
008  *  the Free Software Foundation, either version 3 of the License, or
009  *  (at your option) any later version.
010  *  
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU Affero General Public License for more details.
015  *  
016  *  You should have received a copy of the GNU Affero General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
018  */
019 
020 package jsx.ui.ctrl;
021 
022 import js.Id;
023 import js.Js;
024 import js.ObjectLike;
025 import jsx.Timeout;
026 import jsx.core.ObjectLikes;
027 import jsx.ui.Component;
028 import jsx.ui.event.DblClick;
029 import jsx.ui.event.MouseUp;
030 import jsx.ui.event.OnMouseUp;
031 
032 /**
033  * <p>A base class for double-clickable widgets.</p>
034  * 
035  * @author <a href="mailto:jianjunliu@126.com">J.J.Liu (Jianjun Liu)</a> at <a href="http://www.jscripter.org" target="_blank">http://www.jscripter.org</a>
036  */
037 public class DblClickable extends Clickable implements OnMouseUp
038 {
039     /**
040      * <p>Constructs a double-clickable widget.</p>
041      * @param html The HTML of the control widget.
042      * @since 1.0
043      */
044     public DblClickable(String html) {
045         this(new Component(html));
046     }
047 
048     private final static Id<DblClickable> DBLCLICKABLE = new Id<DblClickable>();
049 
050     /**
051      * <p>Gets the {@link DblClickable} widget associated with a component.</p>
052      * <p>If the specified component does not have an associated {@link DblClickable} widget,
053      * this method will creates one based on that component and associate them.</p>
054      * @param e A component that may have a {@link DblClickable} widget based on it.
055      * @return The {@link DblClickable} widget associated with <tt>e</tt>.
056      * @since 1.0
057      */
058     public static DblClickable get(Component e) {
059         DblClickable d = ini(Clickable.get(e)).var(DBLCLICKABLE);
060         return Js.be(d) ? d : new DblClickable(e);
061     }
062 
063     /**
064      * <p>Typically Constructs a double-clickable widget.</p>
065      * <p>This constructor makes the widget listen to event {@link MouseUp} and sets up a {@link Timeout}
066      * timer to expire a double-click.</p>
067      * @param e The underlying component for the widget.
068      * @since 1.0
069      */
070     protected DblClickable(Component e) {
071         super(e);
072         if (Js.not(ini(Clickable.get(e)).var(DBLCLICKABLE))) {
073             ini(Clickable.get(e)).var(DBLCLICKABLE, this);
074         }
075         timer = new Timeout() {
076             @Override
077             public void run() {
078                 ObjectLikes.delete(ini(DblClickable.this), MOUSEUP);
079             }
080         };
081         addListener(MouseUp.class, this);
082     }
083 
084     private final Timeout timer;
085 
086     private final static Id<Boolean> MOUSEUP = new Id<Boolean>();
087 
088     /**
089      * <p>Performs an action on the rendering event.</p>
090      * <p>This method invokes the overridden method of super class and makes the widget 
091      * fires {@link MouseUp} event from itself on a browser "mouseup" event over the 
092      * underlying HTML element.</p>
093      * @since 1.0
094      */
095     @Override
096     protected void init() {
097         super.init();
098         attachEvent("mouseup", new MouseUp(unwrap()));
099     }
100 
101     /**
102      * <p>Performs an action on the dispatched event.</p>
103      * <p>This method fires {@link DblClick} event from itself on double-clicks.</p>
104      * @param evt The event dispatched to this listener.
105      * @since 1.0
106      */
107     public void onEvent(MouseUp evt) {
108         ObjectLike ini = ini(this);
109         if (ini.var(MOUSEUP)) {
110             timer.clear();
111             ObjectLikes.delete(ini, MOUSEUP);
112             exec(new DblClick(unwrap()));
113         } else {
114             ini.var(MOUSEUP, true);
115             timer.set(1000);
116         }
117     }
118 }