package NET.worlds.scape; import NET.worlds.console.Console; import NET.worlds.console.DialogDisabled; import NET.worlds.console.DialogReceiver; import NET.worlds.console.ExposedPanel; import NET.worlds.console.Main; import NET.worlds.console.MainCallback; import NET.worlds.console.PolledDialog; import NET.worlds.console.RenderCanvas; import NET.worlds.console.SnapTool; import NET.worlds.console.Tree; import NET.worlds.console.TreeCallback; import NET.worlds.network.URL; import java.awt.Button; import java.awt.Component; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Label; import java.awt.Point; import java.io.IOException; import java.text.MessageFormat; import java.util.Enumeration; import java.util.Vector; public class EditTile extends ExposedPanel implements DialogReceiver, TreeCallback, MainCallback, DialogDisabled { private Button editButton = new Button(Console.message("Edit")); private Button addButton = new Button(Console.message("Add")); private Button delButton = new Button(Console.message("Delete")); private Button helpButton = new Button(Console.message("Help")); private ToolBar toolbar = new ToolBar(); private Label title = new Label(); private String titleText = ""; private boolean usingTitleAsPrompt; private PropList props = new PropList(); private int queuedFunction = 0; private Object queuedObject; private Tree tree; private PolledDialog activePopup; private boolean startup = true; private World rootWorld = null; private boolean isDialogDisabled; private static final int NONE = 0; private static final int DELETE = 1; private static final int ADD = 2; private static final int CHANGE = 3; private static final int UPDATE = 4; private static final int CUT = 5; private static final int COPY = 6; private static final int PASTE = 7; private static final int UNDO = 8; private static final int EDIT = 9; private static final int DROP = 10; private static final int HELP = 11; private static ClipboardEntry clipboard; private static UndoStack undoStack = new UndoStack(); private Undoable preAddStackTop; private boolean isAdd; private SendURLAction helpAction = new SendURLAction(); private Persister helpBrowser; public void viewProperties(Object obj) { Console.getFrame().setShaperVisible(true); this.queue(3, obj); } public void libraryDrop(URL url, String propertyName, Component comp, Point location) { this.queue(10, new DropInfo(url, propertyName, comp, location)); } public EditTile(Tree tree) { this.tree = tree; tree.setOwner(this); GridBagLayout gbag = new GridBagLayout(); this.setLayout(gbag); GridBagConstraints c = new GridBagConstraints(); c.fill = 2; c.gridwidth = 0; c.weightx = 1.0; c.weighty = 0.0; c.anchor = 18; this.add(gbag, this.toolbar, c); this.add(gbag, this.title, c); c.weighty = 1.0; c.fill = 1; c.gridwidth = 2; c.gridheight = 0; this.add(gbag, this.props, c); c.weightx = 0.0; c.weighty = 0.0; c.gridwidth = 0; c.gridheight = 1; c.fill = 2; this.add(gbag, this.editButton, c); this.add(gbag, this.addButton, c); this.add(gbag, this.delButton, c); this.add(gbag, this.helpButton, c); Main.register(this); } public void update() { this.queue(4); } private void add(GridBagLayout gbag, Component comp, GridBagConstraints c) { gbag.setConstraints(comp, c); this.add(comp); } private boolean queue(int function) { return this.queue(function, null); } private synchronized boolean queue(int function, Object obj) { if (this.queuedFunction == 0 && this.activePopup == null) { this.queuedFunction = function; this.queuedObject = obj; this.disable(); } return true; } @Override public synchronized void mainCallback() { if (this.startup) { World w = Pilot.getActiveWorld(); if (w != null) { this.change(w); this.startup = false; } } if (this.rootWorld != null) { this.rootWorld.incRef(); } boolean enable = true; switch (this.queuedFunction) { case 0: return; case 1: this.delete(false); break; case 2: enable = this.doAdd(); break; case 3: this.change(this.queuedObject); break; case 4: this.tree.update(); break; case 5: this.delete(true); break; case 6: this.doCopy(); break; case 7: this.doPaste(); break; case 8: this.doUndo(); break; case 9: enable = this.doEdit(); break; case 10: if (!this.drop((DropInfo)this.queuedObject)) { Object[] arguments = new Object[]{new String("" + ((DropInfo)this.queuedObject).url)}; Console.println(MessageFormat.format(Console.message("Target-doesnt"), arguments)); } break; case 11: this.doHelp(); } this.enable(enable); this.queuedFunction = 0; this.queuedObject = null; } private void delete(boolean isCut) { if (this.delButton.isEnabled()) { PropTreeNode e = (PropTreeNode)this.tree.getSelectedNode(); if (e != null && this.tree.hasFocus()) { this.addUndoable(e.delete(isCut)); } else { Property p = this.props.getSelectedProperty(); assert p.canSetNull() && p.get() != null; this.addUndoableSet(p, null); } this.tree.update(); } } public static void adjustDroppedSource(SuperRoot sr) { if (sr != null && (!(sr instanceof WObject) || !((WObject)sr).isDynamic())) { sr.setSourceURL(null); } } private boolean drop(DropInfo info) { Object dropped = info.url; if (info.url.endsWith(".class") || info.url.endsWith("." + WObject.getSaveExtension())) { SuperRoot sr = WobLoader.immediateLoad(info.url); adjustDroppedSource(sr); dropped = sr; } return this.drop(dropped, info.propertyName, false, info.comp, info.location); } private boolean drop(Object obj, String propertyName, boolean isPaste) { return this.drop(obj, propertyName, isPaste, null, null); } private boolean drop(Object obj, String propertyName, boolean isPaste, Component comp, Point location) { if (obj == null) { return false; } else { PropTreeNode e = null; Point3Temp dropPoint = null; if (comp == null && this.tree.hasFocus()) { e = (PropTreeNode)this.tree.getSelectedNode(); } else if (comp == this.tree) { e = (PropTreeNode)this.tree.elementAt(location); } else if (comp instanceof RenderCanvas) { Camera c = ((RenderCanvas)comp).getCamera(); dropPoint = Point3Temp.make(); WObject picked = c.getObjectAt(location.x, location.y, false, dropPoint); if (picked != null) { if (obj instanceof WObject) { picked = picked.getRoom(); } } else { Pilot pilot = Pilot.getActive(); picked = pilot.getRoom(); dropPoint.set(0.0F, 180.0F, 0.0F); dropPoint.times(pilot); } if (picked != null) { this.change(picked); e = (PropTreeNode)this.tree.getSelectedNode(); } } if (e == null) { return false; } else { boolean success = false; VectorProperty vp; PropAdder adder; if ((vp = e.getContainingVectorProperty()) != null && (adder = vp.getAdder()) != null) { success = adder.libraryDrop(this, obj, isPaste, true); } if (!success) { Object top; for (top = null; e != null; e = (PropTreeNode)e.getParent()) { top = e.getObject(); if (top instanceof Properties) { break; } if (top instanceof Property) { Property prop = (Property)top; top = ((Property)top).get(); if (top instanceof Properties) { break; } } } if (e != null) { Vector targets = new Vector(); int topLevelTargets = this.recurseFindDropTargets(targets, obj, propertyName, isPaste, new EnumProperties(top), 0, 10); if (topLevelTargets == 1 || topLevelTargets == 0 && targets.size() == 1) { success = ((LibraryDrop)targets.elementAt(0)).libraryDrop(this, obj, isPaste, true); } } } if (success) { if (obj instanceof Properties) { this.change(obj); } else { this.tree.update(); } } WObject wobj; if (dropPoint != null && obj instanceof WObject && !(obj instanceof Room) && (wobj = (WObject)obj).isActive()) { dropPoint.z = wobj.getZ(); wobj.moveTo(SnapTool.snapTool().snapTo(dropPoint)); } return success; } } } private int recurseFindDropTargets(Vector targets, Object obj, String propertyName, boolean isPaste, Enumeration props, int level, int maxLevel) { int firstLevelMatches = 0; if (level > maxLevel) { return 0; } else { while (props.hasMoreElements()) { Property p = (Property)props.nextElement(); boolean propMatch = propertyName == null || propertyName.equals(p.getName()); if (propMatch) { LibraryDrop target = null; if (p instanceof VectorProperty) { target = ((VectorProperty)p).getAdder(); } else { target = p.getEditor(); } if (target != null && target.libraryDrop(this, obj, isPaste, false)) { if (level == 0) { targets.insertElementAt(target, firstLevelMatches++); } else { targets.addElement(target); } continue; } } if (!(p instanceof VectorProperty)) { int err = this.recurseFindDropTargets(targets, obj, propertyName, isPaste, new EnumProperties(p.get()), level + 1, maxLevel); if (err != 0) { return err; } } } return firstLevelMatches; } } private boolean change(Object obj) { Object parent = obj; Vector lineage = new Vector(); Object p; while (parent instanceof Properties && (p = ((Properties)parent).propertyParent()) != null) { if (lineage != null) { Enumeration e = new EnumProperties(p); boolean found = false; while (e.hasMoreElements()) { Property prop = (Property)e.nextElement(); Object o = prop.get(); boolean isVector = prop instanceof VectorProperty; if (o == parent || isVector && o != null && ((Vector)o).indexOf(parent) != -1) { if (isVector) { lineage.insertElementAt(parent, 0); } lineage.insertElementAt(prop, 0); found = true; break; } } if (!found) { lineage = null; } } parent = p; } this.rootWorld = null; if (parent instanceof World) { this.rootWorld = (World)parent; } PropTreeNode root = new PropTreeNode(parent); if (lineage != null) { this.tree.change(root, lineage); } else { this.tree.change(root, obj); } return true; } @Override public void treeFocusChanged(boolean hasFocus) { if (hasFocus) { this.props.deselect(this.props.getSelectedIndex()); this.adjustButtons(); } } @Override public void treeChange(Object obj) { if (obj instanceof Property && !(obj instanceof VectorProperty)) { obj = ((Property)obj).get(); } this.props.setObject(obj); this.toolbar.setCurrentObject(obj); String name = obj.getClass().getName(); int index; if ((index = name.lastIndexOf(46)) != -1) { name = name.substring(index + 1); } this.setTitle(name + " " + Console.message("Properties")); this.adjustButtons(); } private void setTitle(String titleText) { this.titleText = titleText; if (!this.usingTitleAsPrompt) { this.title.setText(titleText); } } public void setPrompt(String promptText) { this.title.setText((this.usingTitleAsPrompt = promptText != null) ? promptText : this.titleText); } private void adjustButtons() { PropTreeNode e = (PropTreeNode)this.tree.getSelectedNode(); if (e != null && this.tree.hasFocus()) { this.editButton.enable(e.canEdit()); this.delButton.enable(e.canDelete()); this.addButton.enable(e.canAdd()); this.helpButton.enable(true); } else { Property p = this.props.getSelectedProperty(); if (p != null) { Object obj = p.get(); this.editButton.enable(p.getEditor() != null); this.delButton.enable(p.canSetNull() && obj != null); this.addButton.enable(p.canSetNull() && p.getEditor() != null && obj == null); this.helpButton.enable(p.helpExists); } else { this.editButton.disable(); this.delButton.disable(); this.addButton.disable(); this.helpButton.disable(); } } } @Override public void dialogDisable(boolean disable) { this.isDialogDisabled = disable; this.toolbar.dialogDisable(disable); } @Override public boolean handleEvent(java.awt.Event event) { if (event.id == 701) { if (event.target == this.props) { this.tree.setFocus(false); } this.adjustButtons(); } return this.isDialogDisabled ? false : super.handleEvent(event); } @Override public boolean action(java.awt.Event event, Object what) { Object target = event.target; if (target == this.delButton) { return this.queue(1); } else if (target == this.addButton) { return this.queue(2); } else if (target != this.editButton && (target != this.props || !this.editButton.isEnabled())) { return target == this.helpButton ? this.queue(11) : false; } else { return this.queue(9); } } @Override public void dialogDone(Object who, boolean confirmed) { if (who == this.activePopup) { this.activePopup = null; this.tree.enable(); if (confirmed) { Undoable u; Object obj; if (this.isAdd && (u = undoStack.peek()) != this.preAddStackTop && u instanceof UndoablAdd && (obj = ((UndoablAdd)u).getObject()) instanceof Properties) { this.change(obj); } else { this.tree.update(); } } this.enable(); } } private boolean doEdit() { Property p = this.props.getSelectedProperty(); PropEditor editor; if (p != null && (editor = p.getEditor()) != null) { this.isAdd = false; this.activePopup = editor.edit(this, "Edit " + p.getName()); this.tree.disable(); return false; } else { return true; } } private boolean doAdd() { PropTreeNode e = (PropTreeNode)this.tree.getSelectedNode(); PropAdder adder; if (e != null && this.tree.hasFocus() && (adder = e.getAdder()) != null) { this.preAddStackTop = undoStack.peek(); this.isAdd = true; this.activePopup = adder.add(this, "Add to " + e.getContainerName()); this.tree.disable(); return false; } else { return true; } } public void cut() { this.queue(5); } public void paste() { this.queue(7); } private boolean doPaste() { if (clipboard != null) { SuperRoot obj = clipboard.paste(); if (this.drop(obj, null, true)) { return true; } clipboard.unPaste(obj); Console.println(Console.message("Clip-contents")); } else { Console.println(Console.message("Clip-empty")); } return false; } private boolean doHelp() { this.helpAction.showDialog = false; if (this.tree.hasFocus() && this.props.getSelectedProperty() == null) { try { SuperRoot s = (SuperRoot)((PropTreeNode)this.tree.getSelectedNode()).getObject(); if (s != null) { this.helpAction.setDestination(s.getHelpURL()); } } catch (ClassCastException var5) { Console.println(Console.message("No-help")); } } else { Property p = this.props.getSelectedProperty(); if (p != null && p.helpExists) { try { SuperRoot s = (SuperRoot)((PropTreeNode)this.tree.getSelectedNode()).getObject(); if (s != null) { this.helpAction.setDestination(s.getHelpURL(p)); } } catch (ClassCastException var4) { Console.println(Console.message("No-help")); } } } this.helpBrowser = this.helpAction.trigger(null, this.helpBrowser); return true; } public void copy() { this.queue(6); } private void doCopy() { SuperRoot item = this.getCurSuperRoot(true); if (item != null) { ClipboardEntry newClip = new ClipboardEntry(); if (newClip.copy(item)) { this.addUndoable(new UndoabCopy(newClip)); } } } public boolean save(String fileName) { SuperRoot item = this.getCurSuperRoot(true); try { item.saveFile(new URL(URL.getCurDir(), fileName)); return true; } catch (IOException var4) { return false; } } private SuperRoot getCurSuperRoot(boolean allowContainers) { Object obj = this.props.getObject(); return obj instanceof SuperRoot ? (SuperRoot)obj : null; } public void addUndoable(Undoable u) { undoStack.push(u); } public void addUndoableSet(Property prop, Object obj) { this.addUndoable(new UndoablSet(prop, obj)); } public void addUndoableAdd(VectorProperty prop, Object obj, boolean changeTree) { this.addUndoable(new UndoablAdd(prop, obj)); if (!changeTree) { this.preAddStackTop = undoStack.peek(); } } public void addUndoablePaste(VectorProperty prop, Object obj) { try { this.addUndoable(new UndoablPaste(prop, clipboard, obj)); } catch (Error var4) { Console.println(var4.getMessage()); } } public void undo() { if (Main.isMainThread()) { this.doUndo(); } else { this.queue(8); } } private void doUndo() { if (undoStack.undo()) { this.tree.update(); } } public static void setClipboard(ClipboardEntry clip) { clipboard = clip; } public static ClipboardEntry getClipboard() { return clipboard; } }