booleanexpressioneditor.java
字号:
package piy.support;
import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import javax.swing.event.*;
import java.awt.event.*;
import piy.*;
import java.io.File;
import java.util.*;
/**
* Frame in which user can edit boolean expressions. Relies on PIY for comparator descriptors.
* <p>
* Muse: Should this be made a singleton?
* <p>
* This class is suspiciously similar to ActionListEditor - REFACTOR!
* @author David Vivash
* @version 1.0, 30/04/01
*/
public class BooleanExpressionEditor extends JFrame implements ActionListener, ChangeListener {
private static final String OR_BEFORE = "orBefore";
private static final String OR_AFTER = "orAfter";
private static final String AND_BEFORE = "andBefore";
private static final String AND_AFTER = "andAfter";
private static final String DELETE = "delete";
private static final String SWAP = "swap";
private Color selectionColor = new Color(190, 170, 250);
private BooleanComparable rootExpression = null;
//The action descriptor that has currently been selected on the toolbar
private ActionDescriptor toolbarSelection = null;
private JScrollPane scroller = null;
private ExpressionViewer viewer = null;
private ScrollingButtonPanel[] comparatorPanel = null;
private JTabbedPane tabPane = null;
private PropertiesPanel propertiesPanel = new PropertiesPanel();
private BooleanExpressionEditor editor = null;
private ExpressionIcon selected = null;
private ExpressionIcon rootIcon = null;
private static final int ADD = 0;
private static final int SELECT = 1;
private int editType = SELECT;
private Property whereBound = null;
private ActionDescriptor[] comparatorDescriptors = null;
public BooleanExpressionEditor(BooleanComparable comparable, Property whereBound) {
super("Boolean Expression Editor");
rootExpression = comparable;
comparatorDescriptors = PIY.getInstance().getComparators();
editor = this;
this.whereBound = whereBound;
getContentPane().setLayout(new BorderLayout());
JPanel topPanel = new JPanel() {
public void paint(Graphics g) {
super.paint(g);
g.setColor(getBackground().darker());
g.drawLine(60,2,60,getHeight()-8);
g.setColor(getBackground().brighter());
g.drawLine(61,2,61,getHeight()-8);
}
};
topPanel.setLayout(new BorderLayout());
//---- Set up toolbar buttons -------
JPanel toolbarButtons = new JPanel();
toolbarButtons.setLayout(null);
toolbarButtons.setPreferredSize(new Dimension(120,60));
String sep = File.separator;
String images = "piy" + sep + "images" + sep;
FloatingButton andBefore = new FloatingButton(new ImageIcon(images + "insertbefore.gif").getImage(), AND_BEFORE, false);
andBefore.addActionListener(this);
andBefore.setBounds(4, 6, 22, 22);
andBefore.setToolTipText("Insert AND before");
FloatingButton andAfter = new FloatingButton(new ImageIcon(images + "insertafter.gif").getImage(), AND_AFTER, false);
andAfter.addActionListener(this);
andAfter.setBounds(30, 6, 22, 22);
andAfter.setToolTipText("Insert AND after");
FloatingButton orBefore = new FloatingButton(new ImageIcon(images + "orbefore.gif").getImage(), OR_BEFORE, false);
orBefore.addActionListener(this);
orBefore.setBounds(4, 34, 22, 22);
orBefore.setToolTipText("Insert OR above");
FloatingButton orAfter = new FloatingButton(new ImageIcon(images + "orafter.gif").getImage(), OR_AFTER, false);
orAfter.addActionListener(this);
orAfter.setBounds(30, 34, 22, 22);
orAfter.setToolTipText("Insert OR below");
FloatingButton delete = new FloatingButton(new ImageIcon(images + "bin.gif").getImage(), DELETE, false);
delete.addActionListener(this);
delete.setBounds(64, 20, 22, 22);
delete.setToolTipText("Delete Selected");
FloatingButton swap = new FloatingButton(new ImageIcon(images + "swap.gif").getImage(), SWAP, false);
swap.addActionListener(this);
swap.setBounds(90, 20, 22, 22);
swap.setToolTipText("Swap Order");
toolbarButtons.add(andBefore);
toolbarButtons.add(andAfter);
toolbarButtons.add(orBefore);
toolbarButtons.add(orAfter);
toolbarButtons.add(delete);
toolbarButtons.add(swap);
//------ Set up comparator buttons panel -----
tabPane = new JTabbedPane();
ArrayList collections = sortCategories();
comparatorPanel = new ScrollingButtonPanel[collections.size()];
FloatingButton toolButton = null;
ActionDescriptor[] descriptors = null;
for (int i=0; i<collections.size(); i++) {
descriptors = (ActionDescriptor[])collections.get(i);
comparatorPanel[i] = new ScrollingButtonPanel(descriptors.length, 26, 26, 4);
tabPane.addTab(descriptors[0].getCategory(), comparatorPanel[i]);
comparatorPanel[i].addChangeListener(this);
for (int j=0; j<descriptors.length; j++) {
comparatorPanel[i].addButton(toolButton = new FloatingButton(descriptors[j].getIcon(), ""+j, true));
//where the action descriptor is located in the actionDescriptors array
int num = findDescriptor(descriptors[j]);
toolButton.setIdentifier(num);
toolButton.setToolTipText(descriptors[j].getName());
}
}
//Move the "General" tab to be the first tab in the pane
int posOfGeneral = tabPane.indexOfTab("General");
if (posOfGeneral != -1) {
if (posOfGeneral != 0) {
Component generalPanel = tabPane.getComponentAt(posOfGeneral);
tabPane.removeTabAt(posOfGeneral);
tabPane.insertTab("General", null, generalPanel, null, 0);
}
}
topPanel.add(toolbarButtons, BorderLayout.WEST);
topPanel.add(tabPane, BorderLayout.CENTER);
JPanel padding = new JPanel();
padding.setPreferredSize(new Dimension(0,8));
topPanel.add(padding, BorderLayout.SOUTH);
// propertiesPanel = new JPanel();
propertiesPanel.setPreferredSize(new Dimension(180,100));
propertiesPanel.setMaximumSize(new Dimension(400,100));
propertiesPanel.setMinimumSize(new Dimension(50,100));
viewer = new ExpressionViewer();
scroller = new JScrollPane(viewer);
JSplitPane bottomPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, propertiesPanel, scroller);
propertiesPanel.setPreferredSize(new Dimension(180,100));
getContentPane().add(topPanel, BorderLayout.NORTH);
getContentPane().add(bottomPanel, BorderLayout.CENTER);
setSize(400,300);
}
/**
* Find the specified Descriptor's location in the comparatorDescriptors array
* @param descriptor the descriptor to search for
* @return the descriptor's location in the comparatorDescriptors array, or -1 if it was not found
*/
private int findDescriptor(ActionDescriptor descriptor) {
for (int i=0; i<comparatorDescriptors.length; i++)
if (descriptor == comparatorDescriptors[i])
return i;
return -1;
}
/**
* Retrieve the ActionDescriptor for a particular comparator class type.
* @param comparator the class of the comparator whose action descriptor is required
* @return the action descriptor of the specified comparator class, or null if an
* an appropriate descriptor was not found
*/
protected ActionDescriptor getDescriptor(Class comparator) {
//The NullAction will not be present in the descriptor array
if (comparator == NullComparator.class) return NullComparatorDescriptor.getInstance();
for (int i=0; i<comparatorDescriptors.length; i++)
if (comparatorDescriptors[i].getDescribedClass() == comparator)
return comparatorDescriptors[i];
return null;
}
/**
* Selects the specified icon, deselcting the last one.
* @param icon the ExpressionIcon to select
*/
protected void select(ExpressionIcon icon) {
if (selected != null) selected.setBackground(Color.white);
selected = icon;
if (selected != null) selected.setBackground(selectionColor);
viewer.repaint();
propertiesPanel.setup(icon == null ? null : icon.getComparable());
}
//----- ChangeListener method ------------
private boolean editting = false;
public void stateChanged(ChangeEvent e) {
if (!editting) {
ScrollingButtonPanel inside = (ScrollingButtonPanel)tabPane.getSelectedComponent();
int pos = inside.getSelectedIndex();
editting = true;
//Clear selections on other tabs now
for (int i=0; i<comparatorPanel.length; i++)
if (comparatorPanel[i] != inside) comparatorPanel[i].clearSelection();
//TO DO!!!! Get the action descriptor that was selected
if (pos == -1) {
toolbarSelection = null;
} else {
FloatingButton button = (FloatingButton)inside.getSelectedButton();
toolbarSelection = comparatorDescriptors[button.getIdentifier()];
}
editting = false;
if (pos == -1) editType = SELECT;
else editType = ADD;
}
}
/**
* Takes the comparator descriptors, and sorts them into a collection of arrays - each array contains
* descriptors of comparators in the same category. So sorts out all of the string comparators from
* the files comparators, for example. Each entry in the array list returned is an ActionDescriptor[].
* <p>
* <b>This method needs refactoring.</b> This method is the same (virtually) as the sortCategories
* method in the ActionListEditor. Maybe it could be moved to a PIYUtilities class.
* @return a collection of ActionDescriptor arrays, with each array containing descriptors in the
* same category.
*/
private ArrayList sortCategories() {
//generate a map from each category name to the number of actions in that category
//ie categoryName(String) -> Count(Inteeger)
HashMap nameToCount = new HashMap(comparatorDescriptors.length);
Integer num = null;
for (int i=0; i<comparatorDescriptors.length; i++) {
num = (Integer)nameToCount.get(comparatorDescriptors[i].getCategory());
if (num == null) //category name doesn't yet exist
num = new Integer(1);
else
num = new Integer(num.intValue() + 1);
nameToCount.put(comparatorDescriptors[i].getCategory(), num);
}
//Now construct each array and store it in the arraylist to return.
//We could return an array of ActionDescriptor arrays, but I think that's a bit
//too confusing
ArrayList toReturn = new ArrayList(nameToCount.size());
ActionDescriptor[] array = null;
String currentName = null;
int arrayCounter = 0;
//Iterate over each named category
Iterator nameIterator = nameToCount.keySet().iterator();
while (nameIterator.hasNext()) {
currentName = (String)nameIterator.next();
array = new ActionDescriptor[((Integer)nameToCount.get(currentName)).intValue()];
arrayCounter = 0;
for (int j=0; j<comparatorDescriptors.length; j++) {
if (comparatorDescriptors[j].getCategory().equals(currentName)) {
array[arrayCounter] = comparatorDescriptors[j];
arrayCounter++;
}
}
toReturn.add(array);
}
return toReturn;
}
public boolean getNegate() { return selected == null ? false : selected.getComparable().getNegate(); }
public void setNegate(boolean negate) {
if (selected == null) return;
selected.getComparable().setNegate(negate);
negate(selected);
}
protected void negate(ExpressionIcon icon) {
icon.setBorder(new LineBorder(icon.getComparable().getNegate() ? Color.red : Color.black, 1));
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command == AND_BEFORE || command == OR_BEFORE) {
ExpressionIcon parentIcon = selected.getParentIcon();
if (parentIcon == null) {
rootExpression = new BooleanExpression();
((BooleanExpression)rootExpression).setFirst(new NullComparator());
((BooleanExpression)rootExpression).setSecond(selected.getComparable());
whereBound.setValue(rootExpression);
if (command == OR_BEFORE) ((BooleanExpression)rootExpression).setAnd(false);
rootIcon.setup(rootExpression, null);
} else {
BooleanExpression ex = new BooleanExpression();
ex.setFirst(new NullComparator());
ex.setSecond(selected.getComparable());
if (command == OR_BEFORE) ex.setAnd(false);
if (((BooleanExpression)parentIcon.getComparable()).getFirst() == selected.getComparable()) ((BooleanExpression)parentIcon.getComparable()).setFirst(ex);
else ((BooleanExpression)parentIcon.getComparable()).setSecond(ex);
rootIcon.setup(rootExpression, null);
}
} else if (command == AND_AFTER || command == OR_AFTER) {
ExpressionIcon parentIcon = selected.getParentIcon();
if (parentIcon == null) {
rootExpression = new BooleanExpression();
((BooleanExpression)rootExpression).setSecond(new NullComparator());
((BooleanExpression)rootExpression).setFirst(selected.getComparable());
whereBound.setValue(rootExpression);
if (command == OR_AFTER) ((BooleanExpression)rootExpression).setAnd(false);
rootIcon.setup(rootExpression, null);
} else {
BooleanExpression ex = new BooleanExpression();
ex.setSecond(new NullComparator());
ex.setFirst(selected.getComparable());
if (command == OR_AFTER) ex.setAnd(false);
if (((BooleanExpression)parentIcon.getComparable()).getFirst() == selected.getComparable()) ((BooleanExpression)parentIcon.getComparable()).setFirst(ex);
else ((BooleanExpression)parentIcon.getComparable()).setSecond(ex);
rootIcon.setup(rootExpression, null);
}
} else if (command == SWAP) {
if ((selected != null) && (selected.getComparable() instanceof BooleanExpression)) {
BooleanExpression toSwap = (BooleanExpression)selected.getComparable();
if (toSwap instanceof BooleanExpression) {
BooleanComparable temp = toSwap.getFirst();
toSwap.setFirst(toSwap.getSecond());
toSwap.setSecond(temp);
selected.setup(selected.getComparable(), selected.getParentIcon());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -