/*
* 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.examples.app;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
import ca.gedge.opgraph.app.GraphDocument;
import ca.gedge.opgraph.app.GraphEditorModel;
import ca.gedge.opgraph.app.MenuProvider;
import ca.gedge.opgraph.app.components.PathAddressableMenuImpl;
import ca.gedge.opgraph.app.components.canvas.GridLayer;
/**
* A frame holding a {@link GraphEditor}.
*/
public class GraphEditor extends JFrame {
/** Logger */
private static final Logger LOGGER = Logger.getLogger(GraphEditor.class.getName());
/** The graph editor model */
private GraphEditorModel model;
/** A reference to the menu bar */
private PathAddressableMenuImpl menuBar;
/** Container component containing debug components */
private JComponent debugComponents;
/**
* Default constructor.
*/
GraphEditor() {
super("OpGraph Editor");
// Initialize model and document
this.model = new GraphEditorModel();
GraphEditorModel.setActiveEditorModel(model);
// Set up components
setupWindow();
// Menu bar
final JMenuBar mb = new JMenuBar();
menuBar = new PathAddressableMenuImpl(mb);
for(MenuProvider menu : model.getMenuProviders())
menu.installItems(model, menuBar);
setJMenuBar(mb);
// Root pane state
final GraphDocument document = model.getCanvas().getDocument();
document.addPropertyChangeListener(GraphDocument.SOURCE, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(getRootPane() != null)
getRootPane().putClientProperty("Window.documentFile", evt.getNewValue());
}
});
document.addPropertyChangeListener(GraphDocument.UNDO_STATE, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
getRootPane().putClientProperty("Window.documentModified", document.hasModifications());
}
});
document.addPropertyChangeListener(GraphDocument.PROCESSING_CONTEXT, new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
debugComponents.setVisible(evt.getNewValue() != null);
}
});
//
setSize(1000, 650);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(windowAdapter);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
model.getCanvas().requestFocusInWindow();
}
});
}
/**
* Initializes the docking window.
*/
private void setupWindow() {
// Scroll pane for canvas
final JScrollPane canvasScrollPane = new JScrollPane();
canvasScrollPane.setViewportView(model.getCanvas());
canvasScrollPane.setColumnHeaderView(model.getBreadcrumb());
canvasScrollPane.setBorder(null);
canvasScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
canvasScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
canvasScrollPane.getHorizontalScrollBar().setUnitIncrement(GridLayer.DEFAULT_GRID_SPACING / 10);
canvasScrollPane.getHorizontalScrollBar().setBlockIncrement(GridLayer.DEFAULT_GRID_SPACING);
canvasScrollPane.getVerticalScrollBar().setUnitIncrement(GridLayer.DEFAULT_GRID_SPACING / 10);
canvasScrollPane.getVerticalScrollBar().setBlockIncrement(GridLayer.DEFAULT_GRID_SPACING);
// Scroll pane for console
final JScrollPane consolePane = new JScrollPane(model.getConsolePanel());
consolePane.setBorder(null);
// Scroll pane for debug
final JScrollPane debugScrollPane = new JScrollPane(model.getDebugInfoPanel());
debugScrollPane.setBorder(null);
// Tabbed pane for debug components
final JTabbedPane debugTabPane = new JTabbedPane();
debugTabPane.add("Debug", debugScrollPane);
debugTabPane.add("Console", consolePane);
debugTabPane.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, Color.LIGHT_GRAY));
debugTabPane.setPreferredSize(new Dimension(300, 1));
debugComponents = debugTabPane;
debugComponents.setVisible(false);
// Tabbed pane for debug components
final JTabbedPane nodeTabPane = new JTabbedPane();
nodeTabPane.add("Defaults", model.getNodeDefaults());
nodeTabPane.add("Settings", model.getNodeSettings());
nodeTabPane.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.LIGHT_GRAY));
nodeTabPane.setPreferredSize(new Dimension(300, 1));
// Node library, change border
final JComponent nodeLibrary = model.getNodeLibrary();
nodeLibrary.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.LIGHT_GRAY));
// Layout top
final JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(nodeTabPane, BorderLayout.WEST);
topPanel.add(canvasScrollPane, BorderLayout.CENTER);
topPanel.add(debugTabPane, BorderLayout.EAST);
// Main split pane for top elements and library viewer
final JSplitPane mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
mainSplitPane.setBorder(null);
mainSplitPane.setTopComponent(topPanel);
mainSplitPane.setBottomComponent(nodeLibrary);
mainSplitPane.setDividerSize(3);
mainSplitPane.setDividerLocation(400);
// Add to frame
add(mainSplitPane, BorderLayout.CENTER);
}
//
// WindowAdapter
//
private final WindowAdapter windowAdapter = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
final GraphDocument document = model.getCanvas().getDocument();
if(document.checkForReset()) {
GraphEditor.this.setVisible(false);
GraphEditor.this.dispose();
}
}
};
/**
* Program entry point.
*
* @param args program arguments
*/
public static void main(String [] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
//UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(ClassNotFoundException exc) {
LOGGER.warning("Unable to set LaF");
} catch(InstantiationException exc) {
LOGGER.warning("Unable to set LaF");
} catch(IllegalAccessException exc) {
LOGGER.warning("Unable to set LaF");
} catch(UnsupportedLookAndFeelException exc) {
LOGGER.warning("Unable to set LaF");
}
final JFrame frame = new GraphEditor();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
});
}
}