| /* |
| * Copyright 2000-2009 JetBrains s.r.o. |
| * |
| * 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 com.intellij.uiDesigner.designSurface; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.uiDesigner.FormEditingUtil; |
| import com.intellij.uiDesigner.core.GridConstraints; |
| import com.intellij.uiDesigner.radComponents.RadComponent; |
| import com.intellij.uiDesigner.radComponents.RadContainer; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.datatransfer.DataFlavor; |
| import java.awt.datatransfer.Transferable; |
| import java.awt.datatransfer.UnsupportedFlavorException; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| |
| /** |
| * @author yole |
| */ |
| public class DraggedComponentList implements Transferable, ComponentDragObject { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.DraggedComponentList"); |
| |
| private static DataFlavor ourDataFlavor; |
| |
| static { |
| try { |
| ourDataFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType); |
| } catch (ClassNotFoundException e) { |
| LOG.error(e); |
| } |
| } |
| |
| private final ArrayList<RadComponent> mySelection; |
| private GridConstraints[] myOriginalConstraints; |
| private Rectangle[] myOriginalBounds; |
| private RadContainer[] myOriginalParents; |
| private int myDragRelativeColumn = 0; |
| private int myComponentUnderMouseColumn; |
| private int myComponentUnderMouseRow; |
| private int myDragDeltaX = 0; |
| private int myDragDeltaY = 0; |
| private boolean myHasDragDelta = false; |
| |
| private DraggedComponentList(Collection<RadComponent> selection) { |
| mySelection = new ArrayList<RadComponent>(selection); |
| fillOriginalConstraints(); |
| } |
| |
| private DraggedComponentList(final GuiEditor editor, final Point pnt) { |
| // Store selected components |
| mySelection = FormEditingUtil.getSelectedComponents(editor); |
| |
| // sort selection in correct grid order |
| Collections.sort(mySelection, new Comparator<RadComponent>() { |
| public int compare(final RadComponent o1, final RadComponent o2) { |
| if (o1.getParent() == o2.getParent()) { |
| int result = o1.getConstraints().getRow() - o2.getConstraints().getRow(); |
| if (result == 0) { |
| result = o1.getConstraints().getColumn() - o2.getConstraints().getColumn(); |
| } |
| return result; |
| } |
| return 0; |
| } |
| }); |
| |
| RadComponent componentUnderMouse = null; |
| int componentUnderMouseIndex = mySelection.size() == 0 ? -1 : 0; |
| if (pnt != null) { |
| for(int i=0; i<mySelection.size(); i++) { |
| RadComponent c = mySelection.get(i); |
| Point aPoint = SwingUtilities.convertPoint(editor.getRootContainer().getDelegee(), pnt, |
| c.getParent().getDelegee()); |
| if (c.getBounds().contains(aPoint)) { |
| aPoint = SwingUtilities.convertPoint(editor.getRootContainer().getDelegee(), pnt, |
| c.getDelegee()); |
| mySelection.set(i, c.getComponentToDrag(aPoint)); |
| componentUnderMouseIndex = i; |
| } |
| } |
| } |
| fillOriginalConstraints(); |
| |
| if (componentUnderMouseIndex >= 0) { |
| componentUnderMouse = mySelection.get(componentUnderMouseIndex); |
| myComponentUnderMouseColumn = myOriginalConstraints [componentUnderMouseIndex].getColumn(); |
| myComponentUnderMouseRow = myOriginalConstraints [componentUnderMouseIndex].getRow(); |
| } |
| |
| LOG.debug("myComponentUnderMouseColumn=" + myComponentUnderMouseColumn + |
| ", myComponentUnderMouseRow=" + myComponentUnderMouseRow); |
| |
| if (mySelection.size() > 1 && componentUnderMouse != null) { |
| for(GridConstraints constraints: myOriginalConstraints) { |
| myDragRelativeColumn = Math.max(myDragRelativeColumn, |
| componentUnderMouse.getConstraints().getColumn() - constraints.getColumn()); |
| } |
| } |
| |
| for(RadComponent c: mySelection) { |
| JComponent delegee = c.getDelegee(); |
| if (c == componentUnderMouse && pnt != null) { |
| if (delegee.getX() > pnt.x && delegee.getX() + delegee.getWidth() < pnt.x) { |
| myDragDeltaX = pnt.x - (delegee.getX() + delegee.getWidth() / 2); |
| } |
| if (delegee.getY() > pnt.y && delegee.getY() + delegee.getHeight() < pnt.y) { |
| myDragDeltaY = pnt.y - (delegee.getY() + delegee.getHeight() / 2); |
| } |
| myHasDragDelta = true; |
| } |
| } |
| } |
| |
| private void fillOriginalConstraints() { |
| // Store original constraints and parents. This information is required |
| // to restore initial state if drag is canceled. |
| myOriginalConstraints = new GridConstraints[mySelection.size()]; |
| myOriginalBounds = new Rectangle[mySelection.size()]; |
| myOriginalParents = new RadContainer[mySelection.size()]; |
| for (int i1 = 0; i1 < mySelection.size(); i1++) { |
| final RadComponent component = mySelection.get(i1); |
| myOriginalConstraints[i1] = component.getConstraints().store(); |
| myOriginalBounds[i1] = component.getBounds(); |
| myOriginalParents[i1] = component.getParent(); |
| } |
| } |
| |
| public static DraggedComponentList pickupSelection(final GuiEditor editor, @Nullable Point pnt) { |
| return new DraggedComponentList(editor, pnt); |
| } |
| |
| public static DraggedComponentList withComponents(RadComponent... c) { |
| ArrayList<RadComponent> list = new ArrayList<RadComponent>(); |
| Collections.addAll(list, c); |
| return new DraggedComponentList(list); |
| } |
| |
| @Nullable |
| public static DraggedComponentList fromTransferable(final Transferable transferable) { |
| if (transferable.isDataFlavorSupported(ourDataFlavor)) { |
| Object data; |
| try { |
| data = transferable.getTransferData(ourDataFlavor); |
| } |
| catch (Exception e) { |
| return null; |
| } |
| if (data instanceof DraggedComponentList) { |
| return (DraggedComponentList) data; |
| } |
| } |
| return null; |
| } |
| |
| public int getDragDeltaX() { |
| return myDragDeltaX; |
| } |
| |
| public int getDragDeltaY() { |
| return myDragDeltaY; |
| } |
| |
| public ArrayList<RadComponent> getComponents() { |
| return mySelection; |
| } |
| |
| public int getComponentCount() { |
| return mySelection.size(); |
| } |
| |
| public RadContainer getOriginalParent(final RadComponent c) { |
| return myOriginalParents [mySelection.indexOf(c)]; |
| } |
| |
| /** |
| * Returns a copy of the original constraints array. |
| */ |
| public GridConstraints[] getOriginalConstraints() { |
| GridConstraints[] result = new GridConstraints[myOriginalConstraints.length]; |
| for(int i=0; i<myOriginalConstraints.length; i++) { |
| result [i] = myOriginalConstraints [i].store(); |
| } |
| return result; |
| } |
| |
| public Rectangle[] getOriginalBounds() { |
| return myOriginalBounds; |
| } |
| |
| public Rectangle getOriginalBounds(final RadComponent c) { |
| return myOriginalBounds [mySelection.indexOf(c)]; |
| } |
| |
| public DataFlavor[] getTransferDataFlavors() { |
| return new DataFlavor[] { ourDataFlavor }; |
| } |
| |
| public boolean isDataFlavorSupported(DataFlavor flavor) { |
| return flavor.equals(ourDataFlavor); |
| } |
| |
| public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { |
| return this; |
| } |
| |
| public boolean isHGrow() { |
| for(GridConstraints c: myOriginalConstraints) { |
| if ((c.getHSizePolicy() & GridConstraints.SIZEPOLICY_WANT_GROW) != 0) return true; |
| } |
| return false; |
| } |
| |
| public boolean isVGrow() { |
| for(GridConstraints c: myOriginalConstraints) { |
| if ((c.getVSizePolicy() & GridConstraints.SIZEPOLICY_WANT_GROW) != 0) return true; |
| } |
| return false; |
| } |
| |
| public int getRelativeRow(int componentIndex) { |
| return myOriginalConstraints [componentIndex].getRow() - myComponentUnderMouseRow; |
| } |
| |
| public int getRelativeCol(int componentIndex) { |
| return myOriginalConstraints [componentIndex].getColumn() - myComponentUnderMouseColumn; |
| } |
| |
| public int getRowSpan(int componentIndex) { |
| return myOriginalConstraints [componentIndex].getRowSpan(); |
| } |
| |
| public int getColSpan(int componentIndex) { |
| return myOriginalConstraints [componentIndex].getColSpan(); |
| } |
| |
| public Point getDelta(int componentIndex) { |
| return null; |
| } |
| |
| @NotNull |
| public Dimension getInitialSize(final RadContainer targetContainer) { |
| if (myOriginalBounds.length == 1) { |
| return myOriginalBounds [0].getSize(); |
| } |
| return new Dimension(-1, -1); |
| } |
| |
| public RadContainer[] getOriginalParents() { |
| return myOriginalParents; |
| } |
| |
| public boolean hasDragDelta() { |
| return myHasDragDelta; |
| } |
| } |