| /* |
| * 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.refactoring.java.ui; |
| |
| import java.awt.Color; |
| import java.awt.Component; |
| import java.io.CharConversionException; |
| import java.util.EnumSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| import javax.lang.model.element.*; |
| import javax.lang.model.type.*; |
| import javax.swing.*; |
| import javax.swing.table.DefaultTableCellRenderer; |
| import javax.swing.table.TableCellRenderer; |
| import javax.swing.table.TableColumn; |
| import javax.swing.text.AttributeSet; |
| import javax.swing.text.StyleConstants; |
| import org.netbeans.api.editor.mimelookup.MimeLookup; |
| import org.netbeans.api.editor.mimelookup.MimePath; |
| import org.netbeans.api.editor.settings.FontColorSettings; |
| import org.netbeans.api.java.lexer.JavaTokenId; |
| import org.netbeans.api.java.source.ui.ScanDialog; |
| import org.netbeans.api.lexer.Token; |
| import org.netbeans.api.lexer.TokenHierarchy; |
| import org.netbeans.api.lexer.TokenSequence; |
| import org.netbeans.modules.parsing.api.ParserManager; |
| import org.netbeans.modules.refactoring.java.api.MemberInfo; |
| import org.netbeans.swing.plaf.LFCustoms; |
| import org.openide.util.Lookup; |
| import org.openide.xml.XMLUtil; |
| |
| /** |
| * Class containing various utility methods and inner classes useful when |
| * creating refactoring UI. |
| * |
| * @author Martin Matula, Jan Becicka |
| */ |
| public final class UIUtilities { |
| |
| // XXX: Remove "test_" when #211651 is fixed |
| private static final String TEST_JAVA_MIME_TYPE = "test_text/x-java"; // NOI18N |
| /** |
| * Element.Kind values allowed to be used when calling ElementHandle.create |
| * |
| * @see javax.lang.model.element.ElementKind |
| * @see org.netbeans.api.java.source.ElementHandle |
| */ |
| public static EnumSet allowedElementKinds = EnumSet.of(ElementKind.PACKAGE, ElementKind.CLASS, ElementKind.INTERFACE, ElementKind.ENUM, ElementKind.ANNOTATION_TYPE, ElementKind.METHOD, ElementKind.CONSTRUCTOR, ElementKind.INSTANCE_INIT, ElementKind.STATIC_INIT, ElementKind.FIELD, ElementKind.ENUM_CONSTANT, ElementKind.TYPE_PARAMETER); |
| |
| // not to be instantiated |
| private UIUtilities() { |
| } |
| |
| /** |
| * Returns the same string as passed in or " " if the passed string was an |
| * empty string. This method is used as a workaround for issue #58302. |
| * |
| * @param name Original table column name. |
| * @return "Fixed" column name. |
| */ |
| public static String getColumnName(String name) { |
| return name == null || name.length() == 0 ? " " : name; // NOI18N |
| } |
| |
| /** |
| * Initializes preferred (and eventually maximum) width of a table column |
| * based on the size of its header and the estimated longest value. |
| * |
| * @param table Table to adjust the column width for. |
| * @param index Index of the column. |
| * @param longValue Estimated long value for the column. |
| * @param padding Number of pixes for padding. |
| */ |
| public static void initColumnWidth(JTable table, int index, Object longValue, int padding) { |
| TableColumn column = table.getColumnModel().getColumn(index); |
| |
| // get preferred size of the header |
| TableCellRenderer headerRenderer = column.getHeaderRenderer(); |
| if (headerRenderer == null) { |
| headerRenderer = table.getTableHeader().getDefaultRenderer(); |
| } |
| Component comp = headerRenderer.getTableCellRendererComponent( |
| table, column.getHeaderValue(), false, false, 0, 0); |
| int width = comp.getPreferredSize().width; |
| |
| // get preferred size of the long value (remeber max of the pref. size for header and long value) |
| comp = table.getDefaultRenderer(table.getModel().getColumnClass(index)).getTableCellRendererComponent( |
| table, longValue, false, false, 0, index); |
| width = Math.max(width, comp.getPreferredSize().width) + 2 * padding; |
| |
| // set preferred width of the column |
| column.setPreferredWidth(width); |
| // if the column contains boolean values, the preferred width |
| // should also be its max width |
| if (longValue instanceof Boolean) { |
| column.setMaxWidth(width); |
| } |
| } |
| |
| /** |
| * Table cell renderer that renders Java elements (instances of NamedElement |
| * and its subtypes). When rendering the elements it displays element's icon |
| * (if available) and display text. |
| */ |
| public static class JavaElementTableCellRenderer extends DefaultTableCellRenderer { |
| |
| @Override |
| public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
| super.getTableCellRendererComponent(table, extractText(value), isSelected, hasFocus, row, column); |
| if (value instanceof MemberInfo) { |
| Icon i = ((MemberInfo) value).getIcon(); |
| setIcon(i); |
| } else { |
| setIcon(null); |
| } |
| return this; |
| } |
| |
| /** |
| * Can be overriden to return alter the standard display text returned |
| * for elements. |
| * |
| * @param value Cell value. |
| * @return Display text. |
| */ |
| protected String extractText(Object value) { |
| if (value == null) { |
| return null; |
| } |
| if (value instanceof MemberInfo) { |
| return ((MemberInfo) value).getHtmlText(); |
| } else { |
| return value.toString(); |
| } |
| } |
| } |
| |
| /** |
| * Table cell renderer that renders Java elements (instances of NamedElement |
| * and its subtypes). When rendering the elements it displays element's icon |
| * (if available) and display text. |
| */ |
| public static class JavaElementListCellRenderer extends DefaultListCellRenderer { |
| |
| @Override |
| public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { |
| super.getListCellRendererComponent(list, extractText(value), index, isSelected, cellHasFocus); |
| if (value instanceof MemberInfo) { |
| Icon i = ((MemberInfo) value).getIcon(); |
| setIcon(i); |
| } |
| return this; |
| } |
| |
| /** |
| * Can be overriden to return alter the standard display text returned |
| * for elements. |
| * |
| * @param value Cell value. |
| * @return Display text. |
| */ |
| protected String extractText(Object value) { |
| if (value instanceof MemberInfo) { |
| return ((MemberInfo) value).getHtmlText(); |
| } else { |
| return value.toString(); |
| } |
| } |
| } |
| |
| /** |
| * Table cell renderer for boolean values (a little more advanced that the |
| * standard one). Enables hiding the combo box in case the value is |
| * <code>null</code> rather than |
| * <code>Boolean.TRUE</code> or |
| * <code>Boolean.FALSE</code> or in case of read-only cells to give a better |
| * visual feedback that the cells cannot be edited. |
| */ |
| public static class BooleanTableCellRenderer implements TableCellRenderer { |
| |
| private final TableCellRenderer checkbox; |
| private final TableCellRenderer label; |
| |
| public BooleanTableCellRenderer(JTable jt) { |
| this(jt.getDefaultRenderer(String.class), jt.getDefaultRenderer(Boolean.class)); |
| } |
| |
| private BooleanTableCellRenderer(TableCellRenderer label, TableCellRenderer checkbox) { |
| this.checkbox = checkbox; |
| this.label = label; |
| } |
| |
| @Override |
| public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { |
| TableCellRenderer rend = value == null || !table.getModel().isCellEditable(row, column) |
| ? label : checkbox; |
| // reset value in case the cell is not editable |
| value = value != null && rend == label ? null : value; |
| Component comp = rend.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); |
| return comp; |
| } |
| } |
| |
| public static String getHtml(String text) { |
| StringBuilder buf = new StringBuilder(); |
| TokenHierarchy tokenH = TokenHierarchy.create(text, JavaTokenId.language()); |
| Lookup lookup = MimeLookup.getLookup(MimePath.get(TEST_JAVA_MIME_TYPE)); |
| FontColorSettings settings = lookup.lookup(FontColorSettings.class); |
| TokenSequence tok = tokenH.tokenSequence(); |
| while (tok.moveNext()) { |
| Token<JavaTokenId> token = (Token) tok.token(); |
| String category = token.id().primaryCategory(); |
| if (category == null) { |
| category = "whitespace"; //NOI18N |
| } |
| AttributeSet set = settings.getTokenFontColors(category); |
| buf.append(color(htmlize(token.text().toString()), set)); |
| } |
| return buf.toString(); |
| } |
| |
| private static String color(String string, AttributeSet set) { |
| if (set == null) { |
| return string; |
| } |
| if (string.trim().length() == 0) { |
| return string.replace(" ", " ").replace("\n", "<br>"); //NOI18N |
| } |
| StringBuffer buf = new StringBuffer(string); |
| if (StyleConstants.isBold(set)) { |
| buf.insert(0, "<b>"); //NOI18N |
| buf.append("</b>"); //NOI18N |
| } |
| if (StyleConstants.isItalic(set)) { |
| buf.insert(0, "<i>"); //NOI18N |
| buf.append("</i>"); //NOI18N |
| } |
| if (StyleConstants.isStrikeThrough(set)) { |
| buf.insert(0, "<s>"); // NOI18N |
| buf.append("</s>"); // NOI18N |
| } |
| buf.insert(0, "<font color=" + getHTMLColor(LFCustoms.getForeground(set)) + ">"); //NOI18N |
| buf.append("</font>"); //NOI18N |
| return buf.toString(); |
| } |
| |
| private static String getHTMLColor(Color c) { |
| String colorR = "0" + Integer.toHexString(c.getRed()); //NOI18N |
| colorR = colorR.substring(colorR.length() - 2); |
| String colorG = "0" + Integer.toHexString(c.getGreen()); //NOI18N |
| colorG = colorG.substring(colorG.length() - 2); |
| String colorB = "0" + Integer.toHexString(c.getBlue()); //NOI18N |
| colorB = colorB.substring(colorB.length() - 2); |
| String html_color = "#" + colorR + colorG + colorB; //NOI18N |
| return html_color; |
| } |
| |
| public static String htmlize(String input) { |
| String temp = input.replace("<", "<"); // NOI18N |
| temp = temp.replace(">", ">"); // NOI18N |
| return temp; |
| } |
| |
| static String format(Element element) { |
| return format(element, false, false); |
| } |
| |
| static String format(Element element, boolean forSignature, boolean FQNs) { |
| StringBuilder stringBuilder = new StringBuilder(); |
| format(element, stringBuilder, forSignature, FQNs); |
| |
| return stringBuilder.toString(); |
| } |
| |
| static void format(Element element, StringBuilder stringBuilder, boolean forSignature, boolean FQNs) { |
| if (element == null) { |
| return; |
| } |
| |
| boolean first = true; |
| Set<Modifier> modifiers = element.getModifiers(); |
| |
| switch (element.getKind()) { |
| case PACKAGE: |
| |
| PackageElement packageElement = (PackageElement) element; |
| if (forSignature) { |
| stringBuilder.append("package "); // NOI18N |
| } |
| stringBuilder.append(packageElement.getQualifiedName()); |
| break; |
| |
| case CLASS: |
| case INTERFACE: |
| case ENUM: |
| case ANNOTATION_TYPE: |
| if (forSignature) { |
| stringBuilder.append(toString(modifiers)); |
| if (modifiers.size() > 0) { |
| if (stringBuilder.length() > 0) { |
| stringBuilder.append(" "); |
| } |
| } |
| } |
| |
| if (forSignature) { |
| switch (element.getKind()) { |
| case CLASS: |
| stringBuilder.append("class "); // NOI18N |
| break; |
| case INTERFACE: |
| stringBuilder.append("interface "); // NOI18N |
| break; |
| case ENUM: |
| stringBuilder.append("enum "); // NOI18N |
| break; |
| case ANNOTATION_TYPE: |
| stringBuilder.append("@interface "); // NOI18N |
| break; |
| } |
| } |
| |
| TypeElement typeElement = (TypeElement) element; |
| stringBuilder.append(FQNs |
| ? typeElement.getQualifiedName().toString() |
| : typeElement.getSimpleName().toString()); |
| |
| formatTypeParameters(typeElement.getTypeParameters(), stringBuilder, FQNs); |
| |
| break; |
| |
| case CONSTRUCTOR: |
| if (forSignature) { |
| stringBuilder.append(toString(modifiers)); |
| if (modifiers.size() > 0) { |
| if (stringBuilder.length() > 0) { |
| stringBuilder.append(" "); |
| } |
| } |
| } |
| |
| ExecutableElement constructorElement = (ExecutableElement) element; |
| stringBuilder.append(constructorElement.getEnclosingElement() |
| .getSimpleName().toString()); |
| stringBuilder.append("("); |
| formatVariableElements(constructorElement.getParameters(), |
| constructorElement.isVarArgs(), stringBuilder, FQNs); |
| stringBuilder.append(")"); |
| |
| List<? extends TypeMirror> thrownTypesMirrors = constructorElement.getThrownTypes(); |
| if (!thrownTypesMirrors.isEmpty()) { |
| stringBuilder.append(" throws "); // NOI18N |
| formatTypeMirrors(thrownTypesMirrors, stringBuilder, FQNs); |
| } |
| |
| break; |
| |
| case METHOD: |
| ExecutableElement methodElement = (ExecutableElement) element; |
| TypeMirror returnTypeMirror = methodElement.getReturnType(); |
| List<?extends TypeParameterElement> typeParameters = methodElement.getTypeParameters(); |
| |
| if (forSignature) { |
| stringBuilder.append(toString(modifiers)); |
| |
| if (modifiers.size() > 0) { |
| if (stringBuilder.length() > 0) { |
| stringBuilder.append(" "); |
| } |
| } |
| |
| if ((typeParameters != null) && (typeParameters.size() > 0)) { |
| formatTypeParameters(typeParameters, stringBuilder, FQNs); |
| if (stringBuilder.length() > 0) { |
| stringBuilder.append(" "); |
| } |
| } |
| |
| formatTypeMirror(returnTypeMirror, stringBuilder, FQNs); |
| } |
| |
| if (stringBuilder.length() > 0) { |
| stringBuilder.append(" "); |
| } |
| |
| stringBuilder.append(methodElement.getSimpleName().toString()); |
| stringBuilder.append("("); |
| formatVariableElements(methodElement.getParameters(), |
| methodElement.isVarArgs(), stringBuilder, FQNs); |
| stringBuilder.append(")"); |
| |
| List<? extends TypeMirror> thrownTypesMirrorsByMethod = methodElement.getThrownTypes(); |
| if (!thrownTypesMirrorsByMethod.isEmpty()) { |
| stringBuilder.append(" throws "); // NOI18N |
| formatTypeMirrors(thrownTypesMirrorsByMethod, stringBuilder, FQNs); |
| } |
| |
| if (forSignature) { |
| AnnotationValue annotationValue = methodElement.getDefaultValue(); |
| if (annotationValue != null) { |
| Object annotationValueValue = annotationValue.getValue(); |
| if (annotationValueValue != null) { |
| stringBuilder.append(" default "); // NOI18N |
| if (annotationValueValue instanceof String) { |
| stringBuilder.append("\""); |
| } else if (annotationValueValue instanceof Character) { |
| stringBuilder.append("\'"); |
| } |
| stringBuilder.append(String.valueOf(annotationValueValue)); |
| if (annotationValueValue instanceof String) { |
| stringBuilder.append("\""); |
| } else if (annotationValueValue instanceof Character) { |
| stringBuilder.append("\'"); |
| } |
| } |
| } |
| } else { |
| stringBuilder.append(":"); |
| |
| formatTypeMirror(returnTypeMirror, stringBuilder, FQNs); |
| |
| if ((typeParameters != null) && (typeParameters.size() > 0)) { |
| stringBuilder.append(":"); |
| formatTypeParameters(typeParameters, stringBuilder, FQNs); |
| } |
| } |
| |
| break; |
| |
| case TYPE_PARAMETER: |
| TypeParameterElement typeParameterElement = (TypeParameterElement) element; |
| stringBuilder.append(typeParameterElement.getSimpleName()); |
| |
| List<?extends TypeMirror> bounds = null; |
| try { |
| bounds = typeParameterElement.getBounds(); |
| if ((bounds != null) && (bounds.size() > 0)) { |
| if(!(bounds.size() == 1 && "java.lang.Object".equals( bounds.get(0).toString()))) { // NOI18N |
| stringBuilder.append(" extends "); // NOI18N |
| first = true; |
| for (TypeMirror typeMirror : bounds) { |
| if (first) { |
| first = false; |
| } else { |
| stringBuilder.append(" & "); // NOI18N |
| } |
| formatTypeMirror(typeMirror, stringBuilder, FQNs); |
| } |
| } |
| } |
| } catch (NullPointerException npe) { |
| // Bug? |
| } |
| |
| break; |
| |
| case FIELD: |
| VariableElement fieldElement = (VariableElement) element; |
| if (forSignature) { |
| stringBuilder.append(toString(modifiers)); |
| |
| if (stringBuilder.length() > 0) { |
| stringBuilder.append(" "); |
| } |
| |
| formatTypeMirror(fieldElement.asType(), stringBuilder, FQNs); |
| } |
| |
| if (stringBuilder.length() > 0) { |
| stringBuilder.append(" "); |
| } |
| |
| stringBuilder.append(fieldElement.getSimpleName().toString()); |
| |
| if (forSignature) { |
| Object fieldValue = fieldElement.getConstantValue(); |
| if (fieldValue != null) { |
| stringBuilder.append(" = "); |
| if (fieldValue instanceof String) { |
| stringBuilder.append("\""); |
| } else if (fieldValue instanceof Character) { |
| stringBuilder.append("\'"); |
| } |
| stringBuilder.append(String.valueOf(fieldValue)); |
| if (fieldValue instanceof String) { |
| stringBuilder.append("\""); |
| } else if (fieldValue instanceof Character) { |
| stringBuilder.append("\'"); |
| } |
| } |
| } else { |
| stringBuilder.append(":"); |
| |
| formatTypeMirror(fieldElement.asType(), stringBuilder, FQNs); |
| } |
| |
| break; |
| |
| case ENUM_CONSTANT: |
| stringBuilder.append(element.toString()); |
| break; |
| |
| case PARAMETER: |
| case LOCAL_VARIABLE: |
| VariableElement variableElement = (VariableElement) element; |
| formatTypeMirror(variableElement.asType(), stringBuilder, FQNs); |
| stringBuilder.append(" "); |
| stringBuilder.append(element.getSimpleName().toString()); |
| |
| break; |
| } |
| } |
| |
| static void formatTypeMirror(TypeMirror typeMirror, |
| StringBuilder stringBuilder, boolean FQNs) { |
| if (typeMirror == null) { |
| return; |
| } |
| |
| boolean first = true; |
| |
| switch (typeMirror.getKind()) { |
| case BOOLEAN: |
| case BYTE: |
| case CHAR: |
| case DOUBLE: |
| case FLOAT: |
| case INT: |
| case LONG: |
| case NONE: |
| case NULL: |
| case SHORT: |
| case VOID: |
| stringBuilder.append(typeMirror); |
| |
| break; |
| |
| case TYPEVAR: |
| TypeVariable typeVariable = (TypeVariable)typeMirror; |
| stringBuilder.append(typeVariable.asElement().getSimpleName().toString()); |
| break; |
| |
| case WILDCARD: |
| WildcardType wildcardType = (WildcardType)typeMirror; |
| stringBuilder.append("?"); |
| if ( wildcardType.getExtendsBound() != null ) { |
| stringBuilder.append(" extends "); // NOI18N |
| formatTypeMirror(wildcardType.getExtendsBound(), stringBuilder, FQNs); |
| } |
| if ( wildcardType.getSuperBound() != null ) { |
| stringBuilder.append(" super "); // NOI18N |
| formatTypeMirror(wildcardType.getSuperBound(), stringBuilder, FQNs); |
| } |
| |
| break; |
| |
| case DECLARED: |
| DeclaredType declaredType = (DeclaredType) typeMirror; |
| Element element = declaredType.asElement(); |
| if (element instanceof TypeElement) { |
| stringBuilder.append( |
| FQNs ? |
| ((TypeElement)element).getQualifiedName().toString() : |
| element.getSimpleName().toString()); |
| } else { |
| stringBuilder.append(element.getSimpleName().toString()); |
| } |
| List<? extends TypeMirror> typeArgs = declaredType.getTypeArguments(); |
| if ( !typeArgs.isEmpty() ) { |
| stringBuilder.append("<"); |
| formatTypeMirrors(typeArgs, stringBuilder, FQNs); |
| stringBuilder.append(">"); |
| } |
| |
| break; |
| |
| case ARRAY: |
| |
| int dims = 0; |
| |
| while (typeMirror.getKind() == TypeKind.ARRAY) { |
| dims++; |
| typeMirror = ((ArrayType) typeMirror).getComponentType(); |
| } |
| |
| formatTypeMirror(typeMirror, stringBuilder, FQNs); |
| |
| for (int i = 0; i < dims; i++) { |
| stringBuilder.append("[]"); |
| } |
| |
| break; |
| } |
| } |
| |
| static void formatTypeParameters( |
| List<? extends TypeParameterElement> typeParameters, |
| StringBuilder stringBuilder, boolean FQNs) { |
| if ((typeParameters == null) || (typeParameters.size() == 0)) { |
| return; |
| } |
| |
| boolean first = true; |
| if (typeParameters.size() > 0) { |
| stringBuilder.append("<"); |
| first = true; |
| |
| for (TypeParameterElement typeParameterElement : typeParameters) { |
| if (first) { |
| first = false; |
| } else { |
| stringBuilder.append(", "); |
| } |
| |
| format(typeParameterElement, stringBuilder, false, FQNs); |
| } |
| |
| stringBuilder.append(">"); |
| } |
| } |
| |
| static void formatVariableElements( |
| List<? extends VariableElement> variableElements, boolean varArgs, |
| StringBuilder stringBuilder, boolean FQNs) { |
| if ((variableElements == null) || (variableElements.size() == 0)) { |
| return; |
| } |
| |
| boolean first = true; |
| |
| for (VariableElement variableElement : variableElements) { |
| if (first) { |
| first = false; |
| } else { |
| stringBuilder.append(", "); |
| } |
| |
| format(variableElement, stringBuilder, false, FQNs); |
| } |
| |
| if (varArgs) { |
| stringBuilder.append("..."); |
| } |
| } |
| |
| static void formatTypeMirrors(List<?extends TypeMirror> thrownTypeMirros, |
| StringBuilder stringBuilder, boolean FQNs) { |
| if ((thrownTypeMirros == null) || (thrownTypeMirros.size() == 0)) { |
| return; |
| } |
| |
| boolean first = true; |
| |
| for (TypeMirror typeMirror : thrownTypeMirros) { |
| if (first) { |
| first = false; |
| } else { |
| stringBuilder.append(", "); |
| } |
| |
| formatTypeMirror(typeMirror, stringBuilder, FQNs); |
| } |
| } |
| |
| static int getIntModifiers(Set<Modifier> modifiers) { |
| int intModifiers = 0; |
| |
| if (modifiers.contains(Modifier.ABSTRACT)) { |
| intModifiers |= java.lang.reflect.Modifier.ABSTRACT; |
| } |
| |
| if (modifiers.contains(Modifier.FINAL)) { |
| intModifiers |= java.lang.reflect.Modifier.FINAL; |
| } |
| |
| if (modifiers.contains(Modifier.NATIVE)) { |
| intModifiers |= java.lang.reflect.Modifier.NATIVE; |
| } |
| |
| if (modifiers.contains(Modifier.PRIVATE)) { |
| intModifiers |= java.lang.reflect.Modifier.PRIVATE; |
| } |
| |
| if (modifiers.contains(Modifier.PROTECTED)) { |
| intModifiers |= java.lang.reflect.Modifier.PROTECTED; |
| } |
| |
| if (modifiers.contains(Modifier.PUBLIC)) { |
| intModifiers |= java.lang.reflect.Modifier.PUBLIC; |
| } |
| |
| if (modifiers.contains(Modifier.STATIC)) { |
| intModifiers |= java.lang.reflect.Modifier.STATIC; |
| } |
| |
| if (modifiers.contains(Modifier.STRICTFP)) { |
| intModifiers |= java.lang.reflect.Modifier.STRICT; |
| } |
| |
| if (modifiers.contains(Modifier.SYNCHRONIZED)) { |
| intModifiers |= java.lang.reflect.Modifier.SYNCHRONIZED; |
| } |
| |
| if (modifiers.contains(Modifier.TRANSIENT)) { |
| intModifiers |= java.lang.reflect.Modifier.TRANSIENT; |
| } |
| |
| if (modifiers.contains(Modifier.VOLATILE)) { |
| intModifiers |= java.lang.reflect.Modifier.VOLATILE; |
| } |
| |
| return intModifiers; |
| } |
| |
| static String toString(Set<Modifier> modifiers) { |
| return java.lang.reflect.Modifier.toString(getIntModifiers(modifiers)); |
| } |
| |
| static Set<Modifier> getModifiers(int intModifiers) { |
| EnumSet<Modifier> modifiers = EnumSet.noneOf(Modifier.class); |
| |
| if ((intModifiers & java.lang.reflect.Modifier.ABSTRACT) != 0) { |
| modifiers.add(Modifier.ABSTRACT); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.FINAL) != 0) { |
| modifiers.add(Modifier.FINAL); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.NATIVE) != 0) { |
| modifiers.add(Modifier.NATIVE); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.PRIVATE) != 0) { |
| modifiers.add(Modifier.PRIVATE); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.PROTECTED) != 0) { |
| modifiers.add(Modifier.PROTECTED); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.PUBLIC) != 0) { |
| modifiers.add(Modifier.PUBLIC); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.STATIC) != 0) { |
| modifiers.add(Modifier.STATIC); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.STRICT) != 0) { |
| modifiers.add(Modifier.STRICTFP); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.SYNCHRONIZED) != 0) { |
| modifiers.add(Modifier.SYNCHRONIZED); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.TRANSIENT) != 0) { |
| modifiers.add(Modifier.TRANSIENT); |
| } |
| |
| if ((intModifiers & java.lang.reflect.Modifier.VOLATILE) != 0) { |
| modifiers.add(Modifier.VOLATILE); |
| } |
| |
| return modifiers; |
| } |
| |
| static String getClassName(String className) { |
| return getClassName(className, false); |
| } |
| |
| static String getClassName(String className, boolean FQNs) { |
| // Handle generic type names i.e. strip off parameters |
| int firstLessThan = className.indexOf('<'); |
| |
| if (firstLessThan != -1) { |
| className = className.substring(0, firstLessThan); |
| } |
| |
| if (!FQNs) { |
| int lastDot = className.lastIndexOf('.'); |
| |
| if (lastDot != -1) { |
| className = className.substring(lastDot + 1); |
| } |
| } |
| |
| return className; |
| } |
| |
| static String getClassNameSansPackage(String className) { |
| // Handle generic type names i.e. strip off parameters |
| int firstLessThan = className.indexOf('<'); |
| |
| if (firstLessThan != -1) { |
| className = className.substring(0, firstLessThan); |
| } |
| |
| int lastDot = className.lastIndexOf('.'); |
| |
| if (lastDot != -1) { |
| className = className.substring(lastDot + 1); |
| } |
| |
| return className; |
| } |
| |
| // Tree movement |
| static void firstRow(JTree tree) { |
| int rowCount = tree.getRowCount(); |
| if (rowCount > 0) { |
| tree.setSelectionRow(0); |
| scrollTreeToSelectedRow(tree); |
| } |
| } |
| |
| static void previousRow(JTree tree) { |
| int rowCount = tree.getRowCount(); |
| if (rowCount > 0) { |
| int selectedRow = tree.getSelectionModel().getMinSelectionRow(); |
| if (selectedRow == -1) { |
| selectedRow = (rowCount -1); |
| } else { |
| selectedRow--; |
| if (selectedRow < 0) { |
| selectedRow = (rowCount -1); |
| } |
| } |
| tree.setSelectionRow(selectedRow); |
| scrollTreeToSelectedRow(tree); |
| } |
| } |
| |
| static void nextRow(JTree tree) { |
| int rowCount = tree.getRowCount(); |
| if (rowCount > 0) { |
| int selectedRow = tree.getSelectionModel().getMinSelectionRow(); |
| if (selectedRow == -1) { |
| selectedRow = 0; |
| tree.setSelectionRow(selectedRow); |
| } else { |
| selectedRow++; |
| } |
| tree.setSelectionRow(selectedRow % rowCount); |
| scrollTreeToSelectedRow(tree); |
| } |
| } |
| |
| static void lastRow(JTree tree) { |
| int rowCount = tree.getRowCount(); |
| if (rowCount > 0) { |
| tree.setSelectionRow(rowCount - 1); |
| scrollTreeToSelectedRow(tree); |
| } |
| } |
| |
| static void scrollTreeToSelectedRow(final JTree tree) { |
| final int selectedRow = tree.getLeadSelectionRow(); |
| if (selectedRow >=0) { |
| SwingUtilities.invokeLater( |
| new Runnable() { |
| public void run() { |
| tree.scrollRectToVisible(tree.getRowBounds(selectedRow)); |
| } |
| } |
| ); |
| } |
| } |
| |
| static String escape(String s) { |
| if (s != null) { |
| try { |
| return XMLUtil.toAttributeValue(s); |
| } catch (CharConversionException ex) { |
| } |
| } |
| return null; |
| } |
| |
| private static final String TYPE_COLOR = "#707070"; |
| private static final String INHERITED_COLOR = "#7D694A"; |
| |
| /** |
| * Creates HTML display name of the Executable element |
| */ |
| public static String createHeader(ExecutableElement e, boolean isDeprecated, boolean isInherited, boolean html, boolean isBold) { |
| StringBuilder sb = new StringBuilder(); |
| if (html) { |
| if (isDeprecated) { |
| sb.append("<s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("<b>"); // NOI18N |
| } |
| if (isInherited) { |
| sb.append("<font color=" + INHERITED_COLOR + ">"); // NOI18N |
| } |
| } |
| Name name = e.getKind() == ElementKind.CONSTRUCTOR ? e.getEnclosingElement().getSimpleName() : e.getSimpleName(); |
| sb.append(UIUtilities.escape(name.toString())); |
| if (html) { |
| if (isDeprecated) { |
| sb.append("</s>"); // NOI18N |
| } |
| } |
| |
| sb.append("("); // NOI18N |
| |
| List<? extends VariableElement> params = e.getParameters(); |
| for (Iterator<? extends VariableElement> it = params.iterator(); it.hasNext();) { |
| VariableElement param = it.next(); |
| if (html) { |
| sb.append("<font color=" + TYPE_COLOR + ">"); // NOI18N |
| } |
| final boolean vararg = !it.hasNext() && e.isVarArgs(); |
| sb.append(printArg(param.asType(), vararg, html)); |
| if (html) { |
| sb.append("</font>"); // NOI18N |
| } |
| sb.append(" "); // NOI18N |
| sb.append(UIUtilities.escape(param.getSimpleName().toString())); |
| if (it.hasNext()) { |
| sb.append(", "); // NOI18N |
| } |
| } |
| |
| |
| sb.append(")"); // NOI18N |
| |
| if (html) { |
| if (!isDeprecated && isBold) { |
| sb.append("</b>"); // NOI18N |
| } |
| } |
| if (e.getKind() != ElementKind.CONSTRUCTOR) { |
| TypeMirror rt = e.getReturnType(); |
| if (rt.getKind() != TypeKind.VOID) { |
| sb.append(" : "); // NOI18N |
| if (html) { |
| sb.append("<font color=" + TYPE_COLOR + ">"); // NOI18N |
| } |
| sb.append(print(e.getReturnType(), html)); |
| if (html) { |
| sb.append("</font>"); // NOI18N |
| } |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| public static String createHeader(VariableElement e, boolean isDeprecated, boolean isInherited, boolean html, boolean isBold) { |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| if (html) { |
| if (isDeprecated) { |
| sb.append("<s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("<b>"); // NOI18N |
| } |
| if (isInherited) { |
| sb.append("<font color=" + INHERITED_COLOR + ">"); // NOI18N |
| } |
| } |
| sb.append(UIUtilities.escape(e.getSimpleName().toString())); |
| if (html) { |
| if (isDeprecated) { |
| sb.append("</s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("</b>"); // NOI18N |
| } |
| } |
| |
| if (e.getKind() != ElementKind.ENUM_CONSTANT) { |
| sb.append(" : "); // NOI18N |
| if (html) { |
| sb.append("<font color=" + TYPE_COLOR + ">"); // NOI18N |
| } |
| sb.append(print(e.asType(), html)); |
| if (html) { |
| sb.append("</font>"); // NOI18N |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| public static String createHeader(TypeParameterElement e, boolean isDeprecated, boolean isInherited, boolean html, boolean isBold) { |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| if (html) { |
| if (isDeprecated) { |
| sb.append("<s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("<b>"); // NOI18N |
| } |
| if (isInherited) { |
| sb.append("<font color=" + INHERITED_COLOR + ">"); // NOI18N |
| } |
| } |
| sb.append(UIUtilities.escape(e.getSimpleName().toString())); |
| if (html) { |
| if (isDeprecated) { |
| sb.append("</s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("</b>"); // NOI18N |
| } |
| } |
| |
| if (e.getKind() != ElementKind.ENUM_CONSTANT) { |
| sb.append(" : "); // NOI18N |
| if (html) { |
| sb.append("<font color=" + TYPE_COLOR + ">"); // NOI18N |
| } |
| sb.append(print(e.asType(), html)); |
| if (html) { |
| sb.append("</font>"); // NOI18N |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| public static String createHeader(PackageElement e, boolean isDeprecated, boolean isInherited, boolean html, boolean isBold) { |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| if (html) { |
| if (isDeprecated) { |
| sb.append("<s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("<b>"); // NOI18N |
| } |
| if (isInherited) { |
| sb.append("<font color=" + INHERITED_COLOR + ">"); // NOI18N |
| } |
| } |
| sb.append(UIUtilities.escape(e.getSimpleName().toString())); |
| if (html) { |
| if (isDeprecated) { |
| sb.append("</s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("</b>"); // NOI18N |
| } |
| } |
| |
| if (e.getKind() != ElementKind.ENUM_CONSTANT) { |
| sb.append(" : "); // NOI18N |
| if (html) { |
| sb.append("<font color=" + TYPE_COLOR + ">"); // NOI18N |
| } |
| sb.append(print(e.asType(), html)); |
| if (html) { |
| sb.append("</font>"); // NOI18N |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| public static String createHeader(TypeElement e, boolean isDeprecated, boolean isInherited, boolean html, boolean isBold) { |
| |
| StringBuilder sb = new StringBuilder(); |
| if (html) { |
| if (isDeprecated) { |
| sb.append("<s>"); // NOI18N |
| } else if (isBold) { |
| sb.append("<b>"); // NOI18N |
| } |
| if (isInherited) { |
| sb.append("<font color=" + INHERITED_COLOR + ">"); // NOI18N |
| } |
| } |
| sb.append(UIUtilities.escape(e.getSimpleName().toString())); |
| if(html) { |
| if (isDeprecated) { |
| sb.append("</s>"); // NOI18N |
| } |
| } |
| List<? extends TypeParameterElement> typeParams = e.getTypeParameters(); |
| if (typeParams != null && !typeParams.isEmpty()) { |
| sb.append(html ? "<" : "<"); // NOI18N |
| |
| for (Iterator<? extends TypeParameterElement> it = typeParams.iterator(); it.hasNext();) { |
| TypeParameterElement tp = it.next(); |
| sb.append(UIUtilities.escape(tp.getSimpleName().toString())); |
| List<? extends TypeMirror> bounds = null; |
| try { |
| bounds = tp.getBounds(); |
| } catch (NullPointerException npe) { |
| // Ignore |
| } |
| if (bounds != null && !bounds.isEmpty()) { |
| sb.append(printBounds(bounds, html)); |
| } |
| |
| if (it.hasNext()) { |
| sb.append(", "); // NOI18N |
| } |
| } |
| |
| sb.append(html ? ">" : ">"); // NOI18N |
| } |
| |
| if (html && !isDeprecated && isBold) { |
| sb.append("<b>"); // NOI18N |
| } |
| |
| // Add superclass and implemented interfaces |
| |
| TypeMirror sc = e.getSuperclass(); |
| String scName = print(sc, html); |
| |
| if (sc == null |
| || e.getKind() == ElementKind.ENUM |
| || e.getKind() == ElementKind.ANNOTATION_TYPE |
| || "java.lang.Object".equals(sc.toString()) || // NOI18N |
| "<none>".equals(sc.toString())) { // NOI18N |
| scName = null; |
| } |
| |
| List<? extends TypeMirror> ifaces = e.getInterfaces(); |
| |
| if ((scName != null || !ifaces.isEmpty()) |
| && e.getKind() != ElementKind.ANNOTATION_TYPE) { |
| sb.append(" :: "); // NOI18N |
| if (scName != null) { |
| if (html) { |
| sb.append("<font color=" + TYPE_COLOR + ">"); // NOI18N |
| } |
| sb.append(scName); |
| if (html) { |
| sb.append("</font>"); // NOI18N |
| } |
| } |
| if (!ifaces.isEmpty()) { |
| if (scName != null) { |
| sb.append(" : "); // NOI18N |
| } |
| for (Iterator<? extends TypeMirror> it = ifaces.iterator(); it.hasNext();) { |
| TypeMirror typeMirror = it.next(); |
| if (html) { |
| sb.append("<font color=" + TYPE_COLOR + ">"); // NOI18N |
| } |
| sb.append(print(typeMirror, html)); |
| if (html) { |
| sb.append("</font>"); // NOI18N |
| } |
| if (it.hasNext()) { |
| sb.append(", "); // NOI18N |
| } |
| } |
| |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| public static boolean runWhenScanFinished (final Runnable runnable, final String actionName) { |
| return ScanDialog.runWhenScanFinished( |
| () -> { |
| if (ParserManager.isParsing()) { |
| SwingUtilities.invokeLater(runnable); |
| } else { |
| runnable.run(); |
| } |
| }, |
| actionName); |
| } |
| |
| private static String printBounds(List<? extends TypeMirror> bounds, boolean html) { |
| if (bounds.size() == 1 && "java.lang.Object".equals(bounds.get(0).toString())) { |
| return ""; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| sb.append(" extends "); // NOI18N |
| |
| for (Iterator<? extends TypeMirror> it = bounds.iterator(); it.hasNext();) { |
| TypeMirror bound = it.next(); |
| sb.append(print(bound, html)); |
| if (it.hasNext()) { |
| sb.append(" & "); // NOI18N |
| } |
| } |
| |
| return sb.toString(); |
| } |
| |
| private static String printArg(final TypeMirror tm, final boolean varArg, boolean html) { |
| if (varArg) { |
| if (tm.getKind() == TypeKind.ARRAY) { |
| final ArrayType at = (ArrayType) tm; |
| final StringBuilder sb = new StringBuilder(print(at.getComponentType(), html)); |
| sb.append("..."); //NOI18N |
| return sb.toString(); |
| } else { |
| assert false : "Expected array: " + tm.toString() + " ( " + tm.getKind() + " )"; //NOI18N |
| } |
| } |
| return print(tm, html); |
| } |
| |
| private static String print(TypeMirror tm, boolean html) { |
| StringBuilder sb; |
| |
| switch (tm.getKind()) { |
| case DECLARED: |
| DeclaredType dt = (DeclaredType) tm; |
| sb = new StringBuilder(dt.asElement().getSimpleName().toString()); |
| List<? extends TypeMirror> typeArgs = dt.getTypeArguments(); |
| if (!typeArgs.isEmpty()) { |
| sb.append(html ? "<" : "<"); // NOI18N |
| |
| for (Iterator<? extends TypeMirror> it = typeArgs.iterator(); it.hasNext();) { |
| TypeMirror ta = it.next(); |
| sb.append(print(ta, html)); |
| if (it.hasNext()) { |
| sb.append(", "); |
| } |
| } |
| sb.append(html ? ">" : ">"); // NOI18N |
| } |
| |
| return sb.toString(); |
| case TYPEVAR: |
| TypeVariable tv = (TypeVariable) tm; |
| sb = new StringBuilder(tv.asElement().getSimpleName().toString()); |
| return sb.toString(); |
| case ARRAY: |
| ArrayType at = (ArrayType) tm; |
| sb = new StringBuilder(print(at.getComponentType(), html)); |
| sb.append("[]"); |
| return sb.toString(); |
| case WILDCARD: |
| WildcardType wt = (WildcardType) tm; |
| sb = new StringBuilder("?"); |
| if (wt.getExtendsBound() != null) { |
| sb.append(" extends "); // NOI18N |
| sb.append(print(wt.getExtendsBound(), html)); |
| } |
| if (wt.getSuperBound() != null) { |
| sb.append(" super "); // NOI18N |
| sb.append(print(wt.getSuperBound(), html)); |
| } |
| return sb.toString(); |
| default: |
| return UIUtilities.escape(tm.toString()); |
| } |
| } |
| } |