jsyntaxpane.actions.gui.ReflectCompletionDialog Maven / Gradle / Ivy
/*
* Copyright 2008 Ayman Al-Sairafi [email protected]
*
* Licensed 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 jsyntaxpane.actions.gui;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.KeyEvent;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import jsyntaxpane.actions.ActionUtils;
import jsyntaxpane.util.ReflectUtils;
import jsyntaxpane.util.StringUtils;
import jsyntaxpane.util.SwingUtils;
/**
*
* @author Ayman Al-Sairafi
*/
public class ReflectCompletionDialog
extends javax.swing.JDialog implements EscapeListener {
/**
* The class we are displaying its members:
*/
private Class theClass;
/**
* The current filter, to avoid refiltering the items
*/
public String escapeChars = ";(= \t\n";
public List items;
private final JTextComponent target;
/**
* Creates new form ReflectCompletionDialog
* @param target Text component for this dialog
*/
public ReflectCompletionDialog(JTextComponent target) {
super(SwingUtilities.getWindowAncestor(target), ModalityType.APPLICATION_MODAL);
initComponents();
this.target = target;
jTxtItem.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
refilterList();
}
@Override
public void removeUpdate(DocumentEvent e) {
refilterList();
}
@Override
public void changedUpdate(DocumentEvent e) {
refilterList();
}
});
// This will allow the textfield to receive TAB keys
jTxtItem.setFocusTraversalKeysEnabled(false);
// Add action so we automatically filter on comboBox Enter Key
jCmbClassName.getEditor().addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateItems();
}
});
SwingUtils.addEscapeListener(this);
}
public void setFonts(Font font) {
jTxtItem.setFont(font);
jLstItems.setFont(font);
doLayout();
}
private String getSelection() {
String result;
if (jLstItems.getSelectedIndex() >= 0) {
Object selected = jLstItems.getSelectedValue();
if (selected instanceof Method) {
result = ReflectUtils.getJavaCallString((Method) selected);
} else if (selected instanceof Constructor) {
result = ReflectUtils.getJavaCallString((Constructor) selected);
} else if (selected instanceof Field) {
result = ((Field) selected).getName();
} else {
result = selected.toString();
}
} else {
result = jTxtItem.getText();
}
return result;
}
private void refilterList() {
String prefix = jTxtItem.getText();
Vector filtered = new Vector();
Object selected = jLstItems.getSelectedValue();
for (Member m : items) {
if (StringUtils.camelCaseMatch(m.getName(), prefix)) {
filtered.add(m);
}
}
jLstItems.setListData(filtered);
if (selected != null && filtered.contains(selected)) {
jLstItems.setSelectedValue(selected, true);
} else {
jLstItems.setSelectedIndex(0);
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
jTxtItem = new javax.swing.JTextField();
jScrollPane1 = new javax.swing.JScrollPane();
jLstItems = new javax.swing.JList();
jCmbClassName = new javax.swing.JComboBox();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setName("CompletionDialog"); // NOI18N
setResizable(false);
setUndecorated(true);
jTxtItem.setBorder(null);
jTxtItem.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
jTxtItemKeyPressed(evt);
}
});
jLstItems.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jLstItems.setCellRenderer(new jsyntaxpane.actions.gui.MembersListRenderer(this));
jLstItems.setFocusable(false);
jLstItems.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jLstItemsMouseClicked(evt);
}
});
jScrollPane1.setViewportView(jLstItems);
jCmbClassName.setEditable(true);
jCmbClassName.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Object", "String" }));
jCmbClassName.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jCmbClassNameItemStateChanged(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jTxtItem, javax.swing.GroupLayout.DEFAULT_SIZE, 437, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 437, Short.MAX_VALUE)
.addComponent(jCmbClassName, 0, 437, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jTxtItem, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, 0)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 156, Short.MAX_VALUE)
.addGap(0, 0, 0)
.addComponent(jCmbClassName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
pack();
}// //GEN-END:initComponents
private void jTxtItemKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_jTxtItemKeyPressed
int i = jLstItems.getSelectedIndex();
switch (evt.getKeyCode()) {
case KeyEvent.VK_ESCAPE:
target.setCaretPosition(target.getSelectionEnd());
setVisible(false);
return;
case KeyEvent.VK_DOWN:
i++;
break;
case KeyEvent.VK_UP:
i--;
break;
case KeyEvent.VK_HOME:
i = 0;
break;
case KeyEvent.VK_END:
i = jLstItems.getModel().getSize() - 1;
break;
case KeyEvent.VK_PAGE_DOWN:
i += jLstItems.getVisibleRowCount();
break;
case KeyEvent.VK_PAGE_UP:
i -= jLstItems.getVisibleRowCount();
break;
}
if (escapeChars.indexOf(evt.getKeyChar()) >= 0) {
String result = getSelection();
char pressed = evt.getKeyChar();
// we need to just accept ENTER, and replace the tab with a single
// space
if (pressed != '\n') {
result += (pressed == '\t') ? ' ' : pressed;
}
target.replaceSelection(result);
setVisible(false);
} else {
// perform bounds checks for i
if (i >= jLstItems.getModel().getSize()) {
i = jLstItems.getModel().getSize() - 1;
}
if (i < 0) {
i = 0;
}
jLstItems.setSelectedIndex(i);
jLstItems.ensureIndexIsVisible(i);
}
}//GEN-LAST:event_jTxtItemKeyPressed
private void jCmbClassNameItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_jCmbClassNameItemStateChanged
if (evt.getStateChange() == ItemEvent.SELECTED) {
updateItems();
}
}//GEN-LAST:event_jCmbClassNameItemStateChanged
private void jLstItemsMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLstItemsMouseClicked
if (evt.getClickCount() == 2) {
String selected = getSelection();
target.replaceSelection(selected);
setVisible(false);
}
}//GEN-LAST:event_jLstItemsMouseClicked
private void updateItems() {
String className = jCmbClassName.getEditor().getItem().toString();
if (items == null) {
items = new ArrayList();
} else {
items.clear();
}
// we must have the class in the Combo:
Class aClass = ReflectUtils.findClass(className, ReflectUtils.DEFAULT_PACKAGES);
if (aClass != null) {
// for now, add everything:
theClass = aClass;
ReflectUtils.addConstrcutors(aClass, items);
ReflectUtils.addMethods(aClass, items);
ReflectUtils.addFields(aClass, items);
ActionUtils.insertIntoCombo(jCmbClassName, className);
jTxtItem.requestFocusInWindow();
}
refilterList();
}
public Class getTheClass() {
return theClass;
}
/**
* Set the items to display
* @param items
*/
public void setItems(List items) {
this.items = items;
}
/**
* Display the dialog.
* @param target text component (its Window will be the parent)
*/
public void displayFor(JTextComponent target) {
try {
int dot = target.getSelectionStart();
Window window = SwingUtilities.getWindowAncestor(target);
Rectangle rt = target.modelToView(dot);
Point loc = new Point(rt.x, rt.y);
// convert the location from Text Componet coordinates to
// Frame coordinates...
loc = SwingUtilities.convertPoint(target, loc, window);
// and then to Screen coordinates
SwingUtilities.convertPointToScreen(loc, window);
setLocationRelativeTo(window);
setLocation(loc);
} catch (BadLocationException ex) {
Logger.getLogger(ReflectCompletionDialog.class.getName()).log(Level.SEVERE, null, ex);
} finally {
setFonts(target.getFont());
updateItems();
jTxtItem.setText(target.getSelectedText());
setVisible(true);
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox jCmbClassName;
private javax.swing.JList jLstItems;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextField jTxtItem;
// End of variables declaration//GEN-END:variables
@Override
public void escapePressed() {
target.setCaretPosition(target.getSelectionEnd());
setVisible(false);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy