blob: f3ddc85e928027853930d413d9a2021c6835540c [file] [log] [blame]
/*
* 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;
}
}