Project: BMach
/*
 * 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.Color; 
import java.awt.Dimension; 
import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.lang.reflect.Constructor; 
import java.lang.reflect.Field; 
import java.lang.reflect.Member; 
import java.lang.reflect.Method; 
import java.lang.reflect.Modifier; 
import java.net.URL; 
import java.util.HashMap; 
import java.util.Map; 
import javax.swing.ImageIcon; 
import javax.swing.JList; 
import javax.swing.JPanel; 
import jsyntaxpane.SyntaxView; 
import jsyntaxpane.actions.ActionUtils; 
import jsyntaxpane.util.ReflectUtils; 
 
/**
 * This class will render a Member.  There are Method, Field and Constructor subclasses 
 * @author Ayman Al-Sairafi 
 */
 
abstract class MemberCell extends JPanel { 
 
    private final JList list; 
    private final boolean isSelected; 
    private final Color backColor; 
    private final Member member; 
    private final Class theClass; 
 
    public MemberCell(JList list, boolean isSelected, Color backColor, Member member, Class clazz) { 
        super(); 
        this.list = list; 
        this.isSelected = isSelected; 
        this.backColor = backColor; 
        this.member = member; 
        this.theClass = clazz; 
    } 
 
    @Override 
    public void paintComponent(Graphics g) { 
        SyntaxView.setRenderingHits((Graphics2D) g); 
        g.setFont(list.getFont()); 
        super.paintComponent(g); 
        FontMetrics fm = g.getFontMetrics(); 
        g.setColor(isSelected ? list.getSelectionBackground() : backColor); 
        g.fillRect(00, getWidth(), getHeight()); 
        g.setColor(isSelected ? list.getSelectionForeground() : list.getForeground()); 
        g.drawImage(getIcon(), 20null); 
        int x = 6 + getIcon().getWidth(this); 
        int y = fm.getHeight(); 
        if (member.getDeclaringClass().equals(theClass)) { 
            Font bold = list.getFont().deriveFont(Font.BOLD); 
            g.setFont(bold); 
        } 
        x = drawString(getMemberName(), x, y, g); 
        g.setFont(list.getFont()); 
        x = drawString(getArguments(), x, y, g); 
        String right = getReturnType(); 
        int rw = fm.stringWidth(right); 
        g.drawString(right, getWidth() - rw - 4, fm.getAscent()); 
    } 
 
    @Override 
    public Dimension getPreferredSize() { 
        Font font = list.getFont(); 
        Graphics g = getGraphics(); 
        FontMetrics fm = g.getFontMetrics(font); 
        // total text for this component: 
        String total = getMemberName() + getArguments() + getReturnType() + "  "
        return new Dimension(fm.stringWidth(total) + 20, Math.max(fm.getHeight(), 16)); 
    } 
 
    private int drawString(String string, int x, int y, Graphics g) { 
        if(ActionUtils.isEmptyOrBlanks(string)) { 
            return x; 
        } 
        int w = g.getFontMetrics().stringWidth(string); 
        g.drawString(string, x, y); 
        return x + w; 
    } 
 
    /**
     * Read all relevant icons and returns the Map.  The loc should contain the 
     * fully qualified URL for the icons.  The icon names read will have the words 
     * _private, protected, _static, _static_private and _static_protected and the 
     * extension ".png" appended. 
     * @param loc root for icon locations 
     * @return Map (can be used directly with getModifiers & 0xf) 
     */
 
    Map<Integer, Image> readIcons(String loc) { 
        Map<Integer, Image> icons = new HashMap<Integer, Image>(); 
        icons.put(Modifier.PUBLIC, readImage(loc, "")); 
        icons.put(Modifier.PRIVATE, readImage(loc, "_private")); 
        icons.put(Modifier.PROTECTED, readImage(loc, "_protected")); 
        icons.put(Modifier.STATIC | Modifier.PUBLIC, readImage(loc, "_static")); 
        icons.put(Modifier.STATIC | Modifier.PRIVATE, readImage(loc, "_static_private")); 
        icons.put(Modifier.STATIC | Modifier.PROTECTED, readImage(loc, "_static_protected")); 
        return icons; 
    } 
 
