Java tutorial
/* * Copyright 2011 John Ahlroos * * 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 fi.jasoft.dragdroplayouts.client.ui; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.Paintable; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; import com.vaadin.terminal.gwt.client.VCaption; import com.vaadin.terminal.gwt.client.VConsole; import com.vaadin.terminal.gwt.client.ui.VScrollTable; import com.vaadin.terminal.gwt.client.ui.VTwinColSelect; import com.vaadin.terminal.gwt.client.ui.dd.HorizontalDropLocation; import com.vaadin.terminal.gwt.client.ui.dd.VTransferable; import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; import fi.jasoft.dragdroplayouts.client.ui.interfaces.VHasDragMode; public final class VDragDropUtil { private VDragDropUtil() { // Prevent instantiation } /** * Get the vertical drop location in a ordered layout * * @param element * The target element or cell * @param clientY * The client y-coordinate * @param topBottomRatio * The ratio how the cell has been divided * @return The drop location */ public static VerticalDropLocation getVerticalDropLocation(Element element, int clientY, double topBottomRatio) { int offsetHeight = element.getOffsetHeight(); return getVerticalDropLocation(element, offsetHeight, clientY, topBottomRatio); } /** * Get the vertical drop location in a ordered layout * * @param element * The target element or cell * @param offsetHeight * The height of the cell * @param clientY * The width of the cell * @param topBottomRatio * The ratio of the cell * @return The location of the drop */ public static VerticalDropLocation getVerticalDropLocation(Element element, int offsetHeight, int clientY, double topBottomRatio) { int absoluteTop = element.getAbsoluteTop(); int fromTop = clientY - absoluteTop; float percentageFromTop = (fromTop / (float) offsetHeight); if (percentageFromTop < topBottomRatio) { return VerticalDropLocation.TOP; } else if (percentageFromTop > 1 - topBottomRatio) { return VerticalDropLocation.BOTTOM; } else { return VerticalDropLocation.MIDDLE; } } /** * Get the horizontal drop location in an ordered layout * * @param element * The target element or cell * @param clientX * The x-coordinate of the drop * @param leftRightRatio * The ratio of how the cell has been divided * @return the drop location relative to the cell */ public static HorizontalDropLocation getHorizontalDropLocation(Element element, int clientX, double leftRightRatio) { int absoluteLeft = element.getAbsoluteLeft(); int offsetWidth = element.getOffsetWidth(); int fromTop = clientX - absoluteLeft; float percentageFromTop = (fromTop / (float) offsetWidth); if (percentageFromTop < leftRightRatio) { return HorizontalDropLocation.LEFT; } else if (percentageFromTop > 1 - leftRightRatio) { return HorizontalDropLocation.RIGHT; } else { return HorizontalDropLocation.CENTER; } } /** * Creates a transferable for the tabsheet * * @param tabsheet * The tabsheet the event occurred * @param tab * The tab on which the event occurred * @param event * The event * @param root * The root widget * @return */ private static VTransferable createTabsheetTransferableFromMouseDown(VDDTabSheet tabsheet, Widget tab, NativeEvent event) { // Create transferable VTransferable transferable = new VTransferable(); transferable.setDragSource(tabsheet); if (tabsheet != tab) { transferable.setData(Constants.TRANSFERABLE_DETAIL_COMPONENT, tab); transferable.setData(Constants.TRANSFERABLE_DETAIL_INDEX, tabsheet.getTabPosition(tab)); transferable.setData("tabSheetAbsoluteTop", tabsheet.getAbsoluteTop()); transferable.setData("tabSheetAbsoluteLeft", tabsheet.getAbsoluteLeft()); } transferable.setData(Constants.TRANSFERABLE_DETAIL_MOUSEDOWN, new MouseEventDetails(event).serialize()); return transferable; } /** * Creates a transferable for the Accordion * * @param accordion * The Accordion where the event occurred * @param tab * The tab on which the event occurred * @param event * The event * @param root * The root widget * @return */ private static VTransferable createAccordionTransferableFromMouseDown(VDDAccordion accordion, VCaption tabCaption, NativeEvent event) { // Create transferable VTransferable transferable = new VTransferable(); transferable.setDragSource(accordion); transferable.setData(Constants.TRANSFERABLE_DETAIL_CAPTION, tabCaption); transferable.setData(Constants.TRANSFERABLE_DETAIL_COMPONENT, tabCaption.getParent()); transferable.setData(Constants.TRANSFERABLE_DETAIL_INDEX, accordion.getWidgetIndex(tabCaption.getParent())); transferable.setData(Constants.TRANSFERABLE_DETAIL_MOUSEDOWN, new MouseEventDetails(event).serialize()); return transferable; } /** * Creates a transferable from a mouse down event. Returns null if creation * was not successful. * * @param event * The mouse down event * @param root * The root layout from where the component is dragged * @return A transferable or NULL if something failed */ public static VTransferable createLayoutTransferableFromMouseDown(NativeEvent event, Widget root) { Widget w = Util.findWidget((Element) event.getEventTarget().cast(), null); // NPE check if (w == null) { VConsole.error("Could not find widget"); return null; } // Special treatment for Tabsheet if (root instanceof VDDTabSheet) { if (w instanceof VCaption || w == root) { // We are dragging a tabsheet tab, handle it return createTabsheetTransferableFromMouseDown((VDDTabSheet) root, w, event); } else { return null; } } // Special treatment for Accordion if (root instanceof VDDAccordion) { if (w instanceof VCaption || w == root) { // We are dragging a Accordion tab, handle it return createAccordionTransferableFromMouseDown((VDDAccordion) root, (VCaption) w, event); } else { // Do not allow dragging content, only the "tab" return null; } } // Ensure we have the right widget w = getTransferableWidget(w); // Find the containing layout of the component Container layout = Util.getLayout(w); // Iterate until parent either is the root or a layout with drag and // drop enabled while (layout != root && layout != null) { if (layout instanceof VHasDragMode && ((VHasDragMode) layout).getDragMode() != LayoutDragMode.NONE) { // Found parent layout with support for drag and drop break; } w = (Widget) layout; layout = Util.getLayout(w); } // Consistency check if (w == null || root == w || layout == null) { VConsole.error("Consistency check failed"); return null; } // Ensure layout allows dragging if (!isDraggingEnabled(layout)) { return null; } return createTransferable(layout, w, event); } private static VTransferable createTransferable(Container layout, Widget widget, NativeEvent event) { VTransferable transferable = new VTransferable(); transferable.setDragSource(layout); transferable.setData(Constants.TRANSFERABLE_DETAIL_COMPONENT, widget); transferable.setData(Constants.TRANSFERABLE_DETAIL_MOUSEDOWN, new MouseEventDetails(event).serialize()); return transferable; } private static Widget getTransferableWidget(Widget w) { // Ensure w is Paintable while (!(w instanceof Paintable) && w.getParent() != null) { w = w.getParent(); } // Are we grabbing the caption of a component boolean isCaption = w instanceof VCaption; if (isCaption) { // Dragging caption means dragging component the caption belongs to Widget owner = (Widget) ((VCaption) w).getOwner(); if (owner != null) { w = owner; } } else if (w instanceof VScrollTable.VScrollTableBody.VScrollTableRow) { // Table rows are paintable but we do not want to drag them so // search for next paintable which should be the table itself w = w.getParent(); while (!(w instanceof Paintable)) { w = w.getParent(); } } else if (w.getParent().getParent().getParent() instanceof VTwinColSelect) { // TwinColSelect has paintable buttons.. w = w.getParent().getParent().getParent(); } return w; } /** * Is dragging enabled for a component container * * @param layout * The component container to check * @return */ private static boolean isDraggingEnabled(Container layout) { if (layout instanceof VHasDragMode) { LayoutDragMode dm = ((VHasDragMode) layout).getDragMode(); return dm != LayoutDragMode.NONE; } return false; } /** * Removes the Drag and drop fake paintable from an UIDL * * @param uidl * The uidl which contains a dragdrop paintable (-ac) * @return UIDL stripped of the paintable */ public static native UIDL removeDragDropCriteraFromUIDL(UIDL uidl) /*-{ var obj = new Array(); for(key in uidl){ if(uidl[key][0] != "-ac"){ obj[key] = uidl[key]; } } return obj; }-*/; /** * Measures the left margin of an element * * @param element * The element to measure * @return Left margin in pixels */ public static int measureMarginLeft(Element element) { return element.getAbsoluteLeft() - element.getParentElement().getAbsoluteLeft(); } /** * Measures the top margin of an element * * @param element * The element to measure * @return Top margin in pixels */ public static int measureMarginTop(Element element) { return element.getAbsoluteTop() - element.getParentElement().getAbsoluteTop(); } }