package org.hwo.ui; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.LinkedList; import java.util.List; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.SingleSelectionModel; import javax.swing.Timer; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import org.hwo.datetime.JTimeOfDay; import org.hwo.models.TableMapper.TableMapper; import org.hwo.ui.wellknown.WellKnown; import org.hwo.ui.wellknown.WellKnownClass; import org.hwo.ui.wellknown.WellKnownSearch; public class JSearchTextField extends JTextField implements FocusListener { private Class searchClazz; private JTable tResults; private TableMapper tmResults; private JPopupMenu popupList; private Timer searchTimer; private WellKnownClass wellKnownClass; private WellKnownSearch wellKnownSearch; private Object selectedObject; private List actionListeners; public JSearchTextField() { actionListeners = new LinkedList(); setPreferredSize(new Dimension(120, 24)); searchClazz = null; popupList = new JPopupMenu(); popupList.setFocusable(false); JScrollPane scrollPane = new JScrollPane(); tResults = new JTable(); tResults.setCellSelectionEnabled(false); tResults.setColumnSelectionAllowed(false); tResults.setRowSelectionAllowed(true); scrollPane.setViewportView(tResults); popupList.add(scrollPane); addFocusListener(this); getDocument().addDocumentListener(new DocumentListener() { @Override public void removeUpdate(DocumentEvent arg0) { } @Override public void insertUpdate(DocumentEvent arg0) { searchTimer.stop(); searchTimer.start(); showPopup(); } @Override public void changedUpdate(DocumentEvent arg0) { //showPopup(); } }); KeyStrokeHelper helper = new KeyStrokeHelper(this); helper.registerKeyStrokeListener(new KeyStrokeListener() { @Override public void keyStroke(KeyStrokeParameters parameters) { switch (parameters.getKeyCode()) { case KeyEvent.VK_ESCAPE: popupList.setVisible(false); break; case KeyEvent.VK_UP: selectionUp(); break; case KeyEvent.VK_DOWN: selectionDown(); break; case KeyEvent.VK_ENTER: selectObject(); break; } } }); helper.addKeyCode(KeyEvent.VK_ESCAPE) .addKeyCode(KeyEvent.VK_UP) .addKeyCode(KeyEvent.VK_DOWN) .addKeyCode(KeyEvent.VK_ENTER); searchTimer = new Timer(250, new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { search(); } }); searchTimer.setRepeats(false); } @Override public synchronized void addActionListener(ActionListener l) { actionListeners.add(l); } @Override public synchronized void removeActionListener(ActionListener l) { actionListeners.remove(l); } protected void fireNewActionPerformed() { for (ActionListener l:actionListeners) l.actionPerformed(new ActionEvent(this, 0, "")); } private void selectObject() { if (!popupList.isVisible()) return; Object o = tmResults.getSelectedRow(); if (o != null) { setSelectedObject(o); fireNewActionPerformed(); transferFocus(); } } private void search() { System.err.println("searching..."); if (wellKnownSearch != null) { List l = wellKnownSearch.keywordSearch(searchClazz, getText()); tmResults.setRows(l); } } private void selectionDown() { if (!popupList.isVisible()) showPopup(); if (tResults.getSelectedRow()!=-1) { if (tResults.getSelectedRow() < tmResults.getRowCount() - 1) { tResults.setRowSelectionInterval(tResults.getSelectedRow() + 1,tResults.getSelectedRow() + 1); System.err.println("down"); } } else { System.err.println("Select first"); tResults.setRowSelectionInterval(0, 0); } selectedObject = null; } private void selectionUp() { if (!popupList.isVisible()) return; if (tResults.getSelectedRow()!=-1) { if (tResults.getSelectedRow() > 0) { tResults.setRowSelectionInterval(tResults.getSelectedRow()-1,tResults.getSelectedRow()-1); System.err.println("up"); } } else { System.err.println("Select last"); tResults.setRowSelectionInterval(tmResults.getRowCount() - 1, tmResults.getRowCount() - 1); } selectedObject = null; } private void showPopup() { if (searchClazz == null) return; if (!popupList.isVisible()) { popupList.setPopupSize(getSize().width, 250); popupList.show(this, 0, getHeight()); popupList.setVisible(true); grabFocus(); } } @Override public void focusGained(FocusEvent arg0) { if (selectedObject != null) selectAll(); } @Override public void focusLost(FocusEvent arg0) { if (popupList.isVisible()) popupList.setVisible(false); } public Class getSearchClazz() { return searchClazz; } public void setSearchClazz(Class searchClazz) { this.searchClazz = searchClazz; tmResults = new TableMapper(searchClazz, tResults); tmResults.setReadOnly(true); tmResults.setEditorEnabled(false); tResults.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if ((e.getButton() == MouseEvent.BUTTON1) && (e.getClickCount() == 2)) { Object so = tmResults.getSelectedRow(); if (so != null) { setSelectedObject(so); } } } }); wellKnownClass = WellKnown.getWellKnownClass(searchClazz); if (wellKnownClass != null) { if (wellKnownClass.search() != null) { Class clazz = wellKnownClass.search(); try { wellKnownSearch = clazz.newInstance(); wellKnownSearch.setClazz(searchClazz); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } public void setMaxPopupHeight(int maxPopupHeight) { Dimension dim = popupList.getMaximumSize(); dim.height = maxPopupHeight; popupList.setMaximumSize(dim); } public int getMaxPopupHeight() { return (int)popupList.getMaximumSize().getHeight(); } public Object getSelectedObject() { return selectedObject; } public void setSelectedObject(Object selectedObject) { this.selectedObject = selectedObject; if (selectedObject == null) { setText(""); } else { setText(WellKnown.getDisplayLabel(selectedObject)); } popupList.setVisible(false); fireNewActionPerformed(); } }