/* * Copyright 2010 The gwtquery plugins team. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package gwtquery.plugins.droppable.client.gwt; import static com.google.gwt.query.client.GQuery.$; import static gwtquery.plugins.droppable.client.Droppable.Droppable; import com.google.gwt.dom.client.Element; import com.google.gwt.event.shared.EventBus; import com.google.gwt.event.shared.EventHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.event.shared.SimpleEventBus; import com.google.gwt.event.shared.GwtEvent.Type; import com.google.gwt.query.client.plugins.events.EventsListener; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import gwtquery.plugins.draggable.client.DraggableOptions; import gwtquery.plugins.droppable.client.DroppableOptions; import gwtquery.plugins.droppable.client.DroppableOptions.AcceptFunction; import gwtquery.plugins.droppable.client.DroppableOptions.DroppableTolerance; import gwtquery.plugins.droppable.client.events.ActivateDroppableEvent; import gwtquery.plugins.droppable.client.events.DeactivateDroppableEvent; import gwtquery.plugins.droppable.client.events.DropEvent; import gwtquery.plugins.droppable.client.events.HasAllDropHandler; import gwtquery.plugins.droppable.client.events.OutDroppableEvent; import gwtquery.plugins.droppable.client.events.OverDroppableEvent; import gwtquery.plugins.droppable.client.events.ActivateDroppableEvent.ActivateDroppableEventHandler; import gwtquery.plugins.droppable.client.events.DeactivateDroppableEvent.DeactivateDroppableEventHandler; import gwtquery.plugins.droppable.client.events.DropEvent.DropEventHandler; import gwtquery.plugins.droppable.client.events.OutDroppableEvent.OutDroppableEventHandler; import gwtquery.plugins.droppable.client.events.OverDroppableEvent.OverDroppableEventHandler; /** * Wrapper widget that wrap an GWT widget and make it a drop target. * <p/> * This class can be used as a wrapper or subclassed. * * @param <T> * @author Julien Dramaix (julien.dramaix@gmail.com) */ public class DroppableWidget<T extends Widget> extends Composite implements HasAllDropHandler { private final static String DROPPABLE_WIDGET_KEY = "__droppableWidget"; /** * This method return the widget associated to a droppable DOM element if it * exist. It returns null otherwise. * * @param e a droppable DOM element * @return */ public static DroppableWidget<?> get(Element e) { return $(e).data(DROPPABLE_WIDGET_KEY, DroppableWidget.class); } private EventBus dropHandlerManager; private DroppableOptions options; /** * Constructor * * @param w the widget that you want to make it a drop target. */ public DroppableWidget(T w) { this(w, new DroppableOptions(), DraggableOptions.DEFAULT_SCOPE); } /** * Constructor * * @param w the widget that you want to make it a drop target. * @param options options to use during the drop operation */ public DroppableWidget(T w, DroppableOptions options) { this(w, options, DraggableOptions.DEFAULT_SCOPE); } /** * Constructor * * @param w the widget that you want to make it a drop target. * @param options options to use during the drop operation * @param scope Used to group sets of draggable and droppable Widget, in addition * to droppable's accept option. A draggable with the same scope * value as a droppable will be accepted. */ public DroppableWidget(T w, DroppableOptions options, String scope) { initWidget(w); this.options = options; this.options.setScope(scope); } /** * Add possibility to extend this widget. As {@link DroppableWidget} is a * {@link Composite}, don't forget to call the {@link #initWidget(Widget)} * method */ protected DroppableWidget() { options = new DroppableOptions(); } /** * Add a handler object that will manage the {@link ActivateDroppableEvent} * event. This kind of event is fired when an acceptable draggable start to * drag. * * @return {@link HandlerRegistration} used to remove the handler */ public HandlerRegistration addActivateDroppableHandler(ActivateDroppableEventHandler handler) { return addDropHandler(handler, ActivateDroppableEvent.TYPE); } /** * Add a handler object that will manage the {@link DeactivateDroppableEvent} * event. This kind of event is fired when an acceptable draggable finishes to * drag. * * @return {@link HandlerRegistration} used to remove the handler */ public HandlerRegistration addDeactivateDroppableHandler(DeactivateDroppableEventHandler handler) { return addDropHandler(handler, DeactivateDroppableEvent.TYPE); } /** * Add a handler object that will manage the {@link DropEvent} event. This * kind of event is fired when an acceptable draggable is dropped in the * droppable * * @return {@link HandlerRegistration} used to remove the handler */ public HandlerRegistration addDropHandler(DropEventHandler handler) { return addDropHandler(handler, DropEvent.TYPE); } /** * Add a handler object that will manage the {@link OutDroppableEvent} event. * This kind of event is fired when an acceptable draggable is being dragged * out of the droppable. * * @return {@link HandlerRegistration} used to remove the handler */ public HandlerRegistration addOutDroppableHandler(OutDroppableEventHandler handler) { return addDropHandler(handler, OutDroppableEvent.TYPE); } /** * Add a handler object that will manage the {@link OutDroppableEvent} event. * This kind of event is fired when a acceptable draggable is being dragged * over the droppable. * * @return {@link HandlerRegistration} used to remove the handler */ public HandlerRegistration addOverDroppableHandler(OverDroppableEventHandler handler) { return addDropHandler(handler, OverDroppableEvent.TYPE); } /** * @return the {@link AcceptFunction} */ public AcceptFunction getAccept() { return options.getAccept(); } /** * @return the css class added to the droppable when is activated */ public String getActiveClass() { return options.getActiveClass(); } /** * Return the drag and drop scope. A draggable widget with the same scope than * a droppable widget will be accepted by this droppable. * * @return the scope */ public String getDragAndDropScope() { return options.getScope(); } /** * @return the css class added to an acceptable draggable when it is * being dragged over a droppable */ public String getDraggableHoverClass() { return options.getDraggableHoverClass(); } /** * @return the css class added to the droppable when is hovered */ public String getDroppableHoverClass() { return options.getDroppableHoverClass(); } /** * @return the {@link DroppableOptions} currently used. */ public DroppableOptions getOptions() { return options; } /** * Get the wrapped original widget * * @return */ @SuppressWarnings("unchecked") public T getOriginalWidget() { return (T) getWidget(); } /** * @return the {@link DroppableTolerance} */ public DroppableTolerance getTolerance() { return options.getTolerance(); } /** * @return if the drop is disabled or not. */ public boolean isDisabled() { return options.isDisabled(); } /** * Specify if the droppable is greedy or not. A greedy droppable will prevent * events propagation on drappable parents of this droppable * * @return true if the droppable is greedy. False otherwise */ public boolean isGreedy() { return options.isGreedy(); } /** * set the {@link AcceptFunction}. If null is given, the droppable will accept * all draggables. * * @param acceptFunction */ public void setAccept(AcceptFunction acceptFunction) { if (acceptFunction != null) { options.setAccept(acceptFunction); } else { options.setAccept(DroppableOptions.ACCEPT_ALL); } } /** * Set the css selector used to define elements that will be accepted by this * droppable * * @param selector */ public void setAccept(String selector) { options.setAccept(selector); } /** * Set the css class that will be add to the droppable when it is activated * * @param activeClass */ public void setActiveClass(String activeClass) { options.setActiveClass(activeClass); } /** * Disable (true) or enable (false) the drop. * * @param disabled */ public void setDisabled(boolean disabled) { options.setDisabled(disabled); } /** * Used to group sets of draggable and droppable widget, in addition to * droppable's {@link AcceptFunction}. A DraggableWidget with the same scope * value than a DroppableWidget will be accepted by this last. * * @param scope */ public void setDragAndDropScope(String scope) { $(getElement()).as(Droppable).changeScope(scope); options.setScope(scope); } /** * Set the css class added to an acceptable draggable when it is * being dragged over the droppable * * @param draggableHoverClass */ public void setDraggableHoverClass(String draggableHoverClass) { options.setDraggableHoverClass(draggableHoverClass); } /** * Css class added when a acceptable draggable is being dragged over this * droppable * * @param hoverClass css class */ public void setDroppableHoverClass(String hoverClass) { options.setDroppableHoverClass(hoverClass); } /** * When set to true it prevents events propagation on parents droppable of * this droppable * * @param greedy */ public void setGreedy(boolean greedy) { options.setGreedy(greedy); } /** * set the {@link DroppableTolerance} * * @param tolerance */ public void setTolerance(DroppableTolerance tolerance) { options.setTolerance(tolerance); } protected final <H extends EventHandler> HandlerRegistration addDropHandler(H handler, Type<H> type) { return ensureDropHandlers().addHandler(type, handler); } protected EventBus ensureDropHandlers() { return dropHandlerManager == null ? dropHandlerManager = new SimpleEventBus() : dropHandlerManager; } protected EventBus getDropHandlerManager() { return dropHandlerManager; } @Override protected void onLoad() { super.onLoad(); $(getElement()).as(Droppable).droppable(options, ensureDropHandlers()).data(DROPPABLE_WIDGET_KEY, this); } @Override protected void onUnload() { super.onUnload(); $(getElement()).as(Droppable).destroy().removeData(DROPPABLE_WIDGET_KEY); } }