/** * */ package net.sf.nmedit.jtheme.component.plaf.mcui; import java.awt.Component; import java.awt.Point; import java.awt.datatransfer.Clipboard; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import net.sf.nmedit.jpatch.PModule; import net.sf.nmedit.jpatch.PModuleContainer; import net.sf.nmedit.jpatch.PPatch; import net.sf.nmedit.jpatch.PatchUtils; import net.sf.nmedit.jpatch.dnd.PModuleTransferDataWrapper; import net.sf.nmedit.jpatch.history.PUndoableEditSupport; import net.sf.nmedit.jtheme.cable.JTCableManager; import net.sf.nmedit.jtheme.component.JTModule; import net.sf.nmedit.jtheme.component.JTModuleContainer; import net.sf.nmedit.jtheme.util.ModuleImageRenderer; public class ContainerAction extends AbstractAction { /** * */ private JTModuleContainer jmc; /** * */ private static final long serialVersionUID = 7135918324094843867L; public static final String DELETE_UNUSED = "delete.unused"; public static final String DELETE = "delete"; public static final String SELECT_ALL = "selectAll"; public static final String COPY = "copy"; public static final String PASTE = "paste"; public static final String CUT = "cut"; public static final String SHAKE = "Shake"; public static final String ABORT_PASTE = "abortPaste"; private Clipboard clipBoard = null; public ContainerAction(JTModuleContainer moduleContainer, String command) { this(moduleContainer, command, null); } public ContainerAction(JTModuleContainer moduleContainer, String command, Clipboard clipBoard) { this.clipBoard = clipBoard; this.jmc = moduleContainer; putValue(ACTION_COMMAND_KEY, command); if (command == DELETE_UNUSED) { putValue(NAME, "Delete Unused Modules"); } else if (command == DELETE) { putValue(NAME, "Delete"); } else if (command == SHAKE) { JTCableManager cm = jmc.getCableManager(); setEnabled(cm != null); putValue(NAME, "Shake"); } else { putValue(NAME, command); } } protected PModuleContainer getTarget() { return this.jmc.getModuleContainer(); } public void actionPerformed(ActionEvent e) { if (isEnabled()) { Object key = getValue(ACTION_COMMAND_KEY); if (key==DELETE_UNUSED) { deleteUnusedModules(); } else if (key == SELECT_ALL) { if (jmc != null) { for (JTModule module : jmc.getModules()) jmc.addSelection(module); } } else if (key == DELETE) { delete(); } else if (key == COPY) { if (getClipBoard() != null) copy(); } else if (key == PASTE) { if (getClipBoard() != null) paste(); } else if (key == CUT) { if (getClipBoard() != null) cut(); } else if (key == ABORT_PASTE) { jmc.getUI().abortPaste(); } else if (key == SHAKE) { JTCableManager cm = jmc.getCableManager(); if (cm != null) cm.shake(); } } } private void delete() { Component[] components = jmc.getComponents(); if (components.length>0) { /* Get UndoableEditSupport from any component in JPatch * (in this case from PModuleContainer). * ues may be null, usually when there is no undo support. */ PUndoableEditSupport ues = jmc.getModuleContainer().getEditSupport(); /* didBeginUpdate flag is used to determine if we called * ues.beginUpdate() this when actially an edit happened. */ boolean didBeginUpdate = false; try { for (JTModule mm : jmc.getModules()) { if (mm.isSelected()) { /* Module mm is selected, thus we do an edit * and if not done already call ues.beginUpdate() * (=>didBeginUpdate). ues still might be null. * The beginUpdate() call causes that all * edits until the next endUpdate() are collected * into a single undo event. */ if ((!didBeginUpdate) && ues != null) { // begin update if (jmc.getModules().size() > 1) ues.beginUpdate("delete modules"); else ues.beginUpdate(); // Set beginUpdate flag. Important !!! didBeginUpdate = true; } removeModule(mm); } } // after the remove we have to update the container jmc.revalidate(); // revalidates the bounds of the container jmc.repaint(); // repaint } finally { if (didBeginUpdate && ues != null) { /* Only if ues.beginUpdate() was called we * do the endUpdate(). The try/finally statements * ensures the endUpdate() is called, even if * an exception occures. This is very important * since otherwise an exception would cause the * undo manager to enter an invalid state from * which it will 'never' recover. */ ues.endUpdate(); } } } } public boolean isEnabled(Object sender) { Object key = getValue(ACTION_COMMAND_KEY); if (key==DELETE_UNUSED) { PModuleContainer t = getTarget(); return t != null && PatchUtils.hasUnusedModules(t); } else if (key == DELETE) { if (sender != null && (sender instanceof JTModule) && !((JTModule)sender).isEnabled()) return false; else return true; } else if (key == SELECT_ALL) { return true; } else { return true; } } private void deleteUnusedModules() { PModuleContainer mc = getTarget(); if (mc != null) { PUndoableEditSupport ues = mc.getEditSupport(); try { if (ues != null) ues.beginUpdate("delete unused modules"); while (PatchUtils.removeUnusedModules(mc)>0); } finally { if (ues != null) ues.endUpdate(); } } } private boolean removeModule(JTModule m) { PModule nm = m.getModule(); if (nm != null && nm.getParentComponent() != null) { return nm.getParentComponent().remove(nm); } return false; } public void setClipBoard(Clipboard clipBoard) { this.clipBoard = clipBoard; } public Clipboard getClipBoard() { return clipBoard; } private void cut() { copy(); delete(); } private void paste() { Transferable t = getClipBoard().getContents(this); if (t instanceof PModuleTransferDataWrapper) { PModuleTransferDataWrapper tdata = (PModuleTransferDataWrapper)t; jmc.getUI().startPaste(tdata); } } private void copy() { PPatch newPatch = jmc.getModuleContainer().createPatchWithModules(jmc.getSelectedPModules()); PModuleContainer newMc = null; for (int i = 0; i < newPatch.getModuleContainerCount(); i++) { newMc = newPatch.getModuleContainer(i); if (newMc.getModuleCount() > 0) break; } if (newMc == null) return; PModuleTransferDataWrapper tdata =new PModuleTransferDataWrapper(newMc, newMc.getModules(), new Point(5, 5)); ModuleImageRenderer mir = new ModuleImageRenderer(jmc.getSelectedModules()); mir.setForDragAndDrop(true); mir.setPaintExtraBorder(true); tdata.setTransferImage(mir.render()); getClipBoard().setContents(tdata, null); } }