    private Image readImage(String iconLoc, String kind) { 
        String fullPath = iconLoc + kind + ".png"
        URL loc = this.getClass().getResource(fullPath); 
        if (loc == null) { 
            return null
        } else { 
            Image i = new ImageIcon(loc).getImage(); 
            return i; 
        } 
    } 
 
    protected String getMemberName() { 
        return member.getName(); 
    } 
 
    abstract protected String getArguments(); 
 
    abstract protected String getReturnType(); 
 
    abstract protected Image getIcon(); 
 
/**
 * Renders a Method 
 * @author Ayman Al-Sairafi 
 */
 
class MethodCell extends MemberCell { 
 
    private final Method method; 
 
    public MethodCell(JList list, boolean isSelected, Color backColor, Method method, Class clazz) { 
        super(list, isSelected, backColor, method, clazz); 
        this.method = method; 
    } 
 
    @Override 
    protected String getArguments() { 
        return ReflectUtils.getParamsString(method.getParameterTypes()); 
    } 
 
    @Override 
    protected String getReturnType() { 
        return method.getReturnType().getSimpleName(); 
    } 
 
    @Override 
    protected Image getIcon() { 
        int type = method.getModifiers() & 0xf// only get public/private/protected/static 
        if (icons == null) { 
            icons = readIcons(METHOD_ICON_LOC); 
        } 
        return icons.get(type); 
    } 
    private static Map<Integer, Image> icons = null
    public static final String METHOD_ICON_LOC = "/META-INF/images/completions/method"
 
/**
 * Renders a Field 
 * @author Ayman Al-Sairafi 
 */
 
class FieldCell extends MemberCell { 
 
    private final Field field; 
 
    public FieldCell(JList list, boolean isSelected, Color backColor, Field field, Class clazz) { 
        super(list, isSelected, backColor, field, clazz); 
        this.field = field; 
    } 
 
    @Override 
    protected String getArguments() { 
        return ""
    } 
 
    @Override 
    protected String getReturnType() { 
        return field.getType().getSimpleName(); 
    } 
 
    @Override 
    protected Image getIcon() { 
        int type = field.getModifiers() & 0xf// only get public/private/protected/static 
        if (icons == null) { 
            icons = readIcons(FIELD_ICON_LOC); 
        } 
        if (icons.get(type) == null) { 
            System.err.println("Unable to get icon for type: " + field.getModifiers()); 
        } 
        return icons.get(type); 
    } 
    private static Map<Integer, Image> icons = null
    public static final String FIELD_ICON_LOC = "/META-INF/images/completions/field"
 
/**
 * Renders a Field 
 * @author Ayman Al-Sairafi 
 */
 
class ConstructorCell extends MemberCell { 
 
    private final Constructor cons; 
 
    public ConstructorCell(JList list, boolean isSelected, Color backColor, Constructor cons, Class clazz) { 
        super(list, isSelected, backColor, cons, clazz); 
        this.cons = cons; 
    } 
 
    @Override 
    protected String getMemberName() { 
        return cons.getDeclaringClass().getSimpleName(); 
    } 
 
    @Override 
    protected String getArguments() { 
        return ReflectUtils.getParamsString(cons.getParameterTypes()); 
    } 
 
    @Override 
    protected String getReturnType() { 
        return cons.getDeclaringClass().getSimpleName(); 
    } 
 
    @Override 
    protected Image getIcon() { 
        int type = cons.getModifiers() & 0x7// only get public/private/protected, mask out static 
        if (icons == null) { 
            icons = readIcons(FIELD_ICON_LOC); 
        } 
        if (icons.get(type) == null) { 
            System.out.println("Unable to get icon for type: " + cons.getModifiers()); 
        } 
        return icons.get(type); 
    } 
 
    private static Map<Integer, Image> icons = null
    public static final String FIELD_ICON_LOC = "/META-INF/images/completions/constructor"
}