/*******************************************************************************
* Copyright (c) 2012-present Jakub Kováč, Jozef Brandýs, Katarína Kotrlová,
* Pavol Lukča, Ladislav Pápay, Viktor Tomkovič, Tatiana Tóthová
*
* 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 algvis.ui;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Hashtable;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.undo.StateEditable;
import algvis.core.Algorithm;
import algvis.core.DataStructure;
import algvis.core.history.HashtableStoreSupport;
import algvis.internationalization.ChLabel;
import algvis.internationalization.IButton;
import algvis.internationalization.ICheckBox;
/**
* The Class Buttons. This is a panel with standard buttons such as input field,
* the "Next", "Clear", and "Random" buttons, "Pause" checkbox, label with
* statistics, and "Zoom in/Zoom out" buttons. Panels with data
* structure-specific buttons (such "Insert" or "Delete") are created by
* extending this class (see for example classes DictButtons, PQButtons).
*/
abstract public class Buttons extends JPanel implements ActionListener,
StateEditable {
private static final long serialVersionUID = 1417759004124906334L;
protected final VisPanel panel;
protected final DataStructure D;
public InputField I;
private IButton previous;
protected IButton next;
private IButton clear;
protected IButton random;
private IButton save;
private ICheckBox pause;
private ChLabel stats;
private String statsText;
private JButton zoomIn;
private JButton zoomOut;
private JButton resetView;
protected final String hash = Integer.toString(hashCode());
protected abstract void actionButtons(JPanel P);
protected void actionButtons2(JPanel P) {
}
protected Buttons(VisPanel panel) {
this.panel = panel;
D = panel.D;
assert D != null : "data structure not initialized yet";
final JPanel first = initFirstRow();
final JPanel second = initSecondRow();
final JPanel third = initThirdRow();
final JPanel statsPanel = initStats();
// put everything together
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(first);
add(second);
if (third != null) {
add(third);
}
add(statsPanel);
setBorder(BorderFactory.createTitledBorder(""));
}
// input field, actions (insert, find, delete,...), previous, next
JPanel initFirstRow() {
final JPanel first = new JPanel();
first.setLayout(new FlowLayout());
I = new InputField(5, panel.statusBar, panel.S);
first.add(I);
actionButtons(first);
initPrevious();
initNext();
first.add(previous);
first.add(next);
actionButtons2(first);
return first;
}
// [x] pause, clear, random, zoom in/out
JPanel initSecondRow() {
final JPanel second = new JPanel();
initPause();
initClear();
initRandom();
// initSave();
initZoom();
second.setLayout(new FlowLayout());
second.add(pause);
second.add(clear);
if (random != null) {
second.add(random);
}
// second.add(save);
// second.add(zoomLabel);
// second.add(zoomIn);
// second.add(zoomOut);
second.add(resetView);
otherButtons(second);
return second;
}
protected JPanel initThirdRow() {
return null;
}
// statistics
JPanel initStats() {
final JPanel statsPanel = new JPanel();
statsPanel.setLayout(new FlowLayout());
stats = new ChLabel(D.stats());
statsText = stats.getText();
statsPanel.add(stats);
return statsPanel;
}
void initPrevious() {
previous = new IButton("previous");
previous.setMnemonic(KeyEvent.VK_O);
previous.setEnabled(false);
previous.addActionListener(this);
}
void initNext() {
next = new IButton("next");
next.setMnemonic(KeyEvent.VK_N);
next.setEnabled(false);
next.addActionListener(this);
}
void initPause() {
pause = new ICheckBox("button-pause", true);
pause.setMnemonic(KeyEvent.VK_P);
pause.addActionListener(this);
}
void initClear() {
clear = new IButton("button-clear");
clear.setMnemonic(KeyEvent.VK_C);
clear.addActionListener(this);
}
protected void initRandom() {
random = new IButton("button-random");
random.setMnemonic(KeyEvent.VK_R);
random.addActionListener(this);
}
// TODO
// public void initSave() {
// save = new IButton("button-save");
// save.setMnemonic(KeyEvent.VK_S);
// save.setEnabled(panel.scenario.isEnabled());
// save.addActionListener(this);
// }
private JButton createButton(String alt, String path) {
final java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new JButton(new ImageIcon(imgURL));
} else {
System.err.println("Couldn't find file: " + path);
return new JButton(alt);
}
}
void initZoom() {
// zoomLabel = new ILabel("zoomio");
// zoomIn = createButton("+", "../images/zoom_in.gif");
zoomIn = createButton("+", "/algvis/images/zoom_in.gif");
zoomOut = createButton("-", "/algvis/images/zoom_out.gif");
resetView = createButton("R", "/algvis/images/reset.gif");
zoomIn.addActionListener(this);
zoomOut.addActionListener(this);
resetView.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent evt) {
I.sb.setText(" ");
if (evt.getSource() == previous) {
if (panel.history.canUndo()) {
if (panel.pauses) {
panel.history.undo();
} else {
panel.history.undoAlgorithm();
}
panel.refresh();
}
} else if (evt.getSource() == next) {
final Algorithm a = panel.D.getA();
if (panel.history.canRedo()) {
if (panel.pauses) {
panel.history.redo();
} else {
panel.history.redoAlgorithm();
}
panel.refresh();
}
} else if (evt.getSource() == clear) {
D.start(new Algorithm(panel) {
@Override
public void runAlgorithm() {
D.clear();
}
});
} else if (evt.getSource() == random) {
D.random(I.getInt(10));
} else if (evt.getSource() == pause) {
panel.pauses = pause.isSelected();
} else if (evt.getSource() == zoomIn) {
panel.screen.V.zoomIn();
} else if (evt.getSource() == zoomOut) {
panel.screen.V.zoomOut();
} else if (evt.getSource() == save) {
// TODO
} else if (evt.getSource() == resetView) {
panel.screen.V.resetView();
}
I.requestFocusInWindow();
}
public void setOtherEnabled(boolean enabled) {
clear.setEnabled(enabled);
if (random != null) {
random.setEnabled(enabled);
}
}
public void refresh() {
previous.setEnabled(panel.history.canUndo());
next.setEnabled(panel.history.canRedo()
|| (panel.D.getA() != null && !panel.D.getA().isDone()));
setOtherEnabled(panel.history.isBetweenAlgorithms());
refreshStats();
}
public void setStats(String s) {
statsText = s;
}
void refreshStats() {
if (!statsText.equals(stats.getText())) {
stats.setText(statsText);
stats.refresh();
}
}
protected void otherButtons(JPanel P) {
}
@Override
public Dimension getMaximumSize() {
return new Dimension(Integer.MAX_VALUE, 150);
}
@Override
public void storeState(Hashtable<Object, Object> state) {
HashtableStoreSupport.store(state, hash + "statsText", statsText);
}
@Override
public void restoreState(Hashtable<?, ?> state) {
final Object statsText = state.get(hash + "statsText");
if (statsText != null) {
this.statsText = (String) HashtableStoreSupport.restore(statsText);
}
}
}