/*
* JFLAP - Formal Languages and Automata Package
*
*
* Susan H. Rodger
* Computer Science Department
* Duke University
* August 27, 2009
* Copyright (c) 2002-2009
* All rights reserved.
* JFLAP is open source software. Please see the LICENSE for terms.
*
*/
package gui.grammar.parse;
import grammar.*;
import grammar.parse.*;
import gui.SuperMouseAdapter;
import gui.grammar.GrammarTable;
import gui.grammar.GrammarTableModel;
import gui.grammar.ImmutableGrammarTableModel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
/**
* This allows a user to specify sets of items.
*
* @author Thomas Finley
*/
public class ItemSetChooser {
/**
* Instantiates a new item set chooser for a grammar.
*
* @param grammar
* the grammar to create the item set chooser for
*/
public ItemSetChooser(Grammar grammar, Component parent) {
this.grammar = grammar;
this.parent = parent;
chooseTable = new GrammarTable(new ImmutableGrammarTableModel(grammar));
chooseTable.addMouseListener(GTListener);
choiceTable = new GrammarTable(new ImmutableGrammarTableModel());
JScrollPane p = new JScrollPane(chooseTable);
p.setPreferredSize(new Dimension(200, 200));
panel.add(p, BorderLayout.WEST);
p = new JScrollPane(choiceTable);
p.setPreferredSize(new Dimension(200, 200));
panel.add(p, BorderLayout.EAST);
// Set up the tool bar.
JToolBar bar = new JToolBar();
bar.add(new AbstractAction("Closure") {
public void actionPerformed(ActionEvent e) {
closure();
}
});
bar.add(new AbstractAction("Finish") {
public void actionPerformed(ActionEvent e) {
finish();
}
});
panel.add(bar, BorderLayout.NORTH);
}
/**
* This will add the closure of all selected items in choice to the choice.
*/
private void closure() {
HashSet selected = new HashSet();
GrammarTableModel model = choiceTable.getGrammarModel();
for (int i = 0; i < model.getRowCount() - 1; i++)
if (choiceTable.isRowSelected(i))
selected.add(model.getProduction(i));
if (selected.size() == 0) {
JOptionPane.showMessageDialog(parent,
"Select an item (or items) in the right table.",
"Nothing Selected", JOptionPane.ERROR_MESSAGE);
return;
}
Set closureSet = Operations.closure(grammar, selected);
closureSet.removeAll(alreadyChosen);
Iterator it = closureSet.iterator();
while (it.hasNext())
addItem((Production) it.next());
}
/**
* This will complete the items in choice.
*/
private void finish() {
if (restricted == null) {
JOptionPane.showMessageDialog(parent,
"There is no one right answer in this case.", "Ambiguity",
JOptionPane.ERROR_MESSAGE);
return;
}
HashSet toAdd = new HashSet(restricted);
toAdd.removeAll(alreadyChosen);
Iterator it = toAdd.iterator();
while (it.hasNext())
addItem((Production) it.next());
}
/**
* This will bring up a dialog box allowing a user to specify item sets.
*
* @param items
* the target item set in the event that the user is being asked
* to give some information that is already known, or null
* if there is no prearranged target
* @param message
* a small message to display to the user
* @return an array containing the items the user selected, or null
* if the user cancelled the action
*/
public Production[] getItemSet(Set items, String message) {
restricted = items;
choiceTable.setModel(new ImmutableGrammarTableModel());
alreadyChosen = new HashSet();
while (true) {
int choice = JOptionPane.showConfirmDialog(parent, panel, message,
JOptionPane.OK_CANCEL_OPTION);
if (choice == JOptionPane.CANCEL_OPTION)
return null;
// Get those selected.
List selected = new ArrayList();
GrammarTableModel model = choiceTable.getGrammarModel();
for (int i = 0; i < model.getRowCount() - 1; i++)
selected.add(model.getProduction(i));
// Check if it's our target.
if (items != null) {
Set selectedSet = new HashSet(selected);
if (!selectedSet.equals(items)) {
JOptionPane.showMessageDialog(parent,
"Some items are missing!", "Items Missing",
JOptionPane.ERROR_MESSAGE);
continue;
}
}
return (Production[]) selected.toArray(new Production[0]);
}
}
/**
* This method should be called when an item should be added.
*
* @param item
* the item that was selected for addition
*/
private void addItem(Production item) {
if (restricted != null && !restricted.contains(item)) {
JOptionPane.showMessageDialog(parent, item.toString()
+ " is not part of the set.", "Item not Desirable",
JOptionPane.ERROR_MESSAGE);
return;
}
if (alreadyChosen.contains(item)) {
JOptionPane.showMessageDialog(parent, item.toString()
+ " is already chosen.", "Item Already Chosen",
JOptionPane.ERROR_MESSAGE);
return;
}
alreadyChosen.add(item);
choiceTable.getGrammarModel().addProduction(item);
}
private final GrammarTableListener GTListener = new GrammarTableListener();
private class GrammarTableListener extends SuperMouseAdapter {
public void mouseClicked(MouseEvent event) {
GrammarTable gt = (GrammarTable) event.getSource();
Point at = event.getPoint();
int row = gt.rowAtPoint(at);
if (row == -1)
return;
if (row == gt.getGrammarModel().getRowCount() - 1)
return;
Production p = gt.getGrammarModel().getProduction(row);
Production[] pItems = Operations.getItems(p);
JPopupMenu menu = new JPopupMenu();
ItemMenuListener itemListener = new ItemMenuListener(p);
for (int i = 0; i < pItems.length; i++) {
JMenuItem item = new JMenuItem(pItems[i].toString());
item.setActionCommand(pItems[i].getRHS());
item.addActionListener(itemListener);
menu.add(item);
}
menu.show(gt, at.x, at.y);
}
}
private class ItemMenuListener implements ActionListener {
public ItemMenuListener(Production p) {
prod = p;
}
public void actionPerformed(ActionEvent event) {
String rhs = event.getActionCommand();
Production p = new Production(prod.getLHS(), rhs);
addItem(p);
}
Production prod;
}
/** The parent for dialog boxes. */
private Component parent;
/** This is the pane for the grammar. */
private JPanel panel = new JPanel(new BorderLayout());
/** Productions we can choose items from. */
private GrammarTable chooseTable;
/** What items we have already chosen. */
private GrammarTable choiceTable;
/**
* Items able to be added are restricted to this set. If null, there are no
* restrictions.
*/
private Set restricted = null;
/** The items that have been added sofar are listed here. */
private Set alreadyChosen;
/** The grammar for the item set chooser. */
private Grammar grammar;
}