org.netbeans.modules.properties.FindPerformer Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.properties;
import java.awt.event.*;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.Set;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.NbBundle;
import org.openide.util.WeakListeners;
/**
* FindPerformer is a performer of the FindAction which is invoked on Resource Bundles table view component.
* Does actual dirty job, search on the actual activated table and sets the results as highlighted text on particular cell.
*
* @author Peter Zavadsky
* @author Marian Petras
*/
public class FindPerformer extends javax.swing.AbstractAction
implements PropertyChangeListener {
/** Table on which perform the search. */
private JTable table;
/** String to find. */
private String findString;
/** Stores values which are used to start search from and store the results for next search.
* 1st item - row index of cell with found string,
* 2nd item - column index of cell with found string,
* 3rd item - start offset of found string.
* 4th item - end offset of found string.
*/
private int[] searchValues;
/** Flag if it is set highliht search. */
private boolean highlightSearch = true;
/** Flag if it is set match case search. */
private boolean matchCaseSearch = false;
/** Flag if it is set forward search. */
private boolean backwardSearch = false;
/** Flag if it is set wrap search. */
private boolean wrapSearch = true;
/** Flag if it is set search by rows. */
private boolean rowSearch = true;
/** Listener for registering keystrokes to find next action. */
private final ActionListener findNextActionListener;
/** Listener for registering keystrokes to find previous action. */
private final ActionListener findPreviousActionListener;
/** Listener for registering keystrokes to toggle highlight action. */
private final ActionListener toggleHighlightListener;
/** Keeps history of found strings. */
private Set history = new HashSet();
/** Helper variable keeping settings
. */
private TableViewSettings settings;
// Initializes action listener use to register for key strokes to table.
{
findNextActionListener = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// Find next action invoked (default F3) -> search next occurence.
if(searchValues != null) {
synchronized(this) {
backwardSearch = false;
performSearch();
}
}
}
};
findPreviousActionListener = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// Find previous action invoked (default Shift-F3)-> search previous occurence.
if(searchValues != null) {
synchronized(this) {
backwardSearch = true;
performSearch();
}
}
}
};
toggleHighlightListener = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// Toggle highlight action invoked (defauilt Shift-Alt-H) -> toggle highlight.
highlightSearch = !highlightSearch;
table.repaint();
}
};
} // end of initializer
/** Soft reference for caching singleton find performer on last table view. */
private static SoftReference softRef;
/** Dialog for perform search. */
private static JDialog findDialog;
/** Name of client property used to store search result values. */
public static final String TABLE_SEARCH_RESULT = "table.search.result"; // NOI18N
/** Creates new FindPerformer. Used internally only, for getting the singleton use #getFindPerformer method. */
private FindPerformer(JTable table) {
this.table = table;
settings = TableViewSettings.getDefault();
settings.addPropertyChangeListener(
WeakListeners.propertyChange(this, settings)
);
registerKeyStrokes();
}
/**
* Listen on setting changes.
*/
public void propertyChange(PropertyChangeEvent evt) {
// Settings were changed reset registered key strokes.
registerKeyStrokes();
}
/** Gets find performer. */
public static FindPerformer getFindPerformer(JTable table) {
if(softRef != null) {
FindPerformer fp = softRef.get();
if(fp != null) {
if(!fp.validateTable(table)) {
fp.resetTable(table);
fp.registerKeyStrokes();
}
return fp;
}
}
FindPerformer fp = new FindPerformer(table);
softRef = new SoftReference(fp);
return fp;
}
/** Resets the table if necessary. */
private void resetTable(JTable table) {
this.table = table;
}
/** Validates if the table is the same one as last opened find panel. */
private boolean validateTable(JTable table) {
if(this.table != null && this.table.equals(table))
return true;
return false;
}
/** Register key strokes F3 and Shift-F3 (next & previous search) to table. */
private synchronized void registerKeyStrokes() {
// Register key strokes to table.
KeyStroke[] keyStrokes = settings.getKeyStrokesFindNext();
for(int i=0; irow loop else->column loop.
for(int i= rowSearch ? startRow : startColumn;
backwardSearch ? i>=0 : i<(rowSearch ? table.getRowCount() : table.getColumnCount());
i = backwardSearch ? i-1 : i+1 ) {
// If rowSearch->column loop else->row loop.
for(int j= rowSearch ? startColumn : startRow;
backwardSearch ? j>=0 : j<(rowSearch ? table.getColumnCount() : table.getRowCount());
j = backwardSearch ? j-1 : j+1) {
// Set row and column indexes for this iteration.
int row = rowSearch ? i : j;
int column = rowSearch ? j : i;
String str = ((PropertiesTableModel.StringPair)table.getValueAt(row, column)).toString();
// Skip to next iteration if value is null or is the string in cell is shorter than string to find.
if(str == null || str.length() < findString.length())
continue;
if(!firstIteration)
startOffset = backwardSearch ? str.length()-findString.length() : 0;
int offset = containsFindString(str, startOffset);
if(offset>=0) {
// puts client property which is then used by cell editor
// for setting and highlighting the find string
table.putClientProperty(TABLE_SEARCH_RESULT, new int[] {row, column, offset, offset+findString.length()});
return new int[] {row, column, offset, offset+findString.length()};
}
if(firstIteration) firstIteration = false;
}
// Next inner loop from beginning(end) for forward (backward) search.
if(rowSearch)
startColumn = backwardSearch ? table.getColumnCount()-1 : 0;
else
startRow = backwardSearch ? table.getRowCount()-1 : 0;
}
return null;
}
/** The function search if findString occures whitin specified string.
* @param str String which is looked if contains find string.
* @param startOffset Offset from starts the search.
* @return Offset on which starts find string whitin str or -1. */
private int containsFindString(String str, int startOffset) {
if(startOffset < 0 || startOffset >= str.length())
return -1;
for(int i=startOffset;
backwardSearch ? i>=0 : i<(str.length()-findString.length()+1);
i = backwardSearch ? i-1 : i+1) {
if(findString.regionMatches(!matchCaseSearch, 0, str, i, findString.length()))
return i;
}
return -1;
}
}