/* * (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.fib.editor.controller; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Point; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragGestureRecognizer; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceContext; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.event.MouseListener; import java.util.Hashtable; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JComponent; import javax.swing.JOptionPane; import org.openflexo.fib.FIBLibrary; import org.openflexo.fib.controller.FIBController; import org.openflexo.fib.editor.FIBAbstractEditor; import org.openflexo.fib.editor.view.FIBEditableViewDelegate.FIBDropTarget; import org.openflexo.fib.model.ComponentConstraints; import org.openflexo.fib.model.FIBComponent; import org.openflexo.fib.model.FIBContainer; import org.openflexo.fib.model.FIBPanel; import org.openflexo.fib.model.FIBPanel.Layout; import org.openflexo.fib.model.FIBTab; import org.openflexo.fib.model.FIBTabPanel; import org.openflexo.fib.view.FIBView; import org.openflexo.logging.FlexoLogger; import org.openflexo.xmlcode.Cloner; public class PaletteElement implements FIBDraggable /*implements Transferable*/{ static final Logger logger = FlexoLogger.getLogger(PaletteElement.class.getPackage().getName()); private final FIBEditorPalette _palette; private FIBComponent modelComponent; private FIBComponent representationComponent; private FIBView view; private DragSource dragSource; private DragGestureListener dgListener; private DragSourceListener dsListener; private int dragAction = DnDConstants.ACTION_COPY; private Hashtable<JComponent, DragGestureRecognizer> dgr; // private static final DataFlavor DATA_FLAVOR = new DataFlavor(PaletteElement.class, "PaletteElement"); public PaletteElement(FIBComponent modelComponent, FIBComponent representationComponent, FIBEditorPalette palette) { this.modelComponent = modelComponent; this.representationComponent = representationComponent; _palette = palette; int x = Integer.parseInt(representationComponent.getParameter("x")); int y = Integer.parseInt(representationComponent.getParameter("y")); view = FIBController.makeView(representationComponent, FIBAbstractEditor.LOCALIZATION); Dimension size = view.getJComponent().getPreferredSize(); view.getJComponent().setBounds(x, y, size.width, size.height); this.dgListener = new DGListener(); this.dragSource = DragSource.getDefaultDragSource(); this.dsListener = new DSListener(); recursivelyRemoveFocusableProperty(view.getJComponent()); dgr = new Hashtable<JComponent, DragGestureRecognizer>(); // component, action, listener // dgr = dragSource.createDefaultDragGestureRecognizer(view.getJComponent(), dragAction, dgListener); recursivelyAddDGR(view.getJComponent()); enableDragging(); } private void recursivelyRemoveFocusableProperty(JComponent c) { c.setRequestFocusEnabled(false); c.setFocusable(false); if (c instanceof Container) { for (Component c2 : ((Container) c).getComponents()) { if (c2 instanceof JComponent) { recursivelyRemoveFocusableProperty((JComponent) c2); } } } } private void recursivelyAddDGR(JComponent c) { for (MouseListener ml : c.getMouseListeners()) { c.removeMouseListener(ml); } DragGestureRecognizer newDGR = dragSource.createDefaultDragGestureRecognizer(c, dragAction, dgListener); dgr.put(c, newDGR); if (c instanceof Container) { for (Component c2 : ((Container) c).getComponents()) { if (c2 instanceof JComponent) { recursivelyAddDGR((JComponent) c2); } } } } public FIBView getView() { return view; } @Override public void enableDragging() { for (JComponent j : dgr.keySet()) { dgr.get(j).setComponent(j); } } @Override public void disableDragging() { for (JComponent j : dgr.keySet()) { dgr.get(j).setComponent(null); } } @Override public boolean acceptDragging(FIBDropTarget target) { logger.fine("acceptDragging ? for component: " + target.getFIBComponent() + " place holder: " + target.getPlaceHolder()); return true; } /*@Override public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[] { DATA_FLAVOR }; } @Override public boolean isDataFlavorSupported(DataFlavor flavor) { return true; } @Override public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { return this; }*/ @Override public boolean elementDragged(FIBDropTarget target, Point pt) { logger.info("Element dragged with component: " + target.getFIBComponent() + " place holder: " + target.getPlaceHolder()); boolean isTabInsertion = modelComponent instanceof FIBPanel && target.getFIBComponent() instanceof FIBTabPanel; if (!isTabInsertion && target.getPlaceHolder() == null) { boolean deleteIt = JOptionPane.showConfirmDialog(_palette.getEditorController().getEditor().getFrame(), target.getFIBComponent() + ": really delete this component (undoable operation) ?", "information", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.YES_OPTION; if (!deleteIt) { return false; } } FIBComponent newComponent = (FIBComponent) Cloner.cloneObjectWithMapping(modelComponent, FIBLibrary.getFIBMapping()); newComponent.setLocalizedDictionary(null); newComponent.clearParameters(); try { if (!isTabInsertion && target.getPlaceHolder() != null) { target.getPlaceHolder().willDelete(); target.getPlaceHolder().insertComponent(newComponent); target.getPlaceHolder().hasDeleted(); return true; } else { FIBComponent targetComponent = target.getFIBComponent(); FIBContainer containerComponent = targetComponent.getParent(); if (containerComponent == null) { return false; } if (targetComponent instanceof FIBTab && !(newComponent instanceof FIBPanel)) { return false; } if (isTabInsertion) { // Special case where a new tab is added to a FIBTabPanel FIBTab newTabComponent = new FIBTab(); newTabComponent.setLayout(Layout.border); newTabComponent.setTitle("NewTab"); newTabComponent.finalizeDeserialization(); ((FIBTabPanel) targetComponent).addToSubComponents(newTabComponent); return true; } else { // Normal case, we replace targetComponent by newComponent ComponentConstraints constraints = targetComponent.getConstraints(); containerComponent.removeFromSubComponentsNoNotification(targetComponent); // No notification, we will do it later, to avoid reindexing targetComponent.delete(); containerComponent.addToSubComponents(newComponent, constraints); return true; } } } catch (Exception e) { e.printStackTrace(); logger.warning("Unexpected exception: " + e); return false; } } /** * DGListener a listener that will start the drag. has access to top level's dsListener and dragSource * * @see java.awt.dnd.DragGestureListener * @see java.awt.dnd.DragSource * @see java.awt.datatransfer.StringSelection */ class DGListener implements DragGestureListener { /** * Start the drag if the operation is ok. uses java.awt.datatransfer.StringSelection to transfer the label's data * * @param e * the event object */ @Override public void dragGestureRecognized(DragGestureEvent e) { logger.fine("dragGestureRecognized"); // if the action is ok we go ahead // otherwise we punt if ((e.getDragAction() & dragAction) == 0) { return; // get the label's text and put it inside a Transferable // Transferable transferable = new StringSelection( // DragLabel.this.getText() ); } PaletteElementDrag transferable = new PaletteElementDrag(PaletteElement.this, e.getDragOrigin()); try { // initial cursor, transferrable, dsource listener e.startDrag(FIBEditorPalette.dropKO, transferable, dsListener); FIBEditorPalette.logger.info("Starting drag for " + _palette); // getDrawingView().captureDraggedNode(PaletteElementView.this, e); } catch (Exception idoe) { idoe.printStackTrace(); FIBEditorPalette.logger.warning("Unexpected exception " + idoe); } } } /** * DSListener a listener that will track the state of the DnD operation * * @see java.awt.dnd.DragSourceListener * @see java.awt.dnd.DragSource * @see java.awt.datatransfer.StringSelection */ public class DSListener implements DragSourceListener { /** * @param e * the event */ @Override public void dragDropEnd(DragSourceDropEvent e) { // getDrawingView().resetCapturedNode(); if (e.getDropSuccess() == false) { if (FIBEditorPalette.logger.isLoggable(Level.INFO)) { FIBEditorPalette.logger.info("Dropping was not successful"); } return; } /* * the dropAction should be what the drop target specified in * acceptDrop */ // this is the action selected by the drop target if (e.getDropAction() == DnDConstants.ACTION_MOVE) { System.out.println("Coucou, que se passe-t-il par ici ?"); } } /** * @param e * the event */ @Override public void dragEnter(DragSourceDragEvent e) { DragSourceContext context = e.getDragSourceContext(); // System.out.println("dragEnter() with "+context+" component="+e.getSource()); // intersection of the users selected action, and the source and // target actions int myaction = e.getDropAction(); if ((myaction & dragAction) != 0) { context.setCursor(DragSource.DefaultCopyDrop); } else { context.setCursor(DragSource.DefaultCopyNoDrop); } } /** * @param e * the event */ @Override public void dragOver(DragSourceDragEvent e) { // interface // System.out.println("dragOver() with "+context+" component="+e.getSource()); } /** * @param e * the event */ @Override public void dragExit(DragSourceEvent e) { // System.out.println("dragExit() with "+context+" component="+e.getSource()); // interface } /** * for example, press shift during drag to change to a link action * * @param e * the event */ @Override public void dropActionChanged(DragSourceDragEvent e) { DragSourceContext context = e.getDragSourceContext(); context.setCursor(DragSource.DefaultCopyNoDrop); } } }