/* * Ext GWT - Ext for GWT * Copyright(c) 2007-2009, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license */ package com.extjs.gxt.ui.client.dnd; import com.extjs.gxt.ui.client.dnd.DND.Feedback; import com.extjs.gxt.ui.client.dnd.DND.Operation; import com.extjs.gxt.ui.client.event.BaseEvent; import com.extjs.gxt.ui.client.event.BaseObservable; import com.extjs.gxt.ui.client.event.DNDEvent; import com.extjs.gxt.ui.client.event.DNDListener; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.widget.Component; /** * Identifies components that can receive data from a drag and drop operations. * * <p /> * While the cursor is over a target, the target is responsible for determining * if the drop is valid and showing any visual indicators for the drop. The @link * {@link StatusProxy} object should be used to specify if the drop is valid, * and can also be used to change the values of the proxy object displayed by * the cursor. The status proxy is accessible via the DNDEvent. * * <dl> * <dt><b>Events:</b></dt> * * <dd><b>DragEnter</b> : DNDEvent(target, source, component, event, dragEvent, * status)<br> * <div>Fires after the cursor enters the target's boundaries.</div> * <ul> * <li>target : this</li> * <li>source : the drag source * <li>component : the source component</li> * <li>event : the dom event</li> * <li>dragEvent : the drag event (draggable)</li> * <li>status : the status object</li> * </ul> * </dd> * * <dd><b>DragLeave</b> : DNDEvent(target, source, component, event, dragEvent, * status)<br> * <div>Fires after the cursor leaves the target's boundaries.</div> * <ul> * <li>target : this</li> * <li>source : the drag source * <li>component : the source component</li> * <li>event : the dom event</li> * <li>dragEvent : the drag event (draggable)</li> * <li>status : the status object</li> * </ul> * </dd> * * <dd><b>DragCancel</b> : DNDEvent(target, source, component, event, dragEvent, * status)<br> * <div>Fires after the user when a drag operation is cancelled.</div> * <ul> * <li>target : this</li> * <li>source : the drag source * <li>component : the source component</li> * <li>event : the dom event</li> * <li>dragEvent : the drag event (draggable)</li> * <li>status : the status object</li> * </ul> * </dd> * * <dd><b>DragMove</b> : DNDEvent(target, source, component, event, dragEvent, * status)<br> * <div>Fires after the user begins a drag and drop operation.</div> * <ul> * <li>target : this</li> * <li>source : the drag source * <li>component : the source component</li> * <li>event : the dom event</li> * <li>dragEvent : the drag event (draggable)</li> * <li>status : the status object</li> * </ul> * </dd> * * <dd><b>DragDrop</b> : DNDEvent(target, source, data, component, event, * dragEvent, status)<br> * <div>Fires after the user drops data over the target.</div> * <ul> * <li>target : this</li> * <li>source : the drag source * <li>data : the data being dragged * <li>component : the source component</li> * <li>event : the dom event</li> * <li>dragEvent : the drag event (draggable)</li> * <li>status : the status object</li> * </ul> * </dd> * </dl> */ public class DropTarget extends BaseObservable { protected Component component; protected String overStyle; protected Operation operation; protected Feedback feedback; private boolean allowSelfAsSource; private String group = ""; private boolean enabled = true; /** * Creates a new drop target. * * @param target the target component */ public DropTarget(Component target) { this.component = target; this.operation = Operation.MOVE; this.feedback = Feedback.APPEND; DNDManager.get().registerDropTarget(this); } /** * Adds the listener to the target. * * @param listener the listener to add */ public void addDNDListener(DNDListener listener) { addListener(Events.DragEnter, listener); addListener(Events.DragLeave, listener); addListener(Events.DragCancel, listener); addListener(Events.Drop, listener); addListener(Events.DragMove, listener); } /** * Disables the drag source. */ public void disable() { enabled = false; } /** * Enables the drag source. */ public void enable() { enabled = true; } /** * Returns the target's component. * * @return the component */ public Component getComponent() { return component; } /** * Returns the target's feedback setting. * * @return the feedback */ public Feedback getFeedback() { return feedback; } /** * Returns the target's group name. * * @return the group name */ public String getGroup() { return group; } /** * Returns the target's operation. * * @return the operation */ public Operation getOperation() { return operation; } /** * Returns the target's over style. * * @return the over style */ public String getOverStyle() { return overStyle; } /** * Returns true if internal drops are allowed. * * @return true for internal drops */ public boolean isAllowSelfAsSource() { return allowSelfAsSource; } /** * Returns true if the drag source is enabled. * * @return true for enabled */ public boolean isEnabled() { return enabled; } /** * Unregisters the target as a drop target. */ public void release() { DNDManager.get().unregisterDropTarget(this); } /** * Removes the listener. * * @param listener the listener to be removed */ public void removeDNDListener(DNDListener listener) { removeListener(Events.DragStart, listener); removeListener(Events.DragLeave, listener); removeListener(Events.DragMove, listener); removeListener(Events.DragCancel, listener); removeListener(Events.Drop, listener); } /** * Sets whether internal drops are allowed (defaults to false). * * @param allowSelfAsSource true to allow internal drops */ public void setAllowSelfAsSource(boolean allowSelfAsSource) { this.allowSelfAsSource = allowSelfAsSource; } /** * Sets the target's feedback. Feedback determines the type of visual * indicators a drop target supports. Subclasses will determine range of valid * values. * * @param feedback the feedback */ public void setFeedback(Feedback feedback) { this.feedback = feedback; } /** * Sets the drag group. If specified, only drag sources with the same group * value are allowed. * * @param group the group name */ public void setGroup(String group) { this.group = group; } /** * Sets the operation for the drop target which specifies if data should be * moved or copied when dropped. Drag sources use this value to determine if * the target data should be removed from the source component. * * @param operation the operation */ public void setOperation(Operation operation) { this.operation = operation; } /** * Sets the style name to be applied when the cursor is over the target * (defaults to null). * * @param overStyle the over style */ public void setOverStyle(String overStyle) { this.overStyle = overStyle; } /** * Called if the user cancels the drag operations while the mouse is over the * target. * * @param event the dd event */ protected void onDragCancelled(DNDEvent event) { Insert.get().hide(); } /** * Called when the user releases the mouse over the target component. * * @param event the dd event */ protected void onDragDrop(DNDEvent event) { } /** * Called when the cursor first enters the bounds of the drop target. * Subclasses or listeners can change the status of status proxy via the * passed event. * * @param event the dd event */ protected void onDragEnter(DNDEvent event) { } /** * Called when the cursor leaves the target. * * @param event the dd event */ protected void onDragLeave(DNDEvent event) { } /** * Called when the cursor is moved within the target component. Subclasses or * listeners can change the status of status proxy via the passed event. If * either a subclass or listener sets {@link BaseEvent#setCancelled(boolean)} * to true, {@link #showFeedback(DNDEvent)} will be called. * * @param event the dd event */ protected void onDragMove(DNDEvent event) { } /** * Called as the mouse is moved over the target component. The default * implementation does nothing. * * @param event the dd event */ protected void showFeedback(DNDEvent event) { } boolean handleDragEnter(DNDEvent event) { event.setCancelled(false); event.getStatus().setStatus(true); onDragEnter(event); if (!fireEvent(Events.DragEnter, event)) { event.getStatus().setStatus(false); return false; } if (overStyle != null) { component.addStyleName(overStyle); } return true; } void handleDragLeave(DNDEvent event) { if (overStyle != null) { component.removeStyleName(overStyle); } event.getStatus().setStatus(false); Insert.get().hide(); onDragLeave(event); } void handleDragMove(DNDEvent event) { showFeedback(event); onDragMove(event); } void handleDrop(DNDEvent event) { Insert.get().hide(); if (overStyle != null) { component.removeStyleName(overStyle); } onDragDrop(event); } }