/*
* Copyright (C) 2012 Jason Gedge <http://www.gedge.ca>
*
* This file is part of the OpGraph project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
*
*/
package ca.gedge.opgraph.app;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import ca.gedge.opgraph.OpGraph;
import ca.gedge.opgraph.OpNode;
import ca.gedge.opgraph.Processor;
import ca.gedge.opgraph.app.components.BreadcrumbViewer;
import ca.gedge.opgraph.app.components.ConsolePanel;
import ca.gedge.opgraph.app.components.ContextViewerPanel;
import ca.gedge.opgraph.app.components.NodeDefaultsPanel;
import ca.gedge.opgraph.app.components.NodeSettingsPanel;
import ca.gedge.opgraph.app.components.canvas.GraphCanvas;
import ca.gedge.opgraph.app.components.canvas.GraphCanvasSelectionListener;
import ca.gedge.opgraph.app.components.library.NodeLibraryViewer;
import ca.gedge.opgraph.util.ServiceDiscovery;
/**
* A model for the graph editor.
*/
public class GraphEditorModel {
/** Logger */
private static final Logger LOGGER = Logger.getLogger(GraphEditorModel.class.getName());
/** The active editor model */
private static GraphEditorModel activeModel;
/**
* Gets the {@link GraphEditorModel} that is currently active.
*
* @return the active editor model, or <code>null</code> if no model active
*/
public static GraphEditorModel getActiveEditorModel() {
return activeModel;
}
/**
* Sets a given model as the active model for the application.
*
* @param model the new model
*/
public static void setActiveEditorModel(GraphEditorModel model) {
activeModel = model;
}
/**
* Gets the {@link GraphDocument} that is currently active.
*
* @return the active document, or <code>null</code> if no document active
*/
public static GraphDocument getActiveDocument() {
final GraphEditorModel model = getActiveEditorModel();
return (model == null ? null : model.getDocument());
}
/** The breadcrumb attached to the canvas */
private BreadcrumbViewer<OpGraph, ?> breadcrumb;
/** The canvas this window is viewing */
private GraphCanvas canvas;
/** The console panel */
private ConsolePanel console;
/** The panel that allows one to edit default values for node input fields */
private NodeDefaultsPanel nodeDefaults;
/** The panel that allows one to modify node settings */
private NodeSettingsPanel nodeSettings;
/** The viewer component for the node library */
private NodeLibraryViewer nodeLibrary;
/** The viewer component for the node library */
private ContextViewerPanel debugPanel;
/** List of menu providers */
private ArrayList<MenuProvider> menuProviders;
/**
*
*/
public GraphEditorModel() {
// Initialize components
canvas = new GraphCanvas(this);
canvas.getSelectionModel().addSelectionListener(graphSelectionListener);
console = new ConsolePanel();
breadcrumb = new BreadcrumbViewer<OpGraph, String>(canvas.getDocument().getBreadcrumb());
nodeDefaults = new NodeDefaultsPanel();
nodeSettings = new NodeSettingsPanel();
nodeLibrary = new NodeLibraryViewer();
debugPanel = new ContextViewerPanel();
// Property change listeners
canvas.getDocument().addPropertyChangeListener(GraphDocument.PROCESSING_CONTEXT, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
final Processor context = (Processor)evt.getNewValue();
// Let canvas redraw itself based on the given context
canvas.updateDebugState(context);
// Update debug panel information
if(debugPanel.getProcessingContext() != context)
debugPanel.setProcessingContext(context);
else
debugPanel.updateDebugInfo();
}
});
// Discover menu extensions
this.menuProviders = new ArrayList<MenuProvider>();
final ServiceDiscovery discovery = ServiceDiscovery.getInstance();
for(Class<? extends MenuProvider> menu : discovery.findProviders(MenuProvider.class)) {
try {
menuProviders.add(menu.newInstance());
} catch(InstantiationException exc) {
LOGGER.warning("Could not instantiate menu provider: " + menu.getName());
} catch(IllegalAccessException exc) {
LOGGER.warning("Could not instantiate menu provider: " + menu.getName());
}
}
}
/**
* Gets the graph canvas this window is using.
*
* @return the canvas, or <code>null</code> if no canvas is being viewed
*/
public GraphCanvas getCanvas() {
return canvas;
}
/**
* Gets the console panel.
*
* @return the console
*/
public ConsolePanel getConsolePanel() {
return console;
}
/**
* Gets the document from the canvas in this editor model.
*
* @return the document
*/
public GraphDocument getDocument() {
return canvas.getDocument();
}
/**
* @return the breadcrumb
*/
public BreadcrumbViewer<OpGraph, ?> getBreadcrumb() {
return breadcrumb;
}
/**
* @return the nodeDefaults
*/
public NodeDefaultsPanel getNodeDefaults() {
return nodeDefaults;
}
/**
* @return the debugPanel
*/
public ContextViewerPanel getDebugInfoPanel() {
return debugPanel;
}
/**
* @return the nodeLibrary
*/
public NodeLibraryViewer getNodeLibrary() {
return nodeLibrary;
}
/**
* @return the nodeSettings
*/
public NodeSettingsPanel getNodeSettings() {
return nodeSettings;
}
/**
* @return immutable list of menu providers
*/
public List<MenuProvider> getMenuProviders() {
return Collections.unmodifiableList(menuProviders);
}
//
// GraphCanvasSelectionListener
//
private final GraphCanvasSelectionListener graphSelectionListener = new GraphCanvasSelectionListener() {
@Override
public void nodeSelectionChanged(Collection<OpNode> old, Collection<OpNode> selected) {
OpNode node = null;
if(selected.size() == 1)
node = selected.iterator().next();
nodeDefaults.setNode(node);
nodeSettings.setNode(node);
debugPanel.setNode(node);
}
};
}