1 19 20 21 package org.netbeans.modules.properties; 22 23 24 import java.awt.event.*; 25 import java.awt.Rectangle ; 26 import java.beans.PropertyChangeEvent ; 27 import java.beans.PropertyChangeListener ; 28 import java.lang.ref.SoftReference ; 29 import java.util.HashSet ; 30 import java.util.Set ; 31 import javax.swing.DefaultComboBoxModel ; 32 import javax.swing.JButton ; 33 import javax.swing.JComponent ; 34 import javax.swing.JDialog ; 35 import javax.swing.JTable ; 36 import javax.swing.JTextField ; 37 import javax.swing.KeyStroke ; 38 import javax.swing.SwingUtilities ; 39 import org.openide.DialogDescriptor; 40 import org.openide.DialogDisplayer; 41 import org.openide.util.actions.SystemAction; 42 import org.openide.util.NbBundle; 43 import org.openide.util.RequestProcessor; 44 import org.openide.util.WeakListeners; 45 46 47 54 public class FindPerformer extends javax.swing.AbstractAction 55 implements PropertyChangeListener { 56 57 58 private JTable table; 59 60 61 private String findString; 62 63 69 private int[] searchValues; 70 71 72 private boolean highlightSearch = true; 73 74 75 private boolean matchCaseSearch = false; 76 77 78 private boolean backwardSearch = false; 79 80 81 private boolean wrapSearch = true; 82 83 84 private boolean rowSearch = true; 85 86 87 private final ActionListener findNextActionListener; 88 89 90 private final ActionListener findPreviousActionListener; 91 92 93 private final ActionListener toggleHighlightListener; 94 95 96 private Set <String > history = new HashSet <String >(); 97 98 99 private TableViewSettings settings; 100 101 { 103 findNextActionListener = new ActionListener() { 104 public void actionPerformed(ActionEvent evt) { 105 if(searchValues != null) { 107 synchronized(this) { 108 backwardSearch = false; 109 performSearch(); 110 } 111 } 112 } 113 }; 114 findPreviousActionListener = new ActionListener() { 115 public void actionPerformed(ActionEvent evt) { 116 if(searchValues != null) { 118 synchronized(this) { 119 backwardSearch = true; 120 performSearch(); 121 } 122 } 123 } 124 }; 125 126 toggleHighlightListener = new ActionListener() { 127 public void actionPerformed(ActionEvent evt) { 128 highlightSearch = !highlightSearch; 130 table.repaint(); 131 } 132 }; 133 } 135 136 private static SoftReference <FindPerformer> softRef; 137 138 139 private static JDialog findDialog; 140 141 142 public static final String TABLE_SEARCH_RESULT = "table.search.result"; 144 145 146 private FindPerformer(JTable table) { 147 this.table = table; 148 149 settings = TableViewSettings.getDefault(); 150 settings.addPropertyChangeListener( 151 WeakListeners.propertyChange(this, settings) 152 ); 153 154 registerKeyStrokes(); 155 } 156 157 158 161 public void propertyChange(PropertyChangeEvent evt) { 162 registerKeyStrokes(); 164 } 165 166 167 public static FindPerformer getFindPerformer(JTable table) { 168 if(softRef != null) { 169 FindPerformer fp = softRef.get(); 170 if(fp != null) { 171 if(!fp.validateTable(table)) { 172 fp.resetTable(table); 173 fp.registerKeyStrokes(); 174 } 175 return fp; 176 } 177 } 178 179 FindPerformer fp = new FindPerformer(table); 180 softRef = new SoftReference <FindPerformer>(fp); 181 182 return fp; 183 } 184 185 186 private void resetTable(JTable table) { 187 this.table = table; 188 } 189 190 191 private boolean validateTable(JTable table) { 192 if(this.table != null && this.table.equals(table)) 193 return true; 194 195 return false; 196 } 197 198 199 private synchronized void registerKeyStrokes() { 200 KeyStroke [] keyStrokes = settings.getKeyStrokesFindNext(); 202 for(int i=0; i<keyStrokes.length; i++) { 203 table.registerKeyboardAction( 204 findNextActionListener, 205 keyStrokes[i], 206 JComponent.WHEN_IN_FOCUSED_WINDOW 207 ); 208 } 209 210 keyStrokes = settings.getKeyStrokesFindPrevious(); 211 for(int i=0; i<keyStrokes.length; i++) { 212 table.registerKeyboardAction( 213 findPreviousActionListener, 214 keyStrokes[i], 215 JComponent.WHEN_IN_FOCUSED_WINDOW 216 ); 217 } 218 219 keyStrokes = settings.getKeyStrokesToggleHighlight(); 220 for(int i=0; i<keyStrokes.length; i++) { 221 table.registerKeyboardAction( 222 toggleHighlightListener, 223 keyStrokes[i], 224 JComponent.WHEN_IN_FOCUSED_WINDOW 225 ); 226 } 227 } 228 229 230 public String getFindString() { 231 return findString; 232 } 233 234 235 public boolean isHighlightSearch() { 236 return highlightSearch; 237 } 238 239 240 public void actionPerformed(java.awt.event.ActionEvent e) { 241 if(findDialog == null) 242 createFindDialog(); 243 else { 244 findDialog.setVisible(true); 246 findDialog.requestFocusInWindow(); 247 } 248 } 249 250 251 private void createFindDialog() { 252 final JDialog dialog; 253 final FindPanel panel = new FindPanel(); 254 DialogDescriptor dd = new DialogDescriptor( 255 panel, 256 NbBundle.getBundle(FindPerformer.class).getString("LBL_Title"), false, new JButton [0], null, DialogDescriptor.DEFAULT_ALIGN, 261 null, null ); 264 265 dialog = (javax.swing.JDialog )DialogDisplayer.getDefault().createDialog(dd); 266 267 findDialog = dialog; 269 270 dialog.getRootPane().setDefaultButton(panel.getButtons()[0]); 272 dialog.setFocusable(false); 273 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 274 275 panel.getButtons()[0].addActionListener( 278 new ActionListener() { 279 public void actionPerformed(ActionEvent evt) { 280 findString = ((JTextField )panel.getComboBox().getEditor().getEditorComponent()).getText(); 281 282 highlightSearch = panel.getHighlightCheck().isSelected(); 284 matchCaseSearch = panel.getMatchCaseCheck().isSelected(); 285 backwardSearch = panel.getBackwardCheck().isSelected(); 286 wrapSearch = panel.getWrapCheck().isSelected(); 287 rowSearch = panel.getRowCheck().isSelected(); 288 289 dialog.dispose(); 290 291 if(findString != null && !findString.trim().equals("")) { 292 293 history.add(findString.intern()); 294 295 performSearch(); 296 } 297 298 table.repaint(); 300 } 301 } 302 ); 303 304 panel.getButtons()[1].addActionListener( 306 new ActionListener() { 307 public void actionPerformed(ActionEvent evt) { 308 dialog.dispose(); 309 } 310 } 311 ); 312 313 dialog.addWindowListener(new WindowAdapter() { 314 public void windowClosed(WindowEvent e) { 315 findDialog = null; 316 } 317 }); 318 319 panel.getHighlightCheck().setSelected(highlightSearch); 321 panel.getMatchCaseCheck().setSelected(matchCaseSearch); 322 panel.getBackwardCheck().setSelected(backwardSearch); 323 panel.getWrapCheck().setSelected(wrapSearch); 324 panel.getRowCheck().setSelected(rowSearch); 325 326 panel.getComboBox().setModel(new DefaultComboBoxModel (history.toArray())); 328 if (findString != null) 330 panel.getComboBox().setSelectedItem(findString); 331 332 dialog.setVisible(true); 333 panel.requestFocusInWindow(); 334 } 335 336 337 public void closeFindDialog() { 338 if(findDialog != null) { 339 synchronized(findDialog) { 340 findDialog.setVisible(false); 341 findDialog.dispose(); 342 findDialog = null; 343 } 344 } 345 } 346 347 350 private void prepareSearch() { 351 int row = table.getSelectedRow(); 352 int column = table.getSelectedColumn(); 353 354 if(searchValues != null && row == searchValues[0] && column == searchValues[1]) 356 return; 357 358 359 if(row != -1 || column != -1) { 360 int startOffset, endOffset; 362 startOffset = endOffset = ((JTextField )((PropertiesTableCellEditor)table.getCellEditor(row, column)).getComponent()).getCaretPosition(); 363 364 searchValues = new int[] {row, column, startOffset, endOffset}; 365 } else { 366 if(backwardSearch) { 368 int lastRow = table.getRowCount()-1; 369 int lastColumn = table.getColumnCount()-1; 370 int startOffset, endOffset; 371 372 startOffset = endOffset = ((PropertiesTableModel.StringPair)table.getValueAt(lastRow, lastColumn)).getValue().length()-1; 373 374 searchValues = new int[] {lastRow, lastColumn, startOffset, endOffset}; 375 } else { 376 searchValues = new int[] {0, 0, 0, 0}; 377 } 378 } 379 380 } 381 382 383 private synchronized void performSearch() { 384 prepareSearch(); 385 PropertiesRequestProcessor.getInstance().post( 387 new Runnable () { 388 public void run() { 389 boolean wrap = false; 391 392 do { 393 final int[] result = search(searchValues[0], searchValues[1], backwardSearch ? searchValues[2]-1 : searchValues[3]); 394 395 if(wrapSearch && !wrap && result == null) { 396 398 if(backwardSearch) { 400 int lastRow = table.getRowCount()-1; 401 int lastColumn = table.getColumnCount()-1; 402 403 searchValues = new int[] {lastRow, 404 lastColumn, 405 ((PropertiesTableModel.StringPair)table.getValueAt(lastRow, lastColumn)).getValue().length()-1, 406 0}; 407 } else { 408 searchValues = new int[] {0, 0, 0, 0}; 409 } 410 411 wrap = true; 412 } else { 413 if(result != null) { 414 searchValues = result; 416 417 SwingUtilities.invokeLater(new Runnable () { 418 public void run() { 419 if (table.getAutoscrolls()) { 421 Rectangle cellRect = table.getCellRect(result[0], result[1], false); 422 if (cellRect != null) { 423 table.scrollRectToVisible(cellRect); 424 } 425 } 426 if (table.isEditing()) { 428 440 table.getCellEditor().stopCellEditing(); 441 } 442 table.getColumnModel().getSelectionModel().setSelectionInterval(result[1], result[1]); 443 table.getSelectionModel().setSelectionInterval(result[0], result[0]); 444 table.editCellAt(result[0], result[1]); 446 } 447 }); 448 } 449 450 searchValues = result; 452 453 wrap = false; 454 } 455 } while (wrap); 456 } } 458 ); 459 } 460 461 467 private int[] search(int startRow, int startColumn, int startOffset) { 468 boolean firstIteration = true; 470 471 for(int i= rowSearch ? startRow : startColumn; 473 backwardSearch ? i>=0 : i<(rowSearch ? table.getRowCount() : table.getColumnCount()); 474 i = backwardSearch ? i-1 : i+1 ) { 475 for(int j= rowSearch ? startColumn : startRow; 477 backwardSearch ? j>=0 : j<(rowSearch ? table.getColumnCount() : table.getRowCount()); 478 j = backwardSearch ? j-1 : j+1) { 479 int row = rowSearch ? i : j; 481 int column = rowSearch ? j : i; 482 483 String str = ((PropertiesTableModel.StringPair)table.getValueAt(row, column)).toString(); 484 if(str == null || str.length() < findString.length()) 486 continue; 487 488 if(!firstIteration) 489 startOffset = backwardSearch ? str.length()-findString.length() : 0; 490 491 int offset = containsFindString(str, startOffset); 492 493 if(offset>=0) { 494 table.putClientProperty(TABLE_SEARCH_RESULT, new int[] {row, column, offset, offset+findString.length()}); 497 return new int[] {row, column, offset, offset+findString.length()}; 498 } 499 500 if(firstIteration) firstIteration = false; 501 } 502 503 if(rowSearch) 505 startColumn = backwardSearch ? table.getColumnCount()-1 : 0; 506 else 507 startRow = backwardSearch ? table.getRowCount()-1 : 0; 508 } 509 510 return null; 511 } 512 513 517 private int containsFindString(String str, int startOffset) { 518 if(startOffset < 0 || startOffset >= str.length()) 519 return -1; 520 521 for(int i=startOffset; 522 backwardSearch ? i>=0 : i<(str.length()-findString.length()+1); 523 i = backwardSearch ? i-1 : i+1) { 524 525 if(findString.regionMatches(!matchCaseSearch, 0, str, i, findString.length())) 526 return i; 527 } 528 529 return -1; 530 } 531 532 } 533 | Popular Tags |