/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2012 Neil C Smith.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU General Public License version 3
* along with this work; if not, see http://www.gnu.org/licenses/
*
*
* Please visit http://neilcsmith.net if you need additional information or
* have any questions.
*/
package net.neilcsmith.praxis.live.pxr;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.beans.BeanInfo;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JToolBar;
import net.neilcsmith.praxis.live.pxr.api.RootEditor;
import net.neilcsmith.praxis.live.pxr.api.RootRegistry;
import org.openide.awt.Actions;
import org.openide.util.ContextAwareAction;
import org.openide.util.Lookup;
import org.openide.util.actions.Presenter;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import org.openide.windows.CloneableTopComponent;
/**
*
* @author Neil C Smith (http://neilcsmith.net)
*/
public class RootEditorTopComponent extends CloneableTopComponent {
private final static Action START_STOP_ACTION = new StartableRootAction();
private final static Action ROOT_CONFIG_ACTION = new RootConfigAction();
private PXRDataObject dob;
private RootEditor editor;
private JComponent editorPanel;
private EditorLookup lookup;
private PXRRootProxy root;
private PropertyChangeListener registryListener;
private JToolBar toolBar;
public RootEditorTopComponent(PXRDataObject dob) {
this.setDisplayName(dob.getName());
this.setIcon(dob.getNodeDelegate().getIcon(BeanInfo.ICON_COLOR_16x16));
this.dob = dob;
lookup = new EditorLookup(Lookups.singleton(dob), dob.getLookup());
associateLookup(lookup);
setLayout(new BorderLayout());
toolBar = new ToolBar();
add(toolBar, BorderLayout.NORTH);
registryListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
checkRoot();
}
};
}
@Override
protected void componentOpened() {
assert EventQueue.isDispatchThread();
root = PXRRootRegistry.getDefault().findRootForFile(dob.getPrimaryFile());
install(root);
RootRegistry.getDefault().addPropertyChangeListener(registryListener);
}
@Override
protected void componentShowing() {
if (editor != null) {
editor.componentShowing();
}
}
@Override
protected void componentActivated() {
if (editor != null) {
editor.componentActivated();
requestFocusInWindow();
}
}
@Override
protected void componentDeactivated() {
if (editor != null) {
editor.componentDeactivated();
}
}
@Override
protected void componentHidden() {
if (editor != null) {
editor.componentHidden();
}
}
@Override
protected void componentClosed() {
RootRegistry.getDefault().removePropertyChangeListener(registryListener);
uninstall(root);
}
// @Override
// public void requestFocus() {
// super.requestFocus();
// if (editorPanel != null) {
// editorPanel.requestFocus();
// }
// }
//
// @Override
// public boolean requestFocusInWindow() {
// super.requestFocusInWindow();
// if (editorPanel != null) {
// return editorPanel.requestFocusInWindow();
// } else {
// return false;
// }
// }
@Override
protected CloneableTopComponent createClonedObject() {
return new RootEditorTopComponent(dob);
}
private void checkRoot() {
PXRRootProxy root = PXRRootRegistry.getDefault().findRootForFile(dob.getPrimaryFile());
if (root == this.root) {
return;
}
uninstall(this.root);
this.root = root;
install(root);
}
private void install(PXRRootProxy root) {
if (root == null) {
editor = new BlankEditor();
lookup.setAdditional(editor.getLookup());
initToolbar(new Action[0]);
} else {
editor = findEditor(root);
lookup.setAdditional(
Lookups.singleton(new PXRRootContext(root)),
editor.getLookup());
initToolbar(buildActions(editor));
}
editorPanel = editor.getEditorComponent();
add(editorPanel);
if (isVisible()) {
editor.componentShowing();
editor.componentActivated();
}
}
private Action[] buildActions(RootEditor editor) {
Action[] editorActions = editor.getActions();
if (editorActions == null || editorActions.length == 0) {
return new Action[]{START_STOP_ACTION, ROOT_CONFIG_ACTION};
}
ArrayList<Action> actions = new ArrayList<Action>(editorActions.length + 2);
actions.add(START_STOP_ACTION);
actions.add(ROOT_CONFIG_ACTION);
actions.add(null);
actions.addAll(Arrays.asList(editorActions));
return actions.toArray(new Action[actions.size()]);
}
private void uninstall(PXRRootProxy root) {
remove(editorPanel);
editorPanel = null;
editor.dispose();
editor = null;
}
private void initToolbar(Action[] actions) {
toolBar.removeAll();
Lookup context = getLookup();
for (Action action : actions) {
if (action instanceof ContextAwareAction) {
action = ((ContextAwareAction) action).createContextAwareInstance(context);
}
Component c;
if (action instanceof Presenter.Toolbar) {
c = ((Presenter.Toolbar) action).getToolbarPresenter();
} else if (action == null) {
c = new JToolBar.Separator();
} else {
JButton button = new JButton();
Actions.connect(button, action);
c = button;
}
if (c instanceof AbstractButton) {
c.setFocusable(false);
}
toolBar.add(c);
}
}
@Override
public int getPersistenceType() {
return PERSISTENCE_NEVER;
}
private RootEditor findEditor(PXRRootProxy root) {
for (RootEditor.Provider provider : Lookup.getDefault().lookupAll(RootEditor.Provider.class)) {
RootEditor ed = provider.createEditor(root);
if (ed != null) {
return ed;
}
}
// String type = root.getType().toString();
// if (type.startsWith("root:")) {
// return new GraphEditor(root, type.substring(5));
// } else {
return new DebugRootEditor(root);
// }
}
private class BlankEditor extends RootEditor {
@Override
public Lookup getLookup() {
return Lookups.singleton(dob.getNodeDelegate());
}
@Override
public JComponent getEditorComponent() {
JComponent editor = new JLabel("<Build " + dob.getName() + " to edit>", JLabel.CENTER);
editor.setFocusable(true);
return editor;
}
}
private class EditorLookup extends ProxyLookup {
private Lookup[] permanent;
private EditorLookup(Lookup... lookups) {
super(lookups);
this.permanent = lookups;
}
private void setAdditional(Lookup... lookups) {
if (lookups == null || lookups.length == 0) {
setLookups(permanent);
} else {
List<Lookup> lst = new ArrayList<Lookup>();
lst.addAll(Arrays.asList(permanent));
lst.addAll(Arrays.asList(lookups));
setLookups(lst.toArray(new Lookup[lst.size()]));
}
}
}
private class ToolBar extends JToolBar {
ToolBar() {
super("editorToolbar");
setFocusable(false);
setFloatable(false);
setRollover(true);
setBorder(BorderFactory.createEtchedBorder());
}
}
}