1 package prefuse.util.ui; 2 3 import java.awt.Color ; 4 import java.awt.Dimension ; 5 import java.awt.Font ; 6 import java.awt.Graphics ; 7 import java.awt.event.ActionEvent ; 8 import java.awt.event.ActionListener ; 9 import java.awt.event.MouseEvent ; 10 import java.awt.event.MouseListener ; 11 12 import javax.swing.BorderFactory ; 13 import javax.swing.Box ; 14 import javax.swing.BoxLayout ; 15 import javax.swing.JComponent ; 16 import javax.swing.JLabel ; 17 import javax.swing.JPanel ; 18 import javax.swing.JTextField ; 19 import javax.swing.event.DocumentEvent ; 20 import javax.swing.event.DocumentListener ; 21 import javax.swing.text.Document ; 22 23 import prefuse.Visualization; 24 import prefuse.data.Tuple; 25 import prefuse.data.event.TupleSetListener; 26 import prefuse.data.search.PrefixSearchTupleSet; 27 import prefuse.data.search.SearchTupleSet; 28 import prefuse.data.tuple.TupleSet; 29 import prefuse.util.ColorLib; 30 31 37 public class JSearchPanel extends JPanel 38 implements DocumentListener , ActionListener 39 { 40 private Object m_lock; 41 private SearchTupleSet m_searcher; 42 43 private JTextField m_queryF = new JTextField (15); 44 private JLabel m_resultL = new JLabel (" "); 45 private JLabel m_searchL = new JLabel ("search >> "); 46 private Box m_sbox = new Box (BoxLayout.X_AXIS); 47 48 private String [] m_fields; 49 50 private Color m_cancelColor = ColorLib.getColor(255,75,75); 51 52 private boolean m_includeHitCount = false; 53 private boolean m_monitorKeys = false; 54 private boolean m_autoIndex = true; 55 56 private boolean m_showBorder = true; 57 private boolean m_showCancel = true; 58 59 62 67 public JSearchPanel(SearchTupleSet search, String field) { 68 this(search, field, false); 69 } 70 71 79 public JSearchPanel(SearchTupleSet search, String field, 80 boolean monitorKeystrokes) 81 { 82 this(null, search, new String [] {field}, false, monitorKeystrokes); 83 } 84 85 94 public JSearchPanel(TupleSet source, SearchTupleSet search, 95 String [] fields, boolean autoIndex, boolean monitorKeystrokes) 96 { 97 m_lock = new Object (); 98 m_fields = fields; 99 m_autoIndex = autoIndex; 100 m_monitorKeys = monitorKeystrokes; 101 102 m_searcher = ( search != null ? search : new PrefixSearchTupleSet() ); 103 104 init(source); 105 } 106 107 110 116 public JSearchPanel(Visualization vis, String field) { 117 this(vis, Visualization.ALL_ITEMS, field, true); 118 } 119 120 127 public JSearchPanel(Visualization vis, String group, String field) { 128 this(vis, group, field, true); 129 } 130 131 141 public JSearchPanel(Visualization vis, String group, String field, 142 boolean autoIndex) 143 { 144 this(vis, group, Visualization.SEARCH_ITEMS, 145 new String [] {field}, autoIndex, false); 146 } 147 148 161 public JSearchPanel(Visualization vis, String group, String field, 162 boolean autoIndex, boolean monitorKeystrokes) 163 { 164 this(vis, group, Visualization.SEARCH_ITEMS, 165 new String [] {field}, autoIndex, true); 166 } 167 168 182 public JSearchPanel(Visualization vis, String group, String searchGroup, 183 String field, boolean autoIndex, boolean monitorKeystrokes) 184 { 185 this(vis, group, searchGroup, new String [] {field}, autoIndex, 186 monitorKeystrokes); 187 } 188 189 203 public JSearchPanel(Visualization vis, String group, String searchGroup, 204 String [] fields, boolean autoIndex, boolean monitorKeystrokes) 205 { 206 m_lock = vis; 207 m_fields = fields; 208 m_autoIndex = autoIndex; 209 m_monitorKeys = monitorKeystrokes; 210 211 TupleSet search = vis.getGroup(searchGroup); 212 213 if ( search != null ) { 214 if ( search instanceof SearchTupleSet ) { 215 m_searcher = (SearchTupleSet)search; 216 } else { 217 throw new IllegalStateException ( 218 "Search focus set not instance of SearchTupleSet!"); 219 } 220 } else { 221 m_searcher = new PrefixSearchTupleSet(); 222 vis.addFocusGroup(searchGroup, m_searcher); 223 } 224 225 init(vis.getGroup(group)); 226 } 227 228 231 private void init(TupleSet source) { 232 if ( m_autoIndex && source != null ) { 233 for ( int i=0; i < m_fields.length; i++ ) 235 m_searcher.index(source.tuples(), m_fields[i]); 236 237 source.addTupleSetListener(new TupleSetListener() { 239 public void tupleSetChanged(TupleSet tset, 240 Tuple[] add, Tuple[] rem) 241 { 242 if ( add != null ) { 243 for ( int i=0; i<add.length; ++i ) { 244 for ( int j=0; j<m_fields.length; j++ ) 245 m_searcher.index(add[i], m_fields[j]); 246 } 247 } 248 if ( rem != null && m_searcher.isUnindexSupported() ) { 249 for ( int i=0; i<rem.length; ++i ) { 250 for ( int j=0; j<m_fields.length; j++ ) 251 m_searcher.unindex(rem[i], m_fields[j]); 252 } 253 } 254 } 255 }); 256 } 257 258 m_queryF.addActionListener(this); 259 if ( m_monitorKeys ) 260 m_queryF.getDocument().addDocumentListener(this); 261 m_queryF.setMaximumSize(new Dimension (400, 100)); 262 m_queryF.setPreferredSize(new Dimension (200, 20)); 263 m_queryF.setBorder(null); 264 setBackground(Color.WHITE); 265 initUI(); 266 } 267 268 private void initUI() { 269 this.removeAll(); 270 this.setLayout(new BoxLayout (this, BoxLayout.X_AXIS)); 271 272 m_sbox.removeAll(); 273 m_sbox.add(Box.createHorizontalStrut(3)); 274 m_sbox.add(m_queryF); 275 m_sbox.add(Box.createHorizontalStrut(3)); 276 if ( m_showCancel ) { 277 m_sbox.add(new CancelButton()); 278 m_sbox.add(Box.createHorizontalStrut(3)); 279 } 280 if ( m_showBorder ) 281 m_sbox.setBorder(BorderFactory.createLineBorder(getForeground())); 282 else 283 m_sbox.setBorder(null); 284 m_sbox.setMaximumSize(new Dimension (400, 100)); 285 m_sbox.setPreferredSize(new Dimension (171, 20)); 286 287 Box b = new Box (BoxLayout.X_AXIS); 288 if ( m_includeHitCount ) { 289 b.add(m_resultL); 290 b.add(Box.createHorizontalStrut(10)); 291 } 293 b.add(m_searchL); 294 b.add(Box.createHorizontalStrut(3)); 295 b.add(m_sbox); 296 297 this.add(b); 298 } 299 300 302 305 public void requestFocus() { 306 this.m_queryF.requestFocus(); 307 } 308 309 313 public void setLock(Object lock) { 314 m_lock = lock; 315 } 316 317 321 public void setShowResultCount(boolean b) { 322 this.m_includeHitCount = b; 323 initUI(); 324 validate(); 325 } 326 327 331 public void setShowBorder(boolean b) { 332 m_showBorder = b; 333 initUI(); 334 validate(); 335 } 336 337 341 public void setShowCancel(boolean b) { 342 m_showCancel = b; 343 initUI(); 344 validate(); 345 } 346 347 350 protected void searchUpdate() { 351 String query = m_queryF.getText(); 352 synchronized ( m_lock ) { 353 m_searcher.search(query); 354 if ( m_searcher.getQuery().length() == 0 ) 355 m_resultL.setText(null); 356 else { 357 int r = m_searcher.getTupleCount(); 358 m_resultL.setText(r + " match" + (r==1?"":"es")); 359 } 360 } 361 } 362 363 367 public void setQuery(String query) { 368 Document d = m_queryF.getDocument(); 369 d.removeDocumentListener(this); 370 m_queryF.setText(query); 371 if ( m_monitorKeys ) 372 d.addDocumentListener(this); 373 searchUpdate(); 374 } 375 376 380 public String getQuery() { 381 return m_queryF.getText(); 382 } 383 384 389 public void setCancelColor(Color c) { 390 m_cancelColor = c; 391 } 392 393 396 public void setBackground(Color bg) { 397 super.setBackground(bg); 398 if ( m_queryF != null ) m_queryF.setBackground(bg); 399 if ( m_resultL != null ) m_resultL.setBackground(bg); 400 if ( m_searchL != null ) m_searchL.setBackground(bg); 401 } 402 403 406 public void setForeground(Color fg) { 407 super.setForeground(fg); 408 if ( m_queryF != null ) { 409 m_queryF.setForeground(fg); 410 m_queryF.setCaretColor(fg); 411 } 412 if ( m_resultL != null ) m_resultL.setForeground(fg); 413 if ( m_searchL != null ) m_searchL.setForeground(fg); 414 if ( m_sbox != null && m_showBorder ) 415 m_sbox.setBorder(BorderFactory.createLineBorder(fg)); 416 } 417 418 421 public void setOpaque(boolean opaque) { 422 super.setOpaque(opaque); 423 if ( m_queryF != null ) { 424 m_queryF.setOpaque(opaque); 425 } 426 if ( m_resultL != null ) m_resultL.setOpaque(opaque); 427 if ( m_searchL != null ) m_searchL.setOpaque(opaque); 428 } 429 430 433 public void setFont(Font f) { 434 super.setFont(f);; 435 if ( m_queryF != null ) m_queryF.setFont(f); 436 if ( m_resultL != null ) m_resultL.setFont(f); 437 if ( m_searchL != null ) m_searchL.setFont(f); 438 } 439 440 444 public void setLabelText(String text) { 445 m_searchL.setText(text); 446 } 447 448 449 452 public void changedUpdate(DocumentEvent e) { 453 searchUpdate(); 454 } 455 458 public void insertUpdate(DocumentEvent e) { 459 searchUpdate(); 460 } 461 464 public void removeUpdate(DocumentEvent e) { 465 searchUpdate(); 466 } 467 468 471 public void actionPerformed(ActionEvent e) { 472 Object src = e.getSource(); 473 if ( src == m_queryF ) { 474 searchUpdate(); 475 } 476 } 477 478 482 public class CancelButton extends JComponent implements MouseListener { 483 484 private boolean hover = false; 485 private int[] outline = new int[] { 486 0,0, 2,0, 4,2, 5,2, 7,0, 9,0, 9,2, 7,4, 7,5, 9,7, 9,9, 487 7,9, 5,7, 4,7, 2,9, 0,9, 0,7, 2,5, 2,4, 0,2, 0,0 488 }; 489 private int[] fill = new int[] { 490 1,1,8,8, 1,2,7,8, 2,1,8,7, 7,1,1,7, 8,2,2,8, 1,8,8,1 491 }; 492 493 public CancelButton() { 494 Dimension d = new Dimension (10,10); 496 this.setPreferredSize(d); 497 this.setMinimumSize(d); 498 this.setMaximumSize(d); 499 500 this.setFocusable(false); 502 503 this.addMouseListener(this); 505 } 506 507 public void paintComponent(Graphics g) { 508 if ( hover ) { g.setColor(m_cancelColor); 510 for ( int i=0; i+3 < fill.length; i+=4 ) { 511 g.drawLine(fill[i],fill[i+1],fill[i+2],fill[i+3]); 512 } 513 } 514 g.setColor(JSearchPanel.this.getForeground()); 515 for ( int i=0; i+3 < outline.length; i+=2 ) { 516 g.drawLine(outline[i], outline[i+1], 517 outline[i+2], outline[i+3]); 518 } 519 } 520 521 public void mouseClicked(MouseEvent arg0) { 522 setQuery(null); 523 } 524 525 public void mousePressed(MouseEvent arg0) { 526 } 527 528 public void mouseReleased(MouseEvent arg0) { 529 } 530 531 public void mouseEntered(MouseEvent arg0) { 532 hover = true; 533 repaint(); 534 } 535 536 public void mouseExited(MouseEvent arg0) { 537 hover = false; 538 repaint(); 539 } 540 541 } 543 } | Popular Tags |