View Javadoc

1   /*--------------------------------------------------------------------------
2    *  Copyright 2008 utgenome.org
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *--------------------------------------------------------------------------*/
16  //--------------------------------------
17  // utgb-widget Project
18  //
19  // Switch.java
20  // Since: Apr 24, 2008
21  //
22  // $URL$ 
23  // $Author$
24  //--------------------------------------
25  package org.utgenome.gwt.widget.client;
26  
27  import com.google.gwt.user.client.DOM;
28  import com.google.gwt.user.client.Element;
29  import com.google.gwt.user.client.Event;
30  import com.google.gwt.user.client.ui.FocusPanel;
31  import com.google.gwt.user.client.ui.Widget;
32  
33  /**
34   * Flip/Flop type widget
35   * 
36   * @author leo
37   * 
38   */
39  public class Switch extends FocusPanel {
40  
41  	private Element currentSwitchFace = null;
42  
43  	private Widget onWidget;
44  	private Widget offWidget;
45  	private Widget onHoveringWidget;
46  	private Widget offHoveringWidget;
47  
48  	private boolean isOn = false;
49  
50  	private boolean isFocusing = false;
51  	private boolean isCapturing = false;
52  	private boolean isHovering = false;
53  
54  	public Switch(Widget on, Widget onHovering, Widget off, Widget offHovering) {
55  		this.onWidget = on;
56  		this.offWidget = off;
57  		this.onHoveringWidget = onHovering;
58  		this.offHoveringWidget = offHovering;
59  
60  		Style.cursor(this, Style.CURSOR_POINTER);
61  		updateSwitchFace(offWidget.getElement());
62  	}
63  
64  	public Switch(Icon on, Icon off) {
65  		this(on.getIconImage(), on.getMouseOverIconImage(), off.getIconImage(), off.getMouseOverIconImage());
66  	}
67  
68  	public void setSwitch(boolean on) {
69  		isOn = on;
70  		updateSwitchFace(isOn ? onWidget.getElement() : offWidget.getElement());
71  	}
72  
73  	private void setHovering(boolean hovering) {
74  		this.isHovering = hovering;
75  		if (isOn)
76  			updateSwitchFace(isHovering ? onHoveringWidget.getElement() : onWidget.getElement());
77  		else
78  			updateSwitchFace(isHovering ? offHoveringWidget.getElement() : offWidget.getElement());
79  	}
80  
81  	protected void updateSwitchFace(Element newFace) {
82  		if (currentSwitchFace != newFace) {
83  			if (currentSwitchFace != null)
84  				DOM.removeChild(getElement(), currentSwitchFace);
85  
86  			currentSwitchFace = newFace;
87  			DOM.appendChild(getElement(), currentSwitchFace);
88  		}
89  	}
90  
91  	/**
92  	 * Called when the user finishes clicking on this button. The default behavior is to fire the click event to
93  	 * listeners. Subclasses that override {@link #onClickStart()} should override this method to restore the normal
94  	 * widget display.
95  	 */
96  	protected void onClick() {
97  
98  	}
99  
100 	/**
101 	 * Called when the user aborts a click in progress; for example, by dragging the mouse outside of the button before
102 	 * releasing the mouse button. Subclasses that override {@link #onClickStart()} should override this method to
103 	 * restore the normal widget display.
104 	 */
105 	protected void onClickCancel() {
106 	}
107 
108 	/**
109 	 * Called when the user begins to click on this button. Subclasses may override this method to display the start of
110 	 * the click visually; such subclasses should also override {@link #onClick()} and {@link #onClickCancel()} to
111 	 * restore normal visual state. Each <code>onClickStart</code> will eventually be followed by either
112 	 * <code>onClick</code> or <code>onClickCancel</code>, depending on whether the click is completed.
113 	 */
114 	protected void onClickStart() {
115 	}
116 
117 	@Override
118 	public void onBrowserEvent(Event event) {
119 		// Should not act on button if disabled.
120 
121 		int type = DOM.eventGetType(event);
122 		switch (type) {
123 		case Event.ONMOUSEDOWN:
124 			isFocusing = true;
125 			onClickStart();
126 			DOM.setCapture(getElement());
127 			isCapturing = true;
128 			// Prevent dragging (on some browsers);
129 			DOM.eventPreventDefault(event);
130 			break;
131 		case Event.ONMOUSEUP:
132 			if (isCapturing) {
133 				isCapturing = false;
134 				DOM.releaseCapture(getElement());
135 				if (isHovering) {
136 					onClick();
137 				}
138 			}
139 			break;
140 		case Event.ONMOUSEMOVE:
141 			if (isCapturing) {
142 				// Prevent dragging (on other browsers);
143 				DOM.eventPreventDefault(event);
144 			}
145 			break;
146 		case Event.ONMOUSEOUT:
147 			Element to = DOM.eventGetToElement(event);
148 			if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event)) && (to == null || !DOM.isOrHasChild(getElement(), to))) {
149 				if (isCapturing) {
150 					onClickCancel();
151 				}
152 				setHovering(false);
153 			}
154 			break;
155 		case Event.ONMOUSEOVER:
156 			if (DOM.isOrHasChild(getElement(), DOM.eventGetTarget(event))) {
157 				setHovering(true);
158 				if (isCapturing) {
159 					onClickStart();
160 				}
161 			}
162 			break;
163 		case Event.ONCLICK:
164 			// we handle clicks ourselves
165 			return;
166 		case Event.ONBLUR:
167 			if (isFocusing) {
168 				isFocusing = false;
169 				onClickCancel();
170 			}
171 			break;
172 		case Event.ONLOSECAPTURE:
173 			if (isCapturing) {
174 				isCapturing = false;
175 				onClickCancel();
176 			}
177 			break;
178 		}
179 
180 		super.onBrowserEvent(event);
181 
182 		// Synthesize clicks based on keyboard events AFTER the normal key handling.
183 		char keyCode = (char) DOM.eventGetKeyCode(event);
184 		switch (type) {
185 		case Event.ONKEYDOWN:
186 			if (keyCode == ' ') {
187 				isFocusing = true;
188 				onClickStart();
189 			}
190 			break;
191 		case Event.ONKEYUP:
192 			if (isFocusing && keyCode == ' ') {
193 				isFocusing = false;
194 				onClick();
195 			}
196 			break;
197 		case Event.ONKEYPRESS:
198 			if (keyCode == '\n' || keyCode == '\r') {
199 				onClickStart();
200 				onClick();
201 			}
202 			break;
203 		}
204 	}
205 
206 }