/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.ie.view.controller.dnd; import java.awt.Point; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JComponent; import org.openflexo.components.browser.BrowserElement; import org.openflexo.components.browser.ie.ReusableComponentDefinitionElement; import org.openflexo.foundation.ie.IEObject; import org.openflexo.foundation.ie.IEReusableComponent; import org.openflexo.foundation.ie.IETabComponent; import org.openflexo.foundation.ie.IEWOComponent; import org.openflexo.foundation.ie.action.DropIEElement; import org.openflexo.foundation.ie.action.DropPartialComponent; import org.openflexo.foundation.ie.action.MoveIEElement; import org.openflexo.foundation.ie.cl.ReusableComponentDefinition; import org.openflexo.foundation.ie.widget.IEBlocWidget; import org.openflexo.foundation.ie.widget.IEButtonWidget; import org.openflexo.foundation.ie.widget.IECustomButtonWidget; import org.openflexo.foundation.ie.widget.IEHTMLTableWidget; import org.openflexo.foundation.ie.widget.IEHyperlinkWidget; import org.openflexo.foundation.ie.widget.IEReusableWidget; import org.openflexo.foundation.ie.widget.IESequenceButton; import org.openflexo.foundation.ie.widget.IESequenceTD; import org.openflexo.foundation.ie.widget.IESequenceTR; import org.openflexo.foundation.ie.widget.IESequenceTab; import org.openflexo.foundation.ie.widget.IESequenceWidget; import org.openflexo.foundation.ie.widget.IETDWidget; import org.openflexo.foundation.ie.widget.IETRWidget; import org.openflexo.foundation.ie.widget.IETabWidget; import org.openflexo.foundation.ie.widget.IEWidget; import org.openflexo.foundation.ie.widget.ITableData; import org.openflexo.foundation.ie.widget.ITableRow; import org.openflexo.foundation.ie.widget.InnerBlocReusableWidget; import org.openflexo.foundation.ie.widget.TopComponentReusableWidget; import org.openflexo.ie.view.DropZoneTopComponent; import org.openflexo.ie.view.IEContainer; import org.openflexo.ie.view.controller.IEController; import org.openflexo.ie.view.palette.IEDSWidget; import org.openflexo.ie.view.widget.ButtonPanel; import org.openflexo.ie.view.widget.DropTabZone; import org.openflexo.ie.view.widget.DropTableZone; import org.openflexo.ie.view.widget.IEBlocWidgetView; import org.openflexo.ie.view.widget.IESequenceWidgetWidgetView; /** * IEDTListener a listener that tracks the state of the operation * * @see java.awt.dnd.DropTargetListener * @see java.awt.dnd.DropTarget */ public class IEDTListener implements DropTargetListener { private static final boolean USE_FLEXO_ACTION = true; private static final Logger logger = Logger.getLogger(IEDTListener.class.getPackage().getName()); public static boolean isValidDropTargetContainer(IEWidget container, IEWidget widget) { if (widget == null) { return false; } // All the following are not movable if (widget instanceof IETRWidget || widget instanceof IESequenceTR || widget instanceof IETDWidget || widget instanceof IESequenceTD || widget instanceof IESequenceButton) { return false; } boolean ok = isValidTargetClassForDropTargetContainer(container, widget.getClass(), widget.isTopComponent()); if (ok) { ok = !widget.isParentOf(container); } if (ok) { if (/*container.getWOComponent()!=widget.getWOComponent() && */container.getWOComponent() instanceof IEReusableComponent) { ok &= !widget.checkWidgetDoesNotEmbedWOComponent((IEReusableComponent) container.getWOComponent()); } } return ok; } public static boolean isValidTargetClassForDropTargetContainer(IEWidget container, Class cls, boolean isTopComponent) { if (cls == IETRWidget.class || cls == IESequenceTR.class || cls == IETDWidget.class || cls == IESequenceTD.class || cls == IESequenceButton.class) { return false; } if (cls == IESequenceTab.class && container.getWOComponent() instanceof IETabComponent) { return false; } if (container instanceof IESequenceWidget && ((IESequenceWidget) container).isTopComponent()) { return cls == IEBlocWidget.class || cls == IESequenceTab.class || cls == IEHTMLTableWidget.class || cls == TopComponentReusableWidget.class && !container.getWOComponent().hasTabContainer() || cls == IESequenceTR.class || cls == IESequenceWidget.class && isTopComponent; } else if (container instanceof IESequenceWidget || container instanceof IETDWidget) { return true; } if (container instanceof IESequenceButton || container instanceof IEBlocWidget || container instanceof IESequenceTab) { if (cls.equals(IEButtonWidget.class) || cls.equals(IEHyperlinkWidget.class) || cls.equals(IECustomButtonWidget.class)) { return true; } } if (container instanceof IESequenceTab && ((IESequenceTab) container).isRoot()) { return cls.equals(IETabWidget.class); } if (container instanceof IEBlocWidget) { return (cls.equals(IEHTMLTableWidget.class) || cls.equals(InnerBlocReusableWidget.class)) && ((IEBlocWidget) container).getContent() == null; } return false; } /* public static boolean isValidDropTargetContainer(IEContainer container, IEWidget widget) { if (widget == null) return false; boolean ok = isValidTargetClassForDropTargetContainer(container, widget.getClass(), widget.isTopComponent()); if (ok) { if (container.getContainerModel() instanceof IEWidget) { ok = !widget.isParentOf((IEWidget) container .getContainerModel()); } } if (ok) { if (/*container.getWOComponent()!=widget.getWOComponent() && *//*container.getWOComponent() instanceof IEReusableComponent) { ok&=!widget.checkWidgetDoesNotEmbedWOComponent((IEReusableComponent) container.getWOComponent()); } } return ok; } public static boolean isValidTargetClassForDropTargetContainer( IEContainer container, Class cls, boolean isTopComponent) { if(cls.equals(IESequenceTab.class) && (container.getWOComponent() instanceof IETabComponent)) return false; if (container instanceof DropZoneTopComponent) { return cls.equals(IEBlocWidget.class) || (cls.equals(IESequenceTab.class)) || cls.equals(IEHTMLTableWidget.class) || (cls.equals(TopComponentReusableWidget.class) && !((DropZoneTopComponent) container) .getModel().getComponentDefinition() .getWOComponent().hasTabContainer()) || cls.equals(IESequenceTR.class) || (cls.equals(IESequenceWidget.class) && isTopComponent); } else if (container instanceof IESequenceWidgetWidgetView) { return true; } else if (container instanceof DropTabZone) { return cls.equals(IETabWidget.class); } else if (container instanceof DropTableZone) { return (cls.equals(IEHTMLTableWidget.class) || cls .equals(InnerBlocReusableWidget.class)) && (((DropTableZone) container).getBlocModel().getContent() == null); } else if (container instanceof ButtonPanel || container instanceof IEBlocWidgetView) { return (cls.equals(IEButtonWidget.class) || cls .equals(IEHyperlinkWidget.class) || cls.equals(IECustomButtonWidget.class)); } return false; } */ private int acceptableActions = DnDConstants.ACTION_COPY_OR_MOVE; private IEContainer _dropContainer; private IEObject _dropContainerModel; private IEController _ieController; public IEDTListener(IEController ieController, IEContainer flexoDropPanel, IEObject model) { super(); _ieController = ieController; _dropContainer = flexoDropPanel; _dropContainerModel = model; } /** * Called by isDragOk Checks to see if the flavor drag flavor is acceptable * * @param e * the DropTargetDragEvent object * @return whether the flavor is acceptable */ private boolean isDragFlavorSupported(DropTargetDragEvent e) { boolean ok = false; if (e.isDataFlavorSupported(WidgetTransferable.widgetFlavor())) { ok = true; } if (e.isDataFlavorSupported(WidgetMovable.widgetFlavor())) { ok = true; } return ok; } /** * Called by dragEnter and dragOver Checks the flavors and operations * * @param e * the event object * @return whether the flavor and operation is ok */ private boolean isDragOk(DropTargetDragEvent e) { int da = e.getDropAction(); // we're saying that these actions are necessary if ((da & acceptableActions) == 0) { return false; } return true; } /** * start "drag under" feedback on component invoke acceptDrag or rejectDrag based on isDragOk * * @param e */ @Override public void dragEnter(DropTargetDragEvent e) { _ieController.setCurrentlyDroppingTarget(_dropContainer); } /** * continue "drag under" feedback on component invoke acceptDrag or rejectDrag based on isDragOk * * @param e */ @Override public void dragOver(DropTargetDragEvent e) { if (isDragOk(e) == false) { e.rejectDrag(); return; } e.acceptDrag(e.getDropAction()); } @Override public void dropActionChanged(DropTargetDragEvent e) { if (isDragOk(e) == false) { e.rejectDrag(); return; } e.acceptDrag(e.getDropAction()); } @Override public void dragExit(DropTargetEvent e) { // interface } /** * perform action from getSourceActions on the transferrable invoke acceptDrop or rejectDrop invoke dropComplete if its a local (same * JVM) transfer, use StringTransferable.localStringFlavor find a match for the flavor check the operation get the transferable * according to the chosen flavor do the transfer * * @param e */ @Override public void drop(DropTargetDropEvent e) { Object data = null; try { Transferable tr = e.getTransferable(); DataFlavor[] flavors = tr.getTransferDataFlavors(); for (int i = 0; i < flavors.length; i++) { if (tr.isDataFlavorSupported(flavors[i])) { data = e.getTransferable().getTransferData(flavors[i]); } } } catch (Exception e1) { e1.printStackTrace(); e.rejectDrop(); } try { if (data == null) { throw new NullPointerException(); } } catch (Throwable t) { t.printStackTrace(); e.dropComplete(false); return; } if (logger.isLoggable(Level.FINE)) { logger.fine("Drop with data :" + data.getClass()); } if (data instanceof TransferedWidget) { if (logger.isLoggable(Level.FINE)) { logger.fine("DATA instance of TransferedWidget"); } try { Point position = e.getLocation(); if (position.x < 0 || position.y < 0) { if (logger.isLoggable(Level.INFO)) { logger.info("Invalid position"); } e.rejectDrop(); return; } IEDSWidget droppedWidget = ((TransferedWidget) data).getWidget(); IEWidget newWidget = null; newWidget = droppedWidget.getWidget(_dropContainer.getWOComponent().getComponentDefinition()); Class targetClass = droppedWidget.getTargetClassModel(); if (targetClass.equals(IEReusableWidget.class)) { } else if (!/*isValidTargetClassForDropTargetContainer( _dropContainer, droppedWidget.getTargetClassModel())*/isValidDropTargetContainer( _dropContainer.getContainerModel(), newWidget)) { e.rejectDrop(); if (logger.isLoggable(Level.INFO)) { logger.info("Invalid target class:" + droppedWidget.getTargetClassModel() + " for container:" + _dropContainer.getClass()); } return; } DropIEElement dropAction = DropIEElement.actionType.makeNewAction(_dropContainerModel, null, _ieController.getEditor()); dropAction.setUpdateDates(_ieController.currentPaletteIsBasicPalette()); dropAction.setDroppedWidget(newWidget); if (_dropContainer instanceof DropZoneTopComponent) { dropAction.setIndex(((DropZoneTopComponent) _dropContainer).findInsertionIndex(position.x, position.y)); } if (_dropContainer instanceof ButtonPanel) { dropAction.setIndex(((ButtonPanel) _dropContainer).findInsertionIndex(position.x)); } if (_dropContainer instanceof IESequenceWidgetWidgetView) { dropAction.setIndex(((IESequenceWidgetWidgetView) _dropContainer).findInsertionIndex(position.x, position.y)); } dropAction.doAction(); if (dropAction.hasActionExecutionSucceeded()) { e.acceptDrop(acceptableActions); ((JComponent) _dropContainer).repaint(); _ieController.getIESelectionManager().resetSelection(); _ieController.getIESelectionManager().addToSelected(newWidget); } else { e.rejectDrop(); return; } } catch (Exception ex) { if (logger.isLoggable(Level.WARNING)) { logger.warning("This should never happen! Invalid XML in node in Palete"); } ex.printStackTrace(); } } else if (data instanceof MovedWidget) { try { Point position = e.getLocation(); if (position.x < 0 || position.y < 0) { e.rejectDrop(); return; } IEWidget movedWidget = ((MovedWidget) data).getWidget(); /* * if (_dropContainer instanceof EmptyCellView && movedWidget * instanceof IETableWidget) { IEController.isDropSuccessFull = * false; e.rejectDrop(); return; } */ if (!isValidDropTargetContainer(_dropContainer.getContainerModel(), movedWidget)) { // e.dropComplete(false); e.rejectDrop(); return; } e.acceptDrop(acceptableActions); if (movedWidget != null) { if (USE_FLEXO_ACTION) { MoveIEElement moveAction = MoveIEElement.actionType.makeNewAction(_dropContainerModel, null, _ieController.getEditor()); moveAction.setMovedWidget(movedWidget); if (_dropContainer instanceof DropZoneTopComponent) { moveAction.setIndex(((DropZoneTopComponent) _dropContainer).findInsertionIndex(position.x, position.y)); } if (_dropContainer instanceof ButtonPanel) { moveAction.setIndex(((ButtonPanel) _dropContainer).findInsertionIndex(position.x)); } if (_dropContainer instanceof IESequenceWidgetWidgetView) { moveAction.setIndex(((IESequenceWidgetWidgetView) _dropContainer).findInsertionIndex(position.x, position.y)); } moveAction.doAction(); } else { movedWidget.removeFromContainer(); insertView(movedWidget, _dropContainer, position); } e.dropComplete(true); /* * if (_dropContainer instanceof EmptyCellView) { * tableContainer.findViewForModel(movedWidget); } else if * (_dropContainer instanceof IEPanel) { ((IEPanel) * _dropContainer).findViewForModel(movedWidget); } */ _ieController.getIESelectionManager().resetSelection(); _ieController.getIESelectionManager().addToSelected(movedWidget); } } catch (Exception ex) { ex.printStackTrace(); } } else if (data instanceof BrowserElement) { if (data instanceof ReusableComponentDefinitionElement) { ReusableComponentDefinition partialComponent = ((ReusableComponentDefinitionElement) data).getComponentDefinition(); DropPartialComponent dropAction = DropPartialComponent.actionType.makeNewAction(_dropContainerModel, null, _ieController.getEditor()); dropAction.setPartialComponent(partialComponent); if (_dropContainer instanceof DropZoneTopComponent) { Point position = e.getLocation(); dropAction.setIndex(((DropZoneTopComponent) _dropContainer).findInsertionIndex(position.x, position.y)); } dropAction.doAction(); if (dropAction.hasActionExecutionSucceeded()) { e.acceptDrop(acceptableActions); ((JComponent) _dropContainer).repaint(); _ieController.getIESelectionManager().resetSelection(); _ieController.getIESelectionManager().addToSelected(dropAction.getDroppedWidget()); } else { e.rejectDrop(); return; } } else { logger.warning("dropped a " + data); } } else { e.dropComplete(false); return; } } /** * * @deprecated DO IT WITH FLEXO ACTION * @param movedWidget * @param parent * @param copyFlexoID * @return */ @Deprecated public static IEWidget createModelFromMovedWidget(IEWidget movedWidget, IEObject parent, boolean copyFlexoID) { IEWOComponent component = movedWidget.getWOComponent(); if (component == null) { if (logger.isLoggable(Level.SEVERE)) { logger.severe("Could not clone widget because it has no WOComponent"); } return null; } try { component.initializeSerialization(); IEWidget returned = (IEWidget) movedWidget.cloneUsingXMLMapping(null, !copyFlexoID, component.getXMLMapping()); returned.setParent(parent); if (parent instanceof IEWOComponent) { returned.setWOComponent((IEWOComponent) parent); } else if (parent instanceof IEWidget) { returned.setWOComponent(((IEWidget) parent).getWOComponent()); } else { returned.setWOComponent(movedWidget.getWOComponent()); } return returned; } catch (Exception e) { e.printStackTrace(); } finally { component.finalizeSerialization(); } return null; } /** * * @deprecated DO IT WITH FLEXO ACTION * @param model * @param container * @param position */ @Deprecated public static void insertView(IEWidget model, IEContainer container, Point position) { if (model instanceof ITableRow || model instanceof ITableData || model == null) { return; } if (container instanceof DropTableZone && model instanceof IEHTMLTableWidget) { ((DropTableZone) container).add((IEHTMLTableWidget) model); if (logger.isLoggable(Level.INFO)) { logger.info("insert HTMLTable in DropTableZone"); } container.validate(); } if (container instanceof ButtonPanel && model instanceof IEHyperlinkWidget) { int i = ((ButtonPanel) container).findInsertionIndex(position.x); ((ButtonPanel) container).getButtonedWidgetModel().insertButtonAtIndex((IEHyperlinkWidget) model, i); container.validate(); } if (container instanceof IEBlocWidgetView && model instanceof IEHyperlinkWidget) { ((IEBlocWidgetView) container).getModel().insertButtonAtIndex((IEHyperlinkWidget) model, Integer.MAX_VALUE); // We use Max value to insert at the end of the sequence container.validate(); } if (container instanceof DropTabZone && model instanceof IETabWidget) { ((DropTabZone) container).getTabModel().addToInnerWidgets((IETabWidget) model); container.validate(); } if (container instanceof IESequenceWidgetWidgetView) { int i = ((IESequenceWidgetWidgetView) container).findInsertionIndex(position.x, position.y); if (model instanceof IETDWidget) { IESequenceWidget seq = ((IETDWidget) model).getSequenceWidget(); for (int j = seq.size() - 1; j > -1; j--) { model = seq.get(j); model.setIndex(i); ((IESequenceWidgetWidgetView) container).getSequenceModel().insertElementAt(model, i); } } else if (model instanceof IESequenceWidget && ((IESequenceWidget) model).getOperator() == null) { IESequenceWidget seq = (IESequenceWidget) model; for (int j = seq.size() - 1; j > -1; j--) { model = seq.get(j); model.setIndex(i); ((IESequenceWidgetWidgetView) container).getSequenceModel().insertElementAt(model, i); } } else { model.setIndex(i); ((IESequenceWidgetWidgetView) container).getSequenceModel().insertElementAt(model, i); } container.validate(); } } }