/* * Copyright (C) 2007, 2010 IsmAvatar <IsmAvatar@gmail.com> * Copyright (C) 2007, 2008 Clam <clamisgood@gmail.com> * Copyright (C) 2007, 2008, 2009 Quadduc <quadduc@gmail.com> * * This file is part of LateralGM. * LateralGM is free software and comes with ABSOLUTELY NO WARRANTY. * See LICENSE for details. */ package org.lateralgm.subframes; import static java.lang.Integer.MAX_VALUE; import static javax.swing.GroupLayout.DEFAULT_SIZE; import static javax.swing.GroupLayout.PREFERRED_SIZE; import static org.lateralgm.main.Util.deRef; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Insets; import java.awt.Point; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import javax.swing.BorderFactory; import javax.swing.DropMode; import javax.swing.GroupLayout; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.GroupLayout.Alignment; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import org.lateralgm.compare.ResourceComparator; import org.lateralgm.components.ActionList; import org.lateralgm.components.ActionListEditor; import org.lateralgm.components.GMLTextArea; import org.lateralgm.components.NumberField; import org.lateralgm.components.ResourceMenu; import org.lateralgm.components.impl.EventNode; import org.lateralgm.components.impl.ResNode; import org.lateralgm.main.LGM; import org.lateralgm.main.Listener; import org.lateralgm.messages.Messages; import org.lateralgm.resources.GmObject; import org.lateralgm.resources.Resource; import org.lateralgm.resources.ResourceReference; import org.lateralgm.resources.Sprite; import org.lateralgm.resources.GmObject.PGmObject; import org.lateralgm.resources.GmObject.ParentLoopException; import org.lateralgm.resources.sub.Argument; import org.lateralgm.resources.sub.Event; import org.lateralgm.resources.sub.MainEvent; import com.sun.corba.se.spi.orbutil.fsm.Action; public class GmObjectFrame extends ResourceFrame<GmObject,PGmObject> implements ActionListener, TreeSelectionListener { private static final long serialVersionUID = 1L; private static final ImageIcon INFO_ICON = LGM.getIconForKey("GmObjectFrame.INFO"); //$NON-NLS-1$ public ResourceMenu<Sprite> sprite; public JButton newSprite; public JButton editSprite; public JCheckBox visible; public JCheckBox solid; public NumberField depth; public JCheckBox persistent; public ResourceMenu<GmObject> parent; public ResourceMenu<Sprite> mask; public JButton information; public EventTree events; public JButton eventAdd; public JButton eventReplace; public JButton eventDuplicate; public JButton eventDelete; public JMenuItem eventAddItem; public JMenuItem eventReplaceItem; public JMenuItem eventDuplicateItem; public JMenuItem eventDeleteItem; public EventGroupNode rootEvent; private MListener mListener = new MListener(); public ActionList actions; public GMLTextArea code; private DefaultMutableTreeNode lastValidEventSelection; public GmObjectFrame(GmObject res, ResNode node) { super(res,node); GroupLayout layout = new GroupLayout(getContentPane()); setLayout(layout); JPanel side1 = new JPanel(); makeSide1(side1); JPanel side2 = new JPanel(new BorderLayout()); JLabel lab = new JLabel(Messages.getString("GmObjectFrame.EVENTS")); //$NON-NLS-1$ side2.add(lab,BorderLayout.NORTH); makeEventTree(res); JScrollPane scroll = new JScrollPane(events); scroll.setPreferredSize(new Dimension(140,260)); side2.add(scroll,BorderLayout.CENTER); JPanel side2bottom = new JPanel(new BorderLayout()); eventAdd = new JButton(Messages.getString("GmObjectFrame.ADD_EVENT")); //$NON-NLS-1 eventAdd.addActionListener(this); eventReplace = new JButton(Messages.getString("GmObjectFrame.REP")); //$NON-NLS-1 eventReplace.addActionListener(this); eventReplace.setToolTipText(Messages.getString("GmObjectFrame.REPLACE_EVENT")); //$NON-NLS-1$ eventReplace.setMargin(new Insets(1,7,1,7)); eventDuplicate = new JButton(Messages.getString("GmObjectFrame.DUP")); //$NON-NLS-1 eventDuplicate.addActionListener(this); eventDuplicate.setToolTipText(Messages.getString("GmObjectFrame.DUPLICATE_EVENT")); //$NON-NLS-1$ eventDuplicate.setMargin(new Insets(1,7,1,7)); eventDelete = new JButton(Messages.getString("GmObjectFrame.DELETE")); //$NON-NLS-1$ eventDelete.addActionListener(this); eventDelete.setToolTipText(Messages.getString("GmObjectFrame.DELETE_EVENT")); //$NON-NLS-1$ eventDelete.setMargin(new Insets(2,0,2,0)); side2bottom.add(eventAdd,BorderLayout.NORTH); side2bottom.add(eventReplace,BorderLayout.WEST); side2bottom.add(eventDuplicate,BorderLayout.EAST); side2bottom.add(eventDelete,BorderLayout.CENTER); side2.add(side2bottom,BorderLayout.SOUTH); JComponent editor; if (false) { //TODO code = new GMLTextArea(""); //$NON-NLS-1$ editor = new JScrollPane(code); } else { actions = new ActionList(this); editor = new ActionListEditor(actions); } layout.setHorizontalGroup(layout.createSequentialGroup() /**/.addComponent(side1,DEFAULT_SIZE,PREFERRED_SIZE,PREFERRED_SIZE) /**/.addComponent(side2) /**/.addComponent(editor)); layout.setVerticalGroup(layout.createParallelGroup() /**/.addComponent(side1) /**/.addComponent(side2) /**/.addComponent(editor)); pack(); // Select first event TreeNode event = (TreeNode) events.getModel().getRoot(); while (event.getChildCount() > 0) event = event.getChildAt(0); if (event != events.getModel().getRoot()) events.setSelectionPath(new TreePath(((DefaultMutableTreeNode) event).getPath())); } private void makeSide1(JPanel side1) { GroupLayout s1Layout = new GroupLayout(side1); s1Layout.setAutoCreateContainerGaps(true); s1Layout.setAutoCreateGaps(true); side1.setLayout(s1Layout); JLabel nLabel = new JLabel(Messages.getString("GmObjectFrame.NAME")); //$NON-NLS-1$ JPanel origin = new JPanel(); GroupLayout oLayout = new GroupLayout(origin); origin.setLayout(oLayout); origin.setBorder(BorderFactory.createTitledBorder(Messages.getString("GmObjectFrame.SPRITE"))); //$NON-NLS-1$ String t = Messages.getString("GmObjectFrame.NO_SPRITE"); //$NON-NLS-1$ sprite = new ResourceMenu<Sprite>(Resource.Kind.SPRITE,t,144); plf.make(sprite,PGmObject.SPRITE); newSprite = new JButton(Messages.getString("GmObjectFrame.NEW")); //$NON-NLS-1$ newSprite.addActionListener(this); editSprite = new JButton(Messages.getString("GmObjectFrame.EDIT")); //$NON-NLS-1$ editSprite.addActionListener(this); oLayout.setHorizontalGroup(oLayout.createSequentialGroup() /**/.addContainerGap(4,4) /**/.addGroup(oLayout.createParallelGroup() /* */.addComponent(sprite) /* */.addGroup(oLayout.createSequentialGroup() /* */.addComponent(newSprite,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE) /* */.addGap(4) /* */.addComponent(editSprite,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE))) /**/.addContainerGap(4,4)); oLayout.setVerticalGroup(oLayout.createSequentialGroup() /**/.addComponent(sprite,DEFAULT_SIZE,DEFAULT_SIZE,PREFERRED_SIZE) /**/.addGap(2) /**/.addGroup(oLayout.createParallelGroup(Alignment.BASELINE) /* */.addComponent(newSprite) /* */.addComponent(editSprite)) /**/.addContainerGap(4,4)); visible = new JCheckBox(Messages.getString("GmObjectFrame.VISIBLE")); //$NON-NLS-1$ plf.make(visible,PGmObject.VISIBLE); solid = new JCheckBox(Messages.getString("GmObjectFrame.SOLID")); //$NON-NLS-1$ plf.make(solid,PGmObject.SOLID); JLabel dLabel = new JLabel(Messages.getString("GmObjectFrame.DEPTH")); //$NON-NLS-1$ depth = new NumberField(0); plf.make(depth,PGmObject.DEPTH); persistent = new JCheckBox(Messages.getString("GmObjectFrame.PERSISTENT")); //$NON-NLS-1$ plf.make(persistent,PGmObject.PERSISTENT); JLabel pLabel = new JLabel(Messages.getString("GmObjectFrame.PARENT")); //$NON-NLS-1$ t = Messages.getString("GmObjectFrame.NO_PARENT"); //$NON-NLS-1$ parent = new ResourceMenu<GmObject>(Resource.Kind.OBJECT,t,110); plf.make(parent,PGmObject.PARENT); JLabel mLabel = new JLabel(Messages.getString("GmObjectFrame.MASK")); //$NON-NLS-1$ t = Messages.getString("GmObjectFrame.SAME_AS_SPRITE"); //$NON-NLS-1$ mask = new ResourceMenu<Sprite>(Resource.Kind.SPRITE,t,110); plf.make(mask,PGmObject.MASK); information = new JButton(Messages.getString("GmObjectFrame.INFO"),INFO_ICON); //$NON-NLS-1$ information.addActionListener(this); save.setText(Messages.getString("GmObjectFrame.SAVE")); //$NON-NLS-1$ s1Layout.setHorizontalGroup(s1Layout.createParallelGroup() /**/.addGroup(s1Layout.createSequentialGroup() /* */.addComponent(nLabel) /* */.addComponent(name,DEFAULT_SIZE,120,MAX_VALUE)) /**/.addComponent(origin) /**/.addGroup(s1Layout.createSequentialGroup() /* */.addComponent(dLabel) /* */.addComponent(depth)) /**/.addGroup(s1Layout.createParallelGroup(Alignment.LEADING) /* */.addComponent(pLabel) /* */.addComponent(mLabel)) /**/.addGroup(s1Layout.createSequentialGroup() /* */.addGroup(s1Layout.createParallelGroup(Alignment.TRAILING) /* */.addComponent(parent,DEFAULT_SIZE,120,MAX_VALUE) /* */.addComponent(mask,DEFAULT_SIZE,120,MAX_VALUE))) /**/.addGroup(s1Layout.createSequentialGroup() /* */.addComponent(visible) /* */.addComponent(solid)) /**/.addComponent(persistent) /**/.addComponent(information,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE) /**/.addComponent(save,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE)); s1Layout.setVerticalGroup(s1Layout.createSequentialGroup() /**/.addGroup(s1Layout.createParallelGroup(Alignment.BASELINE) /* */.addComponent(nLabel) /* */.addComponent(name)) /**/.addComponent(origin) /**/.addGroup(s1Layout.createParallelGroup(Alignment.BASELINE) /* */.addComponent(dLabel) /* */.addComponent(depth)) /**/.addComponent(pLabel) /**/.addGap(4) /**/.addComponent(parent,DEFAULT_SIZE,DEFAULT_SIZE,PREFERRED_SIZE) /**/.addComponent(mLabel) /**/.addGap(4) /**/.addComponent(mask,DEFAULT_SIZE,DEFAULT_SIZE,PREFERRED_SIZE) /**/.addGap(8) /**/.addGroup(s1Layout.createParallelGroup(Alignment.BASELINE) /* */.addComponent(visible) /* */.addComponent(solid)) /**/.addComponent(persistent) /**/.addGap(8,8,MAX_VALUE) /**/.addComponent(information) /**/.addComponent(save)); } public static class EventTree extends JTree { private static final long serialVersionUID = 1L; public EventTree(TreeNode n) { super(n); //otherwise, getToolTipText won't be called setToolTipText(""); //$NON-NLS-1$ } public String getToolTipText(MouseEvent e) { Point p = e.getPoint(); TreePath path = getPathForLocation(p.x,p.y); if (path == null) return null; Object c = path.getLastPathComponent(); if (c instanceof EventInstanceNode) { EventInstanceNode node = (EventInstanceNode) c; Event ev = node.getUserObject(); return Messages.format("MainEvent.EVENT_HINT" + ev.mainId,ev.toString()); //$NON-NLS-1$ } return Messages.format("MainEvent.EVENTS",c.toString()); //$NON-NLS-1$ } } private class EventNodeTransferHandler extends TransferHandler { private static final long serialVersionUID = 1L; public EventNodeTransferHandler() { super(); } protected Transferable createTransferable(JComponent c) { return null; } public int getSourceActions(JComponent c) { return NONE; } public boolean canImport(TransferHandler.TransferSupport support) { if (!support.isDataFlavorSupported(EventNode.EVENTNODE_FLAVOR)) return false; EventNode t = (EventNode) LGM.eventSelect.events.getLastSelectedPathComponent(); if (t == null || !t.isValid()) return false; if (rootEvent.contains(new Event(t.mainId,t.eventId,t.other))) return false; for (DataFlavor f : support.getDataFlavors()) if (f == EventNode.EVENTNODE_FLAVOR) return true; return false; } public boolean importData(TransferHandler.TransferSupport support) { if (!canImport(support)) return false; try { EventNode t = (EventNode) support.getTransferable().getTransferData( EventNode.EVENTNODE_FLAVOR); if (!t.isValid()) return false; Point p = support.getDropLocation().getDropPoint(); TreePath path = events.getPathForLocation(p.x,p.y); functionEvent(t.mainId,t.eventId,t.other,path); return true; } catch (Throwable e) { // This is just to stop the dnd system from silencing exceptions e.printStackTrace(); } return false; } } public static class EventInstanceNode extends DefaultMutableTreeNode implements Comparable<EventInstanceNode> { private static final long serialVersionUID = 1L; public EventInstanceNode(Event e) { super(e); } public Event getUserObject() { return (Event) super.getUserObject(); } public int compareTo(EventInstanceNode n) { return getUserObject().compareTo(n.getUserObject()); } } public class EventGroupNode extends DefaultMutableTreeNode { private static final long serialVersionUID = 1L; public int mainId; public EventGroupNode(int mainId) { super(Messages.getString("MainEvent.EVENT" + mainId)); //$NON-NLS-1$ this.mainId = mainId; } public boolean contains(Event e) { for (int i = 0; i < getChildCount(); i++) { if (getChildAt(i) instanceof EventInstanceNode) { if (((EventInstanceNode) getChildAt(i)).getUserObject().matchesType(e)) return true; } else if (((EventGroupNode) getChildAt(i)).contains(e)) return true; } return false; } @SuppressWarnings("unchecked") public void sortChildren() { // This doesn't seem to have any unwanted effects (directly sorting the protected field) Collections.sort((java.util.Vector<EventInstanceNode>) children); } public TreePath childPath(Event e) { for (int i = 0; i < getChildCount(); i++) if (getChildAt(i) instanceof EventInstanceNode && ((EventInstanceNode) getChildAt(i)).getUserObject().matchesType(e)) return new TreePath(((EventInstanceNode) getChildAt(i)).getPath()); return null; } public void select(Event e) { TreePath p = childPath(e); events.setSelectionPath(p); events.updateUI(); events.scrollPathToVisible(p); events.updateUI(); } } public void addEvent(Event e) { for (int i = 0; i < rootEvent.getChildCount(); i++) { DefaultMutableTreeNode n = (DefaultMutableTreeNode) rootEvent.getChildAt(i); if (n instanceof EventGroupNode) { EventGroupNode group = (EventGroupNode) n; if (group.mainId == e.mainId) { if (!group.contains(e)) { group.add(new EventInstanceNode(e)); group.sortChildren(); } group.select(e); return; } } else { EventInstanceNode ein = (EventInstanceNode) n; if (ein.getUserObject().mainId == e.mainId) { if (!ein.getUserObject().matchesType(e)) { EventGroupNode group = new EventGroupNode(e.mainId); int ind = rootEvent.getIndex(ein); rootEvent.remove(ind); rootEvent.insert(group,ind); group.add(ein); group.add(new EventInstanceNode(e)); group.sortChildren(); group.select(e); } else { rootEvent.select(e); } return; } } } for (int i = 0; i < rootEvent.getChildCount(); i++) { int mid; if (rootEvent.getChildAt(i) instanceof EventInstanceNode) mid = ((EventInstanceNode) rootEvent.getChildAt(i)).getUserObject().mainId; else mid = ((EventGroupNode) rootEvent.getChildAt(i)).mainId; if (mid > e.mainId) { EventInstanceNode ein = new EventInstanceNode(e); rootEvent.insert(ein,i); rootEvent.select(e); return; } } EventInstanceNode ein = new EventInstanceNode(e); rootEvent.add(ein); rootEvent.select(e); } public void removeEvent(EventInstanceNode n) { DefaultMutableTreeNode p = (DefaultMutableTreeNode) n.getParent(); DefaultMutableTreeNode next = n.getNextSibling(); if (next == null) next = n.getPreviousSibling(); if (p == rootEvent) n.removeFromParent(); else { if (p.getChildCount() < 3) //thunder { n.removeFromParent(); rootEvent.insert((DefaultMutableTreeNode) p.getChildAt(0),rootEvent.getIndex(p)); p.removeFromParent(); } else n.removeFromParent(); } if (next == null && rootEvent.getChildCount() != 0) next = (DefaultMutableTreeNode) rootEvent.getChildAt(0); if (next == null) actions.setActionContainer(null); else { TreePath path = new TreePath((next instanceof EventInstanceNode ? next : (DefaultMutableTreeNode) next.getChildAt(0)).getPath()); events.setSelectionPath(path); events.scrollPathToVisible(path); } events.updateUI(); } public void functionEvent(int mainId, int id, ResourceReference<GmObject> other, TreePath path) { if (path == null) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) events.getLastSelectedPathComponent(); path = node == null ? null : new TreePath(node.getPath()); } int func = path == null ? EventFrame.FUNCTION_ADD : LGM.eventSelect.function.getValue(); switch (func) { case EventFrame.FUNCTION_ADD: addEvent(new Event(mainId,id,other)); break; case EventFrame.FUNCTION_REPLACE: DefaultMutableTreeNode dropNode = (DefaultMutableTreeNode) path.getLastPathComponent(); if (!(dropNode instanceof EventInstanceNode)) return; EventInstanceNode drop = (EventInstanceNode) dropNode; removeEvent(drop); Event ev = drop.getUserObject(); ev.mainId = mainId; ev.id = id; ev.other = other; addEvent(ev); break; case EventFrame.FUNCTION_DUPLICATE: dropNode = (DefaultMutableTreeNode) path.getLastPathComponent(); if (!(dropNode instanceof EventInstanceNode)) return; drop = (EventInstanceNode) dropNode; ev = drop.getUserObject(); actions.save(); Event ev2 = ev.copy(); ev2.mainId = mainId; ev2.id = id; ev2.other = other; addEvent(ev2); break; } } public void makeEventTree(GmObject res) { rootEvent = new EventGroupNode(-1); for (int m = 0; m < 12; m++) { MainEvent me = res.mainEvents.get(m); ArrayList<Event> ale = me.events; if (ale.size() == 1) { rootEvent.add(new EventInstanceNode(ale.get(0))); } if (ale.size() > 1) { EventGroupNode node = new EventGroupNode(m); rootEvent.add(node); for (Event e : ale) node.add(new EventInstanceNode(e)); } } if (res.getNode().newRes) { rootEvent.add(new EventInstanceNode(new Event(MainEvent.EV_CREATE,0,null))); rootEvent.add(new EventInstanceNode(new Event(MainEvent.EV_STEP,Event.EV_STEP_NORMAL,null))); rootEvent.add(new EventInstanceNode(new Event(MainEvent.EV_DRAW,0,null))); } events = new EventTree(rootEvent); events.setScrollsOnExpand(true); events.setCellRenderer(new EventNodeRenderer()); events.setRootVisible(false); events.setShowsRootHandles(true); events.setExpandsSelectedPaths(false); events.addMouseListener(mListener); events.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); events.addTreeSelectionListener(this); if (LGM.javaVersion >= 10600) { events.setDragEnabled(true); events.setDropMode(DropMode.ON); events.setTransferHandler(new EventNodeTransferHandler()); } } public void saveEvents() { actions.save(); Enumeration<?> dfe = rootEvent.depthFirstEnumeration(); for (MainEvent me : res.mainEvents) me.events.clear(); while (dfe.hasMoreElements()) { Object o = dfe.nextElement(); if (o instanceof EventInstanceNode) { EventInstanceNode ein = (EventInstanceNode) o; if (ein.getUserObject().actions.size() > 0) { Event e = ein.getUserObject(); res.mainEvents.get(e.mainId).events.add(e); } } } } protected boolean areResourceFieldsEqual() { ResourceComparator c = new ResourceComparator(); c.addExclusions(Action.class,"updateTrigger","updateSource"); c.addExclusions(Argument.class,"updateTrigger","updateSource"); return c.areEqual(res.mainEvents,resOriginal.mainEvents); } public void commitChanges() { saveEvents(); res.setName(name.getText()); } public void actionPerformed(ActionEvent e) { if (e.getSource() == newSprite) { ResNode n = Listener.getPrimaryParent(Resource.Kind.SPRITE); Sprite spr = LGM.currentFile.sprites.add(); Listener.putNode(LGM.tree,n,n,Resource.Kind.SPRITE,n.getChildCount(),spr); res.put(PGmObject.SPRITE,spr.reference); return; } if (e.getSource() == editSprite) { Sprite spr = deRef(sprite.getSelected()); if (spr == null) return; spr.getNode().openFrame(); return; } if (e.getSource() == information) { //TODO: Object Information return; } if (e.getSource() == eventAdd || e.getSource() == eventAddItem) { LGM.eventSelect.show(); LGM.eventSelect.toTop(); LGM.eventSelect.function.setValue(EventFrame.FUNCTION_ADD); return; } if (e.getSource() == eventReplace || e.getSource() == eventReplaceItem) { LGM.eventSelect.show(); LGM.eventSelect.toTop(); LGM.eventSelect.function.setValue(EventFrame.FUNCTION_REPLACE); return; } if (e.getSource() == eventDuplicate || e.getSource() == eventDuplicateItem) { LGM.eventSelect.show(); LGM.eventSelect.toTop(); LGM.eventSelect.function.setValue(EventFrame.FUNCTION_DUPLICATE); return; } if (e.getSource() == eventDelete || e.getSource() == eventDeleteItem) { Object comp = events.getLastSelectedPathComponent(); if (!(comp instanceof EventInstanceNode)) return; removeEvent((EventInstanceNode) comp); return; } super.actionPerformed(e); } @Override public void dispose() { super.dispose(); events.removeTreeSelectionListener(this); events.setModel(null); events.setTransferHandler(null); information.removeActionListener(this); newSprite.removeActionListener(this); editSprite.removeActionListener(this); eventAdd.removeActionListener(this); eventReplace.removeActionListener(this); eventDuplicate.removeActionListener(this); eventDelete.removeActionListener(this); } public void valueChanged(TreeSelectionEvent tse) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) events.getLastSelectedPathComponent(); if (node == null || !node.isLeaf() || !(node.getUserObject() instanceof Event)) { if (node != null && !node.isLeaf()) { TreePath path = new TreePath(node.getPath()); if (events.isExpanded(path)) events.collapsePath(path); else events.expandPath(path); } if (lastValidEventSelection != null) events.setSelectionPath(new TreePath(lastValidEventSelection.getPath())); return; } lastValidEventSelection = node; actions.setActionContainer((Event) node.getUserObject()); } @Override public void exceptionThrown(Exception e) { if (e instanceof ParentLoopException) { String msg = Messages.getString("GmObjectFrame.LOOPING_PARENTS"); //$NON-NLS-1$ String ttl = Messages.getString("GmObjectFrame.ERROR"); //$NON-NLS-1$ JOptionPane.showMessageDialog(this,msg,ttl,JOptionPane.ERROR_MESSAGE); return; } super.exceptionThrown(e); } @Override public Dimension getMinimumSize() { Dimension p = getContentPane().getSize(); Dimension l = getContentPane().getMinimumSize(); Dimension s = getSize(); l.width += s.width - p.width; l.height += s.height - p.height; return l; } public static class EventNodeRenderer extends DefaultTreeCellRenderer { private static final long serialVersionUID = 1L; public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree,value,sel,expanded,leaf,row,hasFocus); int mid = -1; if (value instanceof EventNode) mid = ((EventNode) value).mainId; if (value instanceof EventInstanceNode) mid = ((EventInstanceNode) value).getUserObject().mainId; if (value instanceof EventGroupNode) mid = ((EventGroupNode) value).mainId; Icon i = LGM.getIconForKey("EventNode." + (leaf ? "EVENT" : "GROUP") + mid); if (i != null && i.getIconWidth() != -1) setIcon(i); return this; } } private class MListener extends MouseAdapter { public void mouseReleased(MouseEvent e) { if (e.getSource() != events) return; int button = e.getButton(); if (button == MouseEvent.BUTTON3) { TreePath path = events.getPathForLocation(e.getX(),e.getY()); if (path == null) return; DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); if (node.isLeaf()) { lastValidEventSelection = node; actions.setActionContainer((Event) node.getUserObject()); events.setSelectionPath(path); JPopupMenu menu = new JPopupMenu(); eventAddItem = new JMenuItem(Messages.getString("GmObjectFrame.ADD_EVENT")); //$NON-NLS-1 menu.add(eventAddItem); eventAddItem.addActionListener(GmObjectFrame.this); eventReplaceItem = new JMenuItem(Messages.getString("GmObjectFrame.REPLACE_EVENT")); //$NON-NLS-1 menu.add(eventReplaceItem); eventReplaceItem.addActionListener(GmObjectFrame.this); eventDuplicateItem = new JMenuItem(Messages.getString("GmObjectFrame.DUPLICATE_EVENT")); //$NON-NLS-1 menu.add(eventDuplicateItem); eventDuplicateItem.addActionListener(GmObjectFrame.this); eventDeleteItem = new JMenuItem(Messages.getString("GmObjectFrame.DELETE_EVENT")); //$NON-NLS-1 menu.add(eventDeleteItem); eventDeleteItem.addActionListener(GmObjectFrame.this); menu.show(e.getComponent(),e.getX(),e.getY()); } } } } }