package cz.cuni.lf1.lge.ThunderSTORM.results;
import java.awt.Cursor;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class OperationsHistoryPanel extends JPanel {
private List<LabelWithCheckbox> stack;
private JLabel historyLabel;
private final static String LABEL = "Post-processing history: ";
private final static String LABEL_EMPTY = "Post-processing history: -";
public OperationsHistoryPanel() {
stack = new ArrayList<LabelWithCheckbox>();
this.setLayout(new FlowLayout(FlowLayout.LEFT, 3, 0));
historyLabel = new JLabel(OperationsHistoryPanel.LABEL_EMPTY);
add(historyLabel);
}
List<Operation> getHistory() {
List<Operation> history = new ArrayList<Operation>();
for(LabelWithCheckbox item : stack) {
history.add(item.op);
}
return history;
}
public void addOperation(Operation op) {
if(!stack.isEmpty() && !stack.get(stack.size() - 1).isChecked()) {
removeLastOperation();
}
//add arrow
JLabel arrow = null;
if(!stack.isEmpty()) {
arrow = new JLabel("\u2192");
add(arrow);
} else {
historyLabel.setText(OperationsHistoryPanel.LABEL);
}
LabelWithCheckbox opLabel = new LabelWithCheckbox(op, arrow);
add(opLabel);
stack.add(opLabel);
disableNextToLastCheckbox();
revalidate();
}
public Operation getLastOperation() {
return stack.isEmpty() ? null : stack.get(stack.size() - 1).getOperation();
}
public boolean isLastOperationUndone() {
if(!stack.isEmpty()) {
return !stack.get(stack.size() - 1).isChecked();
} else {
return false;
}
}
public void removeAllOperations() {
stack.clear();
removeAll();
historyLabel.setText(OperationsHistoryPanel.LABEL_EMPTY);
add(historyLabel);
repaint();
}
public Operation removeLastOperation() {
int opCount = stack.size();
if(opCount > 0) {
LabelWithCheckbox last = stack.remove(opCount - 1);
if(last.arrow != null) {
remove(last.arrow); //remove preceding arrow
}
remove(last);
revalidate();
repaint();
return last.getOperation();
}
return null;
}
public void disableNextToLastCheckbox() {
int opCount = stack.size();
if(opCount > 1) {
LabelWithCheckbox nextToLast = stack.get(opCount - 2);
nextToLast.removeCheckbox();
}
}
public void undoOrRedoLastOperation() {
if(!stack.isEmpty()) {
JCheckBox chb = stack.get(stack.size() - 1).chb;
if(chb != null) {
chb.doClick();
}
}
}
class LabelWithCheckbox extends JPanel {
Operation op;
transient JCheckBox chb;
transient JLabel lab;
transient JLabel arrow;
public LabelWithCheckbox(final Operation op, JLabel arrow) {
this.op = op;
this.arrow = arrow;
setLayout(new FlowLayout(FlowLayout.LEFT, 3, 0));
setBorder(javax.swing.BorderFactory.createEtchedBorder());
//label
lab = new JLabel(op.getName());
lab.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
lab.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
op.clicked();
}
});
add(lab);
//checkbox
if(op.isUndoAble()) {
chb = new JCheckBox();
chb.setBorder(null);
chb.setSelected(true);
chb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(chb.isSelected()) {
op.redo();
} else {
op.undo();
}
TableHandlerPlugin.recordUndoOrRedo();
}
});
add(chb);
}
}
public void removeCheckbox() {
if(chb != null) {
remove(chb);
chb = null;
revalidate();
}
}
public boolean isChecked() {
return chb == null ? true : chb.isSelected();
}
public Operation getOperation() {
return op;
}
}
public static abstract class Operation {
protected abstract String getName();
protected boolean isUndoAble() {
return false;
}
protected void clicked() {
}
protected void undo() {
}
protected void redo() {
}
}
}