001: /*
002: * Copyright (c) 2002-2008 Gargoyle Software Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * 1. Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: * 2. Redistributions in binary form must reproduce the above copyright notice,
010: * this list of conditions and the following disclaimer in the documentation
011: * and/or other materials provided with the distribution.
012: * 3. The end-user documentation included with the redistribution, if any, must
013: * include the following acknowledgment:
014: *
015: * "This product includes software developed by Gargoyle Software Inc.
016: * (http://www.GargoyleSoftware.com/)."
017: *
018: * Alternately, this acknowledgment may appear in the software itself, if
019: * and wherever such third-party acknowledgments normally appear.
020: * 4. The name "Gargoyle Software" must not be used to endorse or promote
021: * products derived from this software without prior written permission.
022: * For written permission, please contact info@GargoyleSoftware.com.
023: * 5. Products derived from this software may not be called "HtmlUnit", nor may
024: * "HtmlUnit" appear in their name, without prior written permission of
025: * Gargoyle Software Inc.
026: *
027: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
028: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
029: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
030: * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
031: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
032: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
033: * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
036: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: */
038: package com.gargoylesoftware.htmlunit.javascript.host;
039:
040: import org.mozilla.javascript.Context;
041:
042: import com.gargoylesoftware.htmlunit.html.DomNode;
043:
044: /**
045: * JavaScript object representing a Mouse Event.
046: * For general information on which properties and functions
047: * should be supported, see
048: * <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-MouseEvent">DOM Level 2 Events</a>.
049: *
050: * @version $Revision: 2132 $
051: * @author Marc Guillemot
052: * @author Ahmed Ashour
053: */
054: public class MouseEvent extends UIEvent {
055:
056: private static final long serialVersionUID = 1990705559211878370L;
057:
058: /** The click event type, triggered by "onclick" event handlers. */
059: public static final String TYPE_CLICK = "click";
060:
061: /** The dblclick event type, triggered by "ondblclick" event handlers. */
062: public static final String TYPE_DBL_CLICK = "dblclick";
063:
064: /** The mouse over event type, triggered by "onmouseover" event handlers. */
065: public static final String TYPE_MOUSE_OVER = "mouseover";
066:
067: /** The mouse move event type, triggered by "onmousemove" event handlers. */
068: public static final String TYPE_MOUSE_MOVE = "mousemove";
069:
070: /** The mouse out event type, triggered by "onmouseout" event handlers. */
071: public static final String TYPE_MOUSE_OUT = "mouseout";
072:
073: /** The mouse down event type, triggered by "onmousedown" event handlers. */
074: public static final String TYPE_MOUSE_DOWN = "mousedown";
075:
076: /** The mouse up event type, triggered by "onmouseup" event handlers. */
077: public static final String TYPE_MOUSE_UP = "mouseup";
078:
079: /** The context menu event type, triggered by "oncontextmenu" event handlers. */
080: public static final String TYPE_CONTEXT_MENU = "contextmenu";
081:
082: /** The code for left mouse button. */
083: public static final int BUTTON_LEFT = 0;
084:
085: /** The code for middle mouse button. */
086: public static final int BUTTON_MIDDLE = 1;
087:
088: /** The code for right mouse button. */
089: public static final int BUTTON_RIGHT = 2;
090:
091: /** The button code for IE (1: left button, 4: middle button, 2: right button). */
092: private static final int[] buttonCodeToIE = { 1, 4, 2 };
093:
094: /** The mouse event's horizontal and vertical coordinates. */
095: private int screenX_, screenY_;
096:
097: /** The button code according to W3C (0: left button, 1: middle button, 2: right button). */
098: private int button_;
099:
100: /** Whether or not the "meta" key was pressed during the firing of the event. */
101: private boolean metaKey_;
102:
103: /**
104: * Used to build the prototype.
105: */
106: public MouseEvent() {
107: screenX_ = 0;
108: screenY_ = 0;
109: setDetail(1);
110: }
111:
112: /**
113: * Creates a new event instance.
114: * @param domNode The DOM node that triggered the event.
115: * @param type The event type.
116: * @param shiftKey true if SHIFT is pressed
117: * @param ctrlKey true if CTRL is pressed
118: * @param altKey true if ALT is pressed
119: * @param button the button code, must be {@link #BUTTON_LEFT}, {@link #BUTTON_MIDDLE} or {@link #BUTTON_RIGHT}
120: */
121: public MouseEvent(final DomNode domNode, final String type,
122: final boolean shiftKey, final boolean ctrlKey,
123: final boolean altKey, final int button) {
124:
125: super (domNode, type, shiftKey, ctrlKey, altKey);
126:
127: if (button != BUTTON_LEFT && button != BUTTON_MIDDLE
128: && button != BUTTON_RIGHT) {
129: throw new IllegalArgumentException("Invalid button code: "
130: + button);
131: }
132: button_ = button;
133: metaKey_ = false;
134:
135: if (TYPE_DBL_CLICK.equals(type)) {
136: setDetail(2);
137: } else {
138: setDetail(1);
139: }
140:
141: // compute coordinates from the node
142: final HTMLElement target = (HTMLElement) jsxGet_target();
143: screenX_ = target.getPosX() + 10;
144: screenY_ = target.getPosY() + 10;
145: }
146:
147: /**
148: * {@inheritDoc}
149: */
150: public void copyPropertiesFrom(final Event event) {
151: super .copyPropertiesFrom(event);
152: if (event instanceof MouseEvent) {
153: final MouseEvent mouseEvent = (MouseEvent) event;
154: screenX_ = mouseEvent.screenX_;
155: screenY_ = mouseEvent.screenY_;
156: button_ = mouseEvent.button_;
157: metaKey_ = mouseEvent.metaKey_;
158: }
159: }
160:
161: /**
162: * The horizontal coordinate at which the event occurred relative to the DOM implementation's client area.
163: * @return the horizontal coordinate (currently the same as {@link #jsxGet_screenX()})
164: */
165: public int jsxGet_clientX() {
166: return screenX_;
167: }
168:
169: /**
170: * The horizontal coordinate at which the event occurred relative to the origin of the screen coordinate system.
171: * @return the horizontal coordinate.
172: */
173: public int jsxGet_screenX() {
174: return screenX_;
175: }
176:
177: /**
178: * Returns the horizontal coordinate of the event relative to whole document..
179: * @return the horizontal coordinate (currently the same as {@link #jsxGet_screenX()})
180: * @see <a href="http://developer.mozilla.org/en/docs/DOM:event.pageX">Mozilla doc</a>
181: */
182: public int jsxGet_pageX() {
183: return screenX_;
184: }
185:
186: /**
187: * The vertical coordinate at which the event occurred relative to the DOM implementation's client area.
188: * @return the horizontal coordinate (currently the same as {@link #jsxGet_screenY()})
189: */
190: public int jsxGet_clientY() {
191: return screenY_;
192: }
193:
194: /**
195: * The vertical coordinate at which the event occurred relative to the origin of the screen coordinate system.
196: * @return the vertical coordinate.
197: */
198: public int jsxGet_screenY() {
199: return screenY_;
200: }
201:
202: /**
203: * Returns the vertical coordinate of the event relative to the whole document.
204: * @return the horizontal coordinate (currently the same as {@link #jsxGet_screenY()})
205: * @see <a href="http://developer.mozilla.org/en/docs/DOM:event.pageY">Mozilla doc</a>
206: */
207: public int jsxGet_pageY() {
208: return screenY_;
209: }
210:
211: /**
212: * Gets the button code.
213: * @return the button code
214: */
215: public int jsxGet_button() {
216: if (getWindow().getWebWindow().getWebClient()
217: .getBrowserVersion().isIE()) {
218: //In IE7: oncontextmenu event.button is 0
219: if (jsxGet_type().equals(TYPE_CONTEXT_MENU)) {
220: return 0;
221: }
222: return buttonCodeToIE[button_];
223: }
224: return button_;
225: }
226:
227: /**
228: * Returns whether or not the "meta" key was pressed during the event firing.
229: * @return whether or not the "meta" key was pressed during the event firing
230: */
231: public boolean jsxGet_metaKey() {
232: return metaKey_;
233: }
234:
235: /**
236: * Special for FF (old stuff from Netscape time).
237: * @see <a href="http://unixpapa.com/js/mouse.html">Javascript Madness: Mouse Events</a>
238: * @return the button code
239: */
240: public int jsxGet_which() {
241: return button_ + 1;
242: }
243:
244: /**
245: * Implementation of the DOM Level 2 Event method for initializing the mouse event.
246: *
247: * @param type the event type
248: * @param bubbles can the event bubble
249: * @param cancelable can the event be canceled
250: * @param view the view to use for this event
251: * @param detail the detail to set for the event
252: * @param screenX the initial value of screenX
253: * @param screenY the initial value of screenY
254: * @param clientX the initial value of clientX
255: * @param clientY the initial value of clientY
256: * @param ctrlKey is the control key pressed
257: * @param altKey is the alt key pressed
258: * @param shiftKey is the shift key pressed
259: * @param metaKey is the meta key pressed
260: * @param button what mouse button is pressed
261: * @param relatedTarget is there a related target for the event
262: */
263: public void jsxFunction_initMouseEvent(final String type,
264: final boolean bubbles, final boolean cancelable,
265: final Object view, final int detail, final int screenX,
266: final int screenY, final int clientX, final int clientY,
267: final boolean ctrlKey, final boolean altKey,
268: final boolean shiftKey, final boolean metaKey,
269: final int button, final Object relatedTarget) {
270: jsxFunction_initUIEvent(type, bubbles, cancelable, view, detail);
271: screenX_ = screenX;
272: screenY_ = screenY;
273: // Ignore the clientX parameter; we always use screenX.
274: // Ignore the clientY parameter; we always use screenY.
275: setCtrlKey(ctrlKey);
276: setAltKey(altKey);
277: setShiftKey(shiftKey);
278: // Ignore the metaKey parameter; we don't support it yet.
279: button_ = button;
280: // Ignore the relatedTarget parameter; we don't support it yet.
281: }
282:
283: /**
284: * Returns the mouse event currently firing, or <tt>null</tt> if no mouse event is being processed.
285: * @return the mouse event currently firing
286: */
287: static MouseEvent getCurrentMouseEvent() {
288: final Event event = (Event) Context.getCurrentContext()
289: .getThreadLocal(KEY_CURRENT_EVENT);
290: if (event instanceof MouseEvent) {
291: return (MouseEvent) event;
292: }
293: return null;
294: }
295:
296: /**
297: * Returns <tt>true</tt> if the specified event type should be managed as a mouse event.
298: * @param type the type of event to check
299: * @return <tt>true</tt> if the specified event type should be managed as a mouse event
300: */
301: static boolean isMouseEvent(final String type) {
302: return TYPE_CLICK.equals(type) || TYPE_MOUSE_OVER.equals(type)
303: || TYPE_MOUSE_MOVE.equals(type)
304: || TYPE_MOUSE_OUT.equals(type)
305: || TYPE_MOUSE_DOWN.equals(type)
306: || TYPE_MOUSE_UP.equals(type)
307: || TYPE_CONTEXT_MENU.equals(type);
308: }
309:
310: }
|