/* * Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC * All rights reserved. * * The source code of this document is proprietary work, and is not licensed for * distribution. For information about licensing, contact Sam Harwell at: * sam@tunnelvisionlabs.com */ package org.tvl.goworks.editor.go; import java.awt.Image; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.Collection; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.annotations.common.StaticResource; import org.openide.loaders.DataNode; import org.openide.loaders.DataObject; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.PropertySupport; import org.openide.nodes.Sheet; import org.openide.util.ImageUtilities; import org.openide.util.Lookup; import org.openide.util.NbBundle; /** * * @author Sam Harwell */ @NbBundle.Messages({ "TP_NeedsCompileBadge=Needs to be compiled.", "TP_ExecutableBadge=Contains main class.", }) public final class GoFileNode extends DataNode implements ChangeListener { @StaticResource private static final String EXECUTABLE_BADGE_URL = "org/tvl/goworks/editor/go/resources/executable-badge.png"; @StaticResource private static final String NEEDS_COMPILE_BADGE_URL = "org/tvl/goworks/editor/go/resources/needs-compile.png"; @StaticResource private static final String GO_ICON_BASE = "org/tvl/goworks/editor/go/resources/class.png"; // NOI18N @StaticResource private static final String CLASS_ICON_BASE = "org/tvl/goworks/editor/go/resources/clazz.gif"; // NOI18N private static final Image NEEDS_COMPILE; private static final Image IS_EXECUTABLE_CLASS; private static final Logger LOGGER = Logger.getLogger(GoFileNode.class.getName()); @NonNull private final AtomicBoolean isCompiled = new AtomicBoolean(true); @NonNull private final AtomicBoolean isExecutable = new AtomicBoolean(false); static { URL needsCompileIconURL = GoFileNode.class.getClassLoader().getResource(NEEDS_COMPILE_BADGE_URL); String needsCompileTP = "<img src=\"" + needsCompileIconURL + "\"> " + Bundle.TP_NeedsCompileBadge(); NEEDS_COMPILE = ImageUtilities.assignToolTipToImage(ImageUtilities.loadImage(NEEDS_COMPILE_BADGE_URL), needsCompileTP); // NOI18N URL executableIconURL = GoFileNode.class.getClassLoader().getResource(EXECUTABLE_BADGE_URL); String executableTP = "<img src=\"" + executableIconURL + "\"> " + Bundle.TP_ExecutableBadge(); IS_EXECUTABLE_CLASS = ImageUtilities.assignToolTipToImage(ImageUtilities.loadImage(EXECUTABLE_BADGE_URL), executableTP); // NOI18N } public GoFileNode(DataObject obj, boolean isGoSource) { super(obj, Children.LEAF); this.setIconBaseWithExtension(isGoSource ? GO_ICON_BASE : CLASS_ICON_BASE); } @Override public void setName(String name) { RenameHandler handler = getRenameHandler(); if (handler == null) { super.setName(name); } else { try { handler.handleRename(GoFileNode.this, name); } catch (IllegalArgumentException ex) { super.setName(name); } } } @Override protected Sheet createSheet() { Sheet sheet = super.createSheet(); //if there is any rename handler installed //push under our own property if (getRenameHandler() != null) sheet.get(Sheet.PROPERTIES).put(createNameProperty()); return sheet; } private Node.Property<String> createNameProperty () { Node.Property<String> p = new PropertySupport.ReadWrite<String> ( DataObject.PROP_NAME, String.class, NbBundle.getMessage (DataObject.class, "PROP_name"), NbBundle.getMessage (DataObject.class, "HINT_name") ) { @Override public String getValue () { return GoFileNode.this.getName(); } @Override public Object getValue(String key) { if ("suppressCustomEditor".equals (key)) { //NOI18N return Boolean.TRUE; } else { return super.getValue (key); } } @Override public void setValue(String val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!canWrite()) throw new IllegalAccessException(); GoFileNode.this.setName(val); } @Override public boolean canWrite() { return GoFileNode.this.canRename(); } }; return p; } private static synchronized RenameHandler getRenameHandler() { Collection<? extends RenameHandler> handlers = Lookup.getDefault().lookupAll(RenameHandler.class); if (handlers.isEmpty()) { return null; } if (handlers.size() > 1) { LOGGER.log(Level.WARNING, "Multiple instances of RenameHandler found in Lookup; only using first one: {0}", handlers); // NOI18N } return handlers.iterator().next(); } @Override public void stateChanged(ChangeEvent e) { throw new UnsupportedOperationException("Not supported yet."); } @Override public Image getIcon(int type) { Image i = super.getIcon(type); return enhanceIcon(i); } @Override public Image getOpenedIcon(int type) { Image i = super.getOpenedIcon(type); return enhanceIcon(i); } private Image enhanceIcon(Image i) { if (!isCompiled.get()) { i = ImageUtilities.mergeImages(i, NEEDS_COMPILE, 16, 0); } if (isExecutable.get()) { i = ImageUtilities.mergeImages(i, IS_EXECUTABLE_CLASS, 10, 6); } return i; } }