package gui.subspacePanel; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import javax.swing.JDialog; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import controller.Subspace; import controller.SubspaceController; /** * The dialog, shown to select or search for a new subspace. */ public class SubspaceChooseDialog extends JPanel { private static final long serialVersionUID = 2297719658462819379L; /** * The parent frame in which this dialog is shown. */ private final JDialog parentFrame; /** * The {@link SubspaceController} to get the subspaces from. */ private final SubspaceController subspaceController; /** * A list with all existing subspaces. */ private Subspace[] subspaces; /** * A list with the filtered subspaces. */ private Subspace[] visibleSubspaces; /** * The text field to enter the search query. */ private final JTextField search; /** * The list, visualized in the UI. */ private final JList subspaceList; /** * Constructor of a new choose dialog. * * @param parentFrame * the dialog frame this dialog belongs to * @param subspaceController * the {@link SubspaceController} to get the subspaces from */ public SubspaceChooseDialog(final JDialog parentFrame, final SubspaceController subspaceController) { if (parentFrame == null || subspaceController == null) { throw new IllegalArgumentException("parentFrame or subspaceController was null"); } // init the dialog this.parentFrame = parentFrame; this.subspaceController = subspaceController; this.setLayout(new BorderLayout()); this.setBackground(new Color(0xff99d1f4)); this.setVisible(true); search = new JTextField(""); subspaceList = new JList(); subspaceList.setBackground(new Color(0xff99d1f4)); subspaceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); subspaceList.setLayoutOrientation(JList.VERTICAL); subspaceList.addKeyListener(new java.awt.event.KeyListener() { @Override public void keyTyped(KeyEvent e) { actKeyEvent(e); } @Override public void keyReleased(KeyEvent e) { // nothing to do } @Override public void keyPressed(KeyEvent e) { // nothing to do } }); subspaceList.addMouseListener(new MouseListener() { @Override public void mouseReleased(MouseEvent arg0) { // nothing to do } @Override public void mousePressed(MouseEvent arg0) { // nothing to do } @Override public void mouseExited(MouseEvent arg0) { // nothing to do } @Override public void mouseEntered(MouseEvent arg0) { // nothing to do } @Override public void mouseClicked(MouseEvent arg0) { if (subspaceList.getSelectedIndex() >= 0) { subspaceController.setActiveSubspace(visibleSubspaces[subspaceList.getSelectedIndex()]); parentFrame.setVisible(false); } } }); search.addKeyListener(new java.awt.event.KeyListener() { @Override public void keyTyped(KeyEvent e) { actKeyEvent(e); } @Override public void keyReleased(KeyEvent e) { updateList(); } @Override public void keyPressed(KeyEvent e) { // If the up or down arrow keys are pressed, jump out of the text field and move the selection if (e.getKeyCode() == KeyEvent.VK_DOWN) { subspaceList.setSelectedIndex(subspaceList.getSelectedIndex() + 1); subspaceList.requestFocusInWindow(); } else if (e.getKeyCode() == KeyEvent.VK_UP) { subspaceList.setSelectedIndex(subspaceList.getSelectedIndex() - 1); subspaceList.requestFocusInWindow(); } } }); JScrollPane scrollPane = new JScrollPane(subspaceList); this.add(search, BorderLayout.PAGE_START); this.add(scrollPane, BorderLayout.CENTER); } /** * The methods updates the internal list of subspaces and updates all displays. * * @param subspaces * the new list of subspaces */ public void updateView(Subspace[] subspaces) { if (subspaces == null) { throw new IllegalArgumentException("Subspaces was null"); } this.subspaces = subspaces; this.subspaceList.setListData(subspaces); this.subspaceList.setVisibleRowCount(15); search.selectAll(); search.requestFocusInWindow(); updateList(); } /** * This method determines the pressed key and acts to it. * * @param e * the released key event */ private void actKeyEvent(KeyEvent e) { switch (e.getKeyChar()) { case KeyEvent.VK_ENTER: // select a new active subspace if (subspaceList.getSelectedIndex() >= 0) { this.subspaceController.setActiveSubspace(visibleSubspaces[subspaceList.getSelectedIndex()]); this.parentFrame.setVisible(false); } break; case KeyEvent.VK_ESCAPE: // exit the dialog this.parentFrame.setVisible(false); break; default: break; } } /** * Instant Search * * This method updates the shown list of subspaces, checking the search query. */ private void updateList() { // split the search query to get single words String[] searchQuery = search.getText().toLowerCase().trim().split("[\\s]"); ArrayList<Subspace> newList = new ArrayList<Subspace>(); // iterate the subspaces and check if it reaches the search query for (Subspace current : subspaces) { boolean found = true; // Check single search queries, if the subspace name contains it for (String currentSearch : searchQuery) { if (!current.toString().toLowerCase().contains(currentSearch)) { // if one query is not contained, exit the loop found = false; break; } } // the name contains all queries, so add it to the result list if (found) { newList.add(current); } } // copy the ArrayList to an Array and update the dialog Subspace[] newListArray = new Subspace[newList.size()]; newList.toArray(newListArray); this.subspaceList.setListData(newListArray); visibleSubspaces = newListArray; // move the selection to the currently active subspace, if it is still visible subspaceList.setSelectedIndex(0); for (int i = 0; i < visibleSubspaces.length; i++) { if (subspaceController.getActiveSubspace().equals(visibleSubspaces[i])) { subspaceList.setSelectedIndex(i); } } } }