/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2015 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.tracker;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JToolBar;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ProxyLookup;
import org.openide.windows.TopComponent;
/**
*
* @author Neil C Smith (http://neilcsmith.net)
*/
@NbBundle.Messages({
"label.pattern=Pattern",
"label.rows=Rows",
"label.columns=Columns",
"dialog.delete.title=Confirm deletion",
"dialog.delete.message=Delete last pattern?",
"dialog.close.title=Unsaved changes",
"dialog.close.message=Contains unsaved changes. Close anyway?"
})
@TopComponent.Description(preferredID = "TrackerEditor",
persistenceType = TopComponent.PERSISTENCE_NEVER)
public final class TrackerTopComponent extends TopComponent {
private final static String RESOURCE_DIR = "net/neilcsmith/praxis/live/tracker/resources/";
private final TrackerDataObject dob;
private final Listener listener;
private Patterns patterns;
private TrackerTable table;
private JComboBox<String> patternSelect;
private JSpinner rowSpinner;
private JSpinner columnSpinner;
private JButton addButton;
private JButton removeButton;
private boolean modified;
TrackerTopComponent(TrackerDataObject dob) {
this.dob = dob;
setDisplayName(dob.getPrimaryFile().getName());
associateLookup(new ProxyLookup(dob.getLookup(),
Lookups.singleton(getActionMap())));
setLayout(new BorderLayout());
listener = new Listener();
patterns = new Patterns();
initTable();
initTopToolbar();
initBottomToolbar();
updatePatterns(patterns);
}
private void initTable() {
table = new TrackerTable();
add(new JScrollPane(table), BorderLayout.CENTER);
getActionMap().setParent(table.getActionMap());
}
private void initTopToolbar() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
patternSelect = new JComboBox<>();
patternSelect.addActionListener(listener);
toolbar.add(patternSelect);
toolbar.addSeparator();
removeButton = new JButton(
ImageUtilities.loadImageIcon(RESOURCE_DIR + "delete.png", true));
removeButton.addActionListener(listener);
addButton = new JButton(
ImageUtilities.loadImageIcon(RESOURCE_DIR + "add.png", true));
addButton.addActionListener(listener);
toolbar.add(removeButton);
toolbar.add(addButton);
toolbar.addSeparator();
add(toolbar, BorderLayout.NORTH);
}
private void initBottomToolbar() {
JToolBar toolbar = new JToolBar();
toolbar.setFloatable(false);
rowSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 512, 1));
rowSpinner.addChangeListener(listener);
columnSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 32, 1));
columnSpinner.addChangeListener(listener);
toolbar.add(new JLabel(Bundle.label_rows()));
toolbar.addSeparator();
toolbar.add(rowSpinner);
toolbar.addSeparator();
toolbar.add(new JLabel(Bundle.label_columns()));
toolbar.addSeparator();
toolbar.add(columnSpinner);
add(toolbar, BorderLayout.SOUTH);
}
@Override
protected void componentClosed() {
super.componentClosed();
dob.editorClosed(this);
}
@Override
public boolean canClose() {
if (modified) {
NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
Bundle.dialog_close_message(),
Bundle.dialog_close_title(),
NotifyDescriptor.YES_NO_OPTION);
if (!NotifyDescriptor.YES_OPTION.equals(
DialogDisplayer.getDefault().notify(nd))) {
return false;
}
}
return super.canClose();
}
void updatePatterns(Patterns patterns) {
listener.ignore = true;
this.patterns = patterns;
if (patterns.size() == 0) {
patterns.addPattern(new Pattern(16, 4));
}
configurePatternSelect();
table.setModel(patterns.getPattern(0));
configureDimensions();
listener.ignore = false;
}
void finishEditing() {
if (table.isEditing()) {
if (!table.getCellEditor().stopCellEditing()) {
table.getCellEditor().cancelCellEditing();
}
}
}
private void configurePatternSelect() {
patternSelect.removeAllItems();
for (int i = 0; i < patterns.size(); i++) {
patternSelect.addItem(Bundle.label_pattern() + " : " + i);
}
patternSelect.setSelectedIndex(0);
}
private void addPattern() {
Pattern pattern = new Pattern(16, 4);
patterns.addPattern(pattern);
patternSelect.addItem(Bundle.label_pattern() + " : "
+ patternSelect.getItemCount());
patternSelect.setSelectedIndex(patternSelect.getItemCount() - 1);
table.setModel(pattern);
configureDimensions();
}
private void removePattern() {
int count = patterns.size();
if (count < 2) {
return;
}
NotifyDescriptor nd = new NotifyDescriptor.Confirmation(
Bundle.dialog_delete_message(),
Bundle.dialog_delete_title(),
NotifyDescriptor.YES_NO_OPTION);
if (NotifyDescriptor.YES_OPTION.equals(DialogDisplayer.getDefault().notify(nd))) {
Pattern pattern = patterns.removePattern(count - 1);
patternSelect.removeItemAt(patternSelect.getItemCount() - 1);
if (pattern == table.getModel()) {
patternSelect.setSelectedIndex(0);
table.setModel(patterns.getPattern(0));
configureDimensions();
}
}
}
private void configureDimensions() {
DefaultTableModel model = (DefaultTableModel) table.getModel();
rowSpinner.setValue(model.getRowCount());
columnSpinner.setValue(model.getColumnCount());
}
void setModified(boolean modified) {
if (this.modified == modified) {
return;
}
this.modified = modified;
if (modified) {
setHtmlDisplayName("<html><b>" + dob.getPrimaryFile().getName() + "</b>");
} else {
setHtmlDisplayName(null);
}
}
private class Listener implements ActionListener, ChangeListener {
private boolean ignore;
@Override
public void actionPerformed(ActionEvent e) {
if (ignore) {
return;
}
ignore = true;
Object source = e.getSource();
if (source == patternSelect) {
int p = patternSelect.getSelectedIndex();
if (p >= 0 && p < patterns.size()) {
table.setModel(patterns.getPattern(p));
configureDimensions();
}
} else if (source == addButton) {
addPattern();
} else if (source == removeButton) {
removePattern();
} else {
}
ignore = false;
}
@Override
public void stateChanged(ChangeEvent e) {
if (ignore) {
return;
}
ignore = true;
DefaultTableModel model = (DefaultTableModel) table.getModel();
if (e.getSource() == rowSpinner) {
model.setRowCount((int) rowSpinner.getValue());
} else if (e.getSource() == columnSpinner) {
model.setColumnCount((int) columnSpinner.getValue());
}
ignore = false;
}
}
}