| /* |
| * 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.ide.palette.impl.PaletteToolWindowManager; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.command.CommandProcessor; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.uiDesigner.CutCopyPasteSupport; |
| import com.intellij.uiDesigner.FormEditingUtil; |
| import com.intellij.uiDesigner.SimpleTransferable; |
| import com.intellij.uiDesigner.UIDesignerBundle; |
| import com.intellij.uiDesigner.componentTree.ComponentTree; |
| import com.intellij.uiDesigner.core.GridConstraints; |
| import com.intellij.uiDesigner.palette.ComponentItem; |
| import com.intellij.uiDesigner.propertyInspector.DesignerToolWindowManager; |
| import com.intellij.uiDesigner.radComponents.RadComponent; |
| import com.intellij.uiDesigner.radComponents.RadContainer; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.awt.dnd.*; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author yole |
| */ |
| class DesignDropTargetListener implements DropTargetListener { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.uiDesigner.designSurface.DesignDropTargetListener"); |
| |
| private DraggedComponentList myDraggedComponentList; |
| private ComponentDragObject myComponentDragObject; |
| private List<RadComponent> myDraggedComponentsCopy; |
| private Point myLastPoint; |
| private final GuiEditor myEditor; |
| private final GridInsertProcessor myGridInsertProcessor; |
| private boolean myUseDragDelta = false; |
| |
| public DesignDropTargetListener(final GuiEditor editor) { |
| myEditor = editor; |
| myGridInsertProcessor = new GridInsertProcessor(editor); |
| } |
| |
| public void dragEnter(DropTargetDragEvent dtde) { |
| try { |
| DraggedComponentList dcl = DraggedComponentList.fromTransferable(dtde.getTransferable()); |
| if (dcl != null) { |
| myDraggedComponentList = dcl; |
| myComponentDragObject = dcl; |
| processDragEnter(dcl, dtde.getLocation(), dtde.getDropAction()); |
| dtde.acceptDrag(dtde.getDropAction()); |
| myLastPoint = dtde.getLocation(); |
| } |
| else { |
| ComponentItem componentItem = SimpleTransferable.getData(dtde.getTransferable(), ComponentItem.class); |
| if (componentItem != null) { |
| myComponentDragObject = new ComponentItemDragObject(componentItem); |
| dtde.acceptDrag(dtde.getDropAction()); |
| myLastPoint = dtde.getLocation(); |
| } |
| } |
| } |
| catch (Exception e) { |
| LOG.error(e); |
| } |
| } |
| |
| private void processDragEnter(final DraggedComponentList draggedComponentList, final Point location, final int dropAction) { |
| final List<RadComponent> dragComponents = draggedComponentList.getComponents(); |
| |
| Rectangle allBounds = null; |
| if (!draggedComponentList.hasDragDelta() || !myUseDragDelta) { |
| final RadContainer[] originalParents = draggedComponentList.getOriginalParents(); |
| final Rectangle[] originalBounds = draggedComponentList.getOriginalBounds(); |
| for(int i=0; i<originalParents.length; i++) { |
| Rectangle rc = SwingUtilities.convertRectangle(originalParents [i].getDelegee(), |
| originalBounds [i], |
| myEditor.getDragLayer()); |
| if (allBounds == null) { |
| allBounds = rc; |
| } |
| else { |
| allBounds = allBounds.union(rc); |
| } |
| } |
| } |
| |
| // Place selected components to the drag layer. |
| myDraggedComponentsCopy = CutCopyPasteSupport.copyComponents(myEditor, dragComponents); |
| for (int i=0; i<dragComponents.size(); i++) { |
| myDraggedComponentsCopy.get(i).setSelected(true); |
| final JComponent delegee = myDraggedComponentsCopy.get(i).getDelegee(); |
| final Point point = SwingUtilities.convertPoint( |
| draggedComponentList.getOriginalParents() [i].getDelegee(), |
| delegee.getLocation(), |
| myEditor.getDragLayer() |
| ); |
| if (draggedComponentList.hasDragDelta() && myUseDragDelta) { |
| delegee.setLocation((int) point.getX() + draggedComponentList.getDragDeltaX(), |
| (int) point.getY() + draggedComponentList.getDragDeltaY()); |
| } |
| else { |
| assert allBounds != null; |
| delegee.setLocation((int) (point.getX() - allBounds.getX() + location.getX()), |
| (int) (point.getY() - allBounds.getY() + location.getY())); |
| } |
| //myEditor.getDragLayer().add(delegee); |
| } |
| |
| for (final RadComponent c : dragComponents) { |
| if (dropAction != DnDConstants.ACTION_COPY) { |
| c.setDragBorder(true); |
| } |
| c.setSelected(false); |
| } |
| } |
| |
| public void dragOver(DropTargetDragEvent dtde) { |
| try { |
| if (myComponentDragObject == null) { |
| dtde.rejectDrag(); |
| return; |
| } |
| final int dx = dtde.getLocation().x - myLastPoint.x; |
| final int dy = dtde.getLocation().y - myLastPoint.y; |
| |
| if (myDraggedComponentsCopy != null && myDraggedComponentList != null) { |
| for (RadComponent aMySelection : myDraggedComponentsCopy) { |
| aMySelection.shift(dx, dy); |
| } |
| } |
| |
| myLastPoint = dtde.getLocation(); |
| myEditor.getDragLayer().repaint(); |
| |
| ComponentDropLocation location = myGridInsertProcessor.processDragEvent(dtde.getLocation(), myComponentDragObject); |
| ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); |
| |
| if (!location.canDrop(myComponentDragObject) || |
| (myDraggedComponentList != null && FormEditingUtil.isDropOnChild(myDraggedComponentList, location))) { |
| if (componentTree != null) { |
| componentTree.setDropTargetComponent(null); |
| } |
| dtde.rejectDrag(); |
| } |
| else { |
| if (componentTree != null) { |
| componentTree.setDropTargetComponent(location.getContainer()); |
| } |
| dtde.acceptDrag(dtde.getDropAction()); |
| } |
| } |
| catch (Exception e) { |
| LOG.error(e); |
| } |
| } |
| |
| public void dropActionChanged(DropTargetDragEvent dtde) { |
| DraggedComponentList dcl = DraggedComponentList.fromTransferable(dtde.getTransferable()); |
| if (dcl != null) { |
| setDraggingState(dcl, dtde.getDropAction() != DnDConstants.ACTION_COPY); |
| } |
| } |
| |
| public void dragExit(DropTargetEvent dte) { |
| try { |
| ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); |
| if (componentTree != null) { |
| componentTree.setDropTargetComponent(null); |
| } |
| myUseDragDelta = false; |
| if (myDraggedComponentList != null) { |
| cancelDrag(); |
| setDraggingState(myDraggedComponentList, false); |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| myDraggedComponentList = null; |
| myEditor.setDesignTimeInsets(2); |
| } |
| myDraggedComponentsCopy = null; |
| } |
| catch (Exception e) { |
| LOG.error(e); |
| } |
| } |
| |
| public void drop(final DropTargetDropEvent dtde) { |
| try { |
| ComponentTree componentTree = DesignerToolWindowManager.getInstance(myEditor).getComponentTree(); |
| if (componentTree != null) { |
| componentTree.setDropTargetComponent(null); |
| } |
| |
| |
| final DraggedComponentList dcl = DraggedComponentList.fromTransferable(dtde.getTransferable()); |
| if (dcl != null) { |
| CommandProcessor.getInstance().executeCommand(myEditor.getProject(), |
| new Runnable() { |
| public void run() { |
| if (processDrop(dcl, dtde.getLocation(), dtde.getDropAction())) { |
| myEditor.refreshAndSave(true); |
| } |
| } |
| }, UIDesignerBundle.message("command.drop.components"), null); |
| } |
| else { |
| ComponentItem componentItem = SimpleTransferable.getData(dtde.getTransferable(), ComponentItem.class); |
| if (componentItem != null) { |
| myEditor.getMainProcessor().setInsertFeedbackEnabled(false); |
| new InsertComponentProcessor(myEditor).processComponentInsert(dtde.getLocation(), componentItem); |
| ApplicationManager.getApplication().invokeLater(new Runnable() { |
| public void run() { |
| PaletteToolWindowManager.getInstance(myEditor).clearActiveItem(); |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| myEditor.getLayeredPane().setCursor(null); |
| myEditor.getGlassLayer().requestFocus(); |
| myEditor.getMainProcessor().setInsertFeedbackEnabled(true); |
| } |
| }); |
| } |
| } |
| myDraggedComponentsCopy = null; |
| myEditor.repaintLayeredPane(); |
| } |
| catch (Exception e) { |
| LOG.error(e); |
| } |
| } |
| |
| private boolean processDrop(final DraggedComponentList dcl, final Point dropPoint, final int dropAction) { |
| myEditor.getActiveDecorationLayer().removeFeedback(); |
| final int dropX = dropPoint.x; |
| final int dropY = dropPoint.y; |
| final ArrayList<RadComponent> dclComponents = dcl.getComponents(); |
| final int componentCount = dclComponents.size(); |
| ComponentDropLocation location = GridInsertProcessor.getDropLocation(myEditor.getRootContainer(), dropPoint); |
| if (FormEditingUtil.isDropOnChild(dcl, location)) { |
| setDraggingState(dcl, false); |
| return false; |
| } |
| if (!location.canDrop(dcl)) { |
| setDraggingState(dcl, false); |
| return false; |
| } |
| |
| if (!myEditor.ensureEditable()) { |
| setDraggingState(dcl, false); |
| return false; |
| } |
| |
| List<RadComponent> droppedComponents; |
| |
| RadContainer[] originalParents = dcl.getOriginalParents(); |
| |
| cancelDrag(); |
| if (dropAction == DnDConstants.ACTION_COPY) { |
| setDraggingState(dcl, false); |
| droppedComponents = myDraggedComponentsCopy; |
| if (droppedComponents == null) { |
| return false; |
| } |
| } |
| else { |
| for(int i=0; i<dclComponents.size(); i++) { |
| LOG.info("Removing component " + dclComponents.get(i).getId() + " with constraints " + dcl.getOriginalConstraints() [i]); |
| originalParents [i].removeComponent(dclComponents.get(i)); |
| } |
| droppedComponents = dclComponents; |
| } |
| |
| final int[] dx = new int[componentCount]; |
| final int[] dy = new int[componentCount]; |
| for (int i = 0; i < componentCount; i++) { |
| final RadComponent component = myDraggedComponentsCopy.get(i); |
| dx[i] = component.getX() - dropX; |
| dy[i] = component.getY() - dropY; |
| } |
| |
| final RadComponent[] components = droppedComponents.toArray(new RadComponent[componentCount]); |
| final GridConstraints[] originalConstraints = dcl.getOriginalConstraints(); |
| |
| location.processDrop(myEditor, components, originalConstraints, dcl); |
| |
| if (dropAction == DnDConstants.ACTION_COPY) { |
| for (RadComponent component : droppedComponents) { |
| InsertComponentProcessor.createBindingWhenDrop(myEditor, component, false); |
| } |
| FormEditingUtil.selectComponents(myEditor, droppedComponents); |
| } |
| else { |
| setDraggingState(dcl, false); |
| } |
| |
| for (int i = 0; i < originalConstraints.length; i++) { |
| if (originalParents[i].getLayoutManager().isGrid()) { |
| FormEditingUtil.deleteEmptyGridCells(originalParents[i], originalConstraints[i]); |
| } |
| } |
| return true; |
| } |
| |
| private void cancelDrag() { |
| if (myDraggedComponentsCopy != null) { |
| for(RadComponent c: myDraggedComponentsCopy) { |
| myEditor.getDragLayer().remove(c.getDelegee()); |
| } |
| } |
| myEditor.refresh(); |
| } |
| |
| private static void setDraggingState(final DraggedComponentList draggedComponentList, final boolean dragging) { |
| for (RadComponent c: draggedComponentList.getComponents()) { |
| c.setDragBorder(dragging); |
| } |
| } |
| |
| public void setUseDragDelta(final boolean useDragDelta) { |
| myUseDragDelta = useDragDelta; |
| } |
| } |