package org.chartsy.favorites;
import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ActionMap;
import javax.swing.text.DefaultEditorKit;
import org.chartsy.favorites.xml.FavoritesXmlParser;
import org.chartsy.favorites.xml.FavoritesXmlWriter;
import org.chartsy.main.events.DataProviderEvent;
import org.chartsy.main.events.DataProviderListener;
import org.chartsy.main.favorites.FavoritesTreeView;
import org.chartsy.main.favorites.nodes.RootAPI;
import org.chartsy.main.favorites.nodes.RootAPINode;
import org.chartsy.main.managers.DatasetUsage;
import org.chartsy.main.utils.FileUtils;
import org.chartsy.main.utils.SerialVersion;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.nodes.Node;
import org.openide.nodes.NodeEvent;
import org.openide.nodes.NodeListener;
import org.openide.nodes.NodeMemberEvent;
import org.openide.nodes.NodeOp;
import org.openide.nodes.NodeReorderEvent;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
/**
*
* @author Viorel
*/
public final class FavoritesComponent extends TopComponent
implements DataProviderListener, ExplorerManager.Provider
{
private static FavoritesComponent instance;
private static final String PREFERRED_ID = "FavoritesComponent";
private ExplorerManager manager;
private FavoritesTreeView treeView;
private RootAPI root;
transient private PropertyChangeListener weakRcL;
transient private NodeListener weakNRcL;
transient private NodeListener rcListener;
private FavoritesComponent()
{
setName(NbBundle.getMessage(FavoritesComponent.class, "CTL_FavoritesComponent"));
setToolTipText(NbBundle.getMessage(FavoritesComponent.class, "HINT_FavoritesComponent"));
setIcon(ImageUtilities.loadImage(NbBundle.getMessage(FavoritesComponent.class, "ICON_FavoritesComponent"), true));
putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
putClientProperty(TopComponent.PROP_MAXIMIZATION_DISABLED, Boolean.TRUE);
putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
putClientProperty(TopComponent.PROP_KEEP_PREFERRED_SIZE_WHEN_SLIDED_IN, Boolean.TRUE);
manager = new ExplorerManager();
initComponents();
ActionMap map = getActionMap();
map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(manager));
map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(manager));
map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(manager));
map.put("delete", ExplorerUtils.actionDelete(manager, true));
associateLookup(ExplorerUtils.createLookup(manager, map));
DatasetUsage.getInstance().addDataProviderListener((DataProviderListener) this);
}
private void initComponents()
{
setOpaque(false);
setLayout(new BorderLayout());
treeView = FavoritesTreeView.getDefault();
add(treeView, BorderLayout.CENTER);
}
public static synchronized FavoritesComponent getDefault()
{
if (instance == null)
instance = new FavoritesComponent();
return instance;
}
public static synchronized FavoritesComponent findInstance()
{
TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
if (win == null)
{
Logger.getLogger(FavoritesComponent.class.getName()).warning(
"Cannot find " + PREFERRED_ID + " component. It will not be "
+ "located properly in the window system.");
return getDefault();
}
if (win instanceof FavoritesComponent)
{
return (FavoritesComponent) win;
}
Logger.getLogger(FavoritesComponent.class.getName()).warning(
"There seem to be multiple components with the '"
+ PREFERRED_ID + "' ID. That is a potential source of errors and "
+ "unexpected behavior.");
return getDefault();
}
protected @Override void componentActivated()
{
ExplorerUtils.activateActions(manager, true);
}
protected @Override void componentDeactivated()
{
ExplorerUtils.activateActions(manager, false);
}
protected @Override void componentOpened()
{
if (isInitialized())
initializeRootNode();
else
initialize();
}
public @Override int getPersistenceType()
{
return TopComponent.PERSISTENCE_ALWAYS;
}
protected @Override String preferredID()
{
return PREFERRED_ID;
}
public void triggerDataProviderListener(DataProviderEvent evt)
{
revalidate();
repaint();
}
public ExplorerManager getExplorerManager()
{
return manager;
}
private boolean isInitialized()
{
return FileUtils.favoritesFile().exists();
}
private void initialize()
{
boolean ok = false;
try
{
FileObject dest = FileUtil.createData(FileUtils.favoritesFile());
FileUtil.copy(
FavoritesComponent.class.getResourceAsStream("favoritesDefaults.xml"),
dest.getOutputStream());
ok = true;
}
catch (IOException ex)
{
Logger.getLogger(FavoritesComponent.class.getName()).log(
Level.SEVERE, "Can't copy favorites defaults.", ex);
ok = false;
}
if (ok)
initializeRootNode();
}
private void initializeRootNode()
{
root = FavoritesXmlParser.getRoot();
if (root != null)
{
RootAPINode node = new RootAPINode(root);
setRootContext(node);
}
}
public void setRootContext(Node rc)
{
Node oldRC = getExplorerManager().getRootContext();
if (weakRcL != null)
oldRC.removePropertyChangeListener(weakRcL);
if (weakNRcL != null)
oldRC.removeNodeListener(weakNRcL);
getExplorerManager().setRootContext(rc);
initializeWithRootContext(rc);
}
private void initializeWithRootContext(Node rc)
{
if (weakRcL == null)
weakRcL = WeakListeners.propertyChange(rcListener(), rc);
rc.addPropertyChangeListener(weakRcL);
if (weakNRcL == null)
weakNRcL = NodeOp.weakNodeListener(rcListener(), rc);
rc.addNodeListener(weakNRcL);
}
private NodeListener rcListener()
{
if (rcListener == null)
rcListener = new RootContextListener();
return rcListener;
}
protected @Override Object writeReplace()
{
Logger.getLogger(FavoritesComponent.class.getName()).log
(Level.INFO, "Saving favorites xml ...");
boolean saved = FavoritesXmlWriter.saveFavoritesNodes(getExplorerManager().getRootContext());
if (saved)
Logger.getLogger(FavoritesComponent.class.getName()).log
(Level.INFO, "Favorites xml saved.");
else
Logger.getLogger(FavoritesComponent.class.getName()).log
(Level.INFO, "Couldn't save favorites xml.");
return new ResolvableHelper();
}
private final class RootContextListener implements NodeListener
{
public void propertyChange (PropertyChangeEvent evt)
{}
public void nodeDestroyed(NodeEvent nodeEvent)
{ FavoritesComponent.this.close(); }
public void childrenRemoved(NodeMemberEvent e) {}
public void childrenReordered(NodeReorderEvent e) {}
public void childrenAdded(NodeMemberEvent e) {}
}
final static class ResolvableHelper implements Serializable
{
private static final long serialVersionUID = SerialVersion.APPVERSION;
public ResolvableHelper()
{}
public Object readResolve()
{
return new FavoritesComponent();
}
}
}