Package org.openquark.gems.client.explorer

Source Code of org.openquark.gems.client.explorer.HyperlinkLabelUI

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* ExplorerCellRenderer.java
* Created: Feb 13, 2004
* By: David Mosimann
*/
package org.openquark.gems.client.explorer;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.SystemColor;
import java.awt.Toolkit;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import java.util.HashMap;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTree;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.TreeUI;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;

import org.openquark.cal.compiler.ClassMethod;
import org.openquark.cal.compiler.DataConstructor;
import org.openquark.cal.compiler.Function;
import org.openquark.cal.compiler.FunctionalAgent;
import org.openquark.cal.compiler.ModuleTypeInfo;
import org.openquark.cal.compiler.ScopedEntityNamingPolicy;
import org.openquark.cal.compiler.ScopedEntityNamingPolicy.UnqualifiedUnlessAmbiguous;
import org.openquark.cal.metadata.ArgumentMetadata;
import org.openquark.cal.valuenode.ValueNode;
import org.openquark.gems.client.CodeGem;
import org.openquark.gems.client.CollectorGem;
import org.openquark.gems.client.FunctionalAgentGem;
import org.openquark.gems.client.Gem;
import org.openquark.gems.client.RecordCreationGem;
import org.openquark.gems.client.RecordFieldSelectionGem;
import org.openquark.gems.client.ReflectorGem;
import org.openquark.gems.client.ValueGem;


/**
* The renderer for the TableTopExplorer tree.
* @author Ken Wong
*/
public class ExplorerCellRenderer extends DefaultTreeCellRenderer {

    private static final long serialVersionUID = 1131870254758332921L;

    /** The table top exlorer owner of the explorer tree. */
    private final TableTopExplorerOwner tableTopExplorerOwner;

    /** Whether or not the tree is using the banded look and feel. */
    private boolean useBandedLookAndFeel;

    /** Used to store if the current node is focusable or not. */
    public boolean focusable;

    /* the various icons used in the tree */
    private static final ImageIcon constructorIcon;
    private static final ImageIcon supercombinatorIcon;
    private static final ImageIcon codeGemIcon;
    private static final ImageIcon brokenCodeGemIcon;
    private static final ImageIcon collectorIcon;
//  private static final ImageIcon targetCollectorIcon;
    private static final ImageIcon emitterIcon;
    private static final ImageIcon minorTargetIcon;
    private static final ImageIcon reflectorIcon;
    private static final ImageIcon brokenReflectorGemIcon;
    private static final ImageIcon partInputIcon;
    private static final ImageIcon burnIcon;
    private static final ImageIcon valueIcon;
    private static final ImageIcon recordFieldSelectionIcon;
    private static final ImageIcon recordCreationIcon;
   

    static {
        // Make icon objects
        constructorIcon = new ImageIcon(Object.class.getResource("/Resources/dataConstructor.gif"));
        supercombinatorIcon = new ImageIcon(Object.class.getResource("/Resources/supercombinator.gif"));
        codeGemIcon = new ImageIcon(Object.class.getResource("/Resources/code.gif"));
        brokenCodeGemIcon = new ImageIcon(Object.class.getResource("/Resources/codeBroken.gif"));
        collectorIcon = new ImageIcon(Object.class.getResource("/Resources/collector.gif"));
//      targetCollectorIcon = new ImageIcon(Object.class.getResource("/Resources/targetCollector.gif"));
        emitterIcon = new ImageIcon(Object.class.getResource("/Resources/emitter.gif"));
        minorTargetIcon = new ImageIcon(Object.class.getResource("/Resources/targetbw.gif"));
        reflectorIcon = new ImageIcon(Object.class.getResource("/Resources/reflector.gif"));
        brokenReflectorGemIcon = new ImageIcon(Object.class.getResource("/Resources/reflectorBroken.gif"));
        partInputIcon = new ImageIcon(Object.class.getResource("/Resources/partinput.gif"));
        valueIcon = new ImageIcon(Object.class.getResource("/Resources/constant.gif"));
        Image burnedImage = Toolkit.getDefaultToolkit().createImage(Object.class.getResource("/Resources/burn.gif")).getScaledInstance(16,16,Image.SCALE_SMOOTH);
        burnIcon = new ImageIcon(burnedImage);
        recordFieldSelectionIcon = new ImageIcon(Object.class.getResource("/Resources/recordFieldSelectionGem.gif"));
        recordCreationIcon = new ImageIcon(Object.class.getResource("/Resources/recordCreationGem.gif"));
    }

    /**
     * Default Constructor for the cell renderer;
     * @param owner the explorer owner using the tree
     */
    protected ExplorerCellRenderer(TableTopExplorerOwner owner) {
        this.tableTopExplorerOwner = owner;

        // Set the UI to use the hyperlink label UI
        setUI(HyperlinkLabelUI.createUI(this));
    }

    public void setBandedLookAndFeel(boolean useBandedLookAndFeel) {
        this.useBandedLookAndFeel = useBandedLookAndFeel;
    }

    /**
     * Overide this method so that we can explicitly use a special banded look and feel even if a different
     * look and feel is requested.
     * @param newUI
     */
    public void setUI(TreeUI newUI) {
        super.setUI(HyperlinkLabelUI.createUI(this));
    }

    /**
     * @see javax.swing.tree.TreeCellRenderer#getTreeCellRendererComponent(javax.swing.JTree, java.lang.Object, boolean, boolean, boolean, int, boolean)
     */
    @Override
    public Component getTreeCellRendererComponent(JTree tree,
            Object value,
            boolean sel,
            boolean expanded,
            boolean leaf, int row,
            boolean hasFocus) {
        // By default the node is not focussable
        focusable = false;

        if (tableTopExplorerOwner.hasPhotoLook()) {
            setTextNonSelectionColor(Color.BLACK);
            setTextSelectionColor(Color.WHITE);
            setBackgroundSelectionColor(Color.BLUE.darker().darker());
        } else {       
            setTextNonSelectionColor(SystemColor.textText);
            setTextSelectionColor(SystemColor.textHighlightText);
            setBackgroundSelectionColor(SystemColor.textHighlight);
        }

        setBackgroundNonSelectionColor(new Color(1, 1, 1, 1));
        setFont(null);

        ImageIcon customIcon = null;
        String customText = value.toString();

        // Now we 'tweak' the component a bit to get the look we want.
        if (value instanceof ExplorerGemNode) {

            ExplorerGemNode explorerNode = (ExplorerGemNode) value;
            Gem gem = explorerNode.getGem();

            // Get the customized name and icon
            customIcon = getGemDisplayIcon(gem);
            customText = getGemDisplayString(gem);           

        } else if (value instanceof DefaultMutableTreeNode) {

            // Other nodes in the trees are dealt with here
            DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value;

            if (treeNode.isRoot()) {
                customIcon = ExplorerRootNode.rootNodeIcon;

            } else if (treeNode.getUserObject() instanceof Gem.PartInput) {

                Gem.PartInput input = (Gem.PartInput) treeNode.getUserObject();
                ValueNode valueNode = tableTopExplorerOwner.getValueNode(input);
                ArgumentMetadata metadata = input.getDesignMetadata();

                if (tableTopExplorerOwner.highlightInput(input)) {
                    // TODO: instead of hardcoding the highlighted font style, perhaps the renderer
                    //       should be passed to the highlight fn and let it set whatever is appropriate...
                    setTextNonSelectionColor(Color.RED);
                    setFont(tree.getFont().deriveFont(Font.ITALIC));
                }

                if (tableTopExplorerOwner.canEditInputsAsValues() && valueNode != null && !input.isBurnt()) {
                    customText = input.getArgumentName().getCompositeName() + ":  " + valueNode.getTextValue();

                } else {
                    customIcon = partInputIcon;

                    if (input.isBurnt()) {
                        setTextNonSelectionColor(Color.RED.darker());
                        setTextSelectionColor(Color.WHITE);
                        setBackgroundSelectionColor(Color.RED.darker());
                        customIcon = burnIcon;                     
                    }

                    if (metadata.getShortDescription() != null) {
                        customText = input.getArgumentName().getCompositeName() + " - " + metadata.getShortDescription();
                    } else {
                        customText = input.getArgumentName().getCompositeName();
                    }
                }
            }
        }

        // If we are using the banded look and feel then we don't want the super class to draw focus
        // borders around the objects.  They look funny with the banded background colour.
        if (useBandedLookAndFeel) {
            hasFocus = false;
        }

        super.getTreeCellRendererComponent(tree, customText, sel, expanded, leaf, row, hasFocus);

        if (customIcon != null) {
            setIcon(customIcon);
        }

        return this;
    }      

    /**
     * Returns whether the current node should be rendered as a hyperlink.
     * @return Returns true is the current node is focusable and should be drawn as a hyperlink.
     */
    boolean renderAsHyperlink() {
        return focusable;
    }

    /**
     * Determines if the point in question is over the icon portion of the rendered node.
     * @return whether the point in question is over the icon portion of the rendered node.
     */
    boolean isPointOverIcon(Point p) {
        // Assume all icons are the same size and arbitrarily check the first icon
        return (p.x < constructorIcon.getIconWidth());
    }

    /**
     * Determines the suitable display string for the gem and returns it.  The default behaviour is to
     * use the unqualified gem name unless ambiguous.  Different subclasses may have different behaviour
     * such as different naming policies or using portions of the metadata.
     * @param gem
     * @return A string that will be rendered as part of a gem node in the explorer tree
     */       
    protected String getGemDisplayString(Gem gem) {
        // different icons and text for each type of gem
        if (gem instanceof FunctionalAgentGem) {
            ModuleTypeInfo currentModuleTypeInfo = tableTopExplorerOwner.getCurrentModuleTypeInfo();
            if (currentModuleTypeInfo == null) {
                return null;
            }
            ScopedEntityNamingPolicy namingPolicy = new UnqualifiedUnlessAmbiguous(currentModuleTypeInfo);
            FunctionalAgentGem functionalAgentGem = (FunctionalAgentGem) gem;
            return functionalAgentGem.getGemEntity().getAdaptedName(namingPolicy);

        } else if (gem instanceof CodeGem) {
            return ((CodeGem)gem).getUnqualifiedName();

        } else if (gem instanceof ValueGem) {
            return ((ValueGem)gem).getTextValue();

        } else if (gem instanceof CollectorGem) {
            // Start with the unqualified collector gem name
            return ((CollectorGem)gem).getUnqualifiedName();

        } else if (gem instanceof ReflectorGem) {
            return ((ReflectorGem)gem).getUnqualifiedName();
           
        } else if (gem instanceof RecordFieldSelectionGem) {
            return ((RecordFieldSelectionGem)gem).getDisplayedText();

        } else if (gem instanceof RecordCreationGem) {
            return ((RecordCreationGem)gem).getDisplayName();

        } else {
            return gem.toString();
        }
    }

    /**
     * Determines the suitable icon for the gem and returns it.
     * @param gem
     * @return An icon that will be rendered as part of a gem node in the explorer tree
     */       
    protected ImageIcon getGemDisplayIcon(Gem gem) {
        // different icons for each type of gem
        if (gem instanceof FunctionalAgentGem) {
            FunctionalAgentGem functionalAgentGem = (FunctionalAgentGem) gem;
            FunctionalAgent functionalAgent = functionalAgentGem.getGemEntity().getFunctionalAgent();

            if (functionalAgent instanceof Function || functionalAgent instanceof ClassMethod) {
                return supercombinatorIcon;
            } else if (functionalAgent instanceof DataConstructor) {
                return constructorIcon;
            } else {
                return null;
            }
        } else if (gem instanceof CodeGem) {
            return gem.isBroken() ? brokenCodeGemIcon : codeGemIcon;

        } else if (gem instanceof ValueGem) {
            return valueIcon;

        } else if (gem instanceof CollectorGem) {
            return ((CollectorGem)gem).getTargetCollector() == null ? minorTargetIcon : collectorIcon;

        } else if (gem instanceof ReflectorGem) {
            return gem.isBroken() ? brokenReflectorGemIcon :
                (gem.getNInputs() == 0) ? emitterIcon : reflectorIcon;
       
        } else if (gem instanceof RecordFieldSelectionGem) {
            return recordFieldSelectionIcon;
           
        } else if (gem instanceof RecordCreationGem) {
            return recordCreationIcon;
           
        }
        else {
            return null;
        }
    }
}

/**
* A look and feel for painting JLabel text.  If the label to be painted is an instance of a
* HyperlinkedExplorerCellRenderer and it is set to render as a hyperlink then the painting will try
* to mimic the default hyperlink style used in browsers (underlined with blue font colour).  
*/
class HyperlinkLabelUI extends BasicLabelUI {
    /** A singleton object holding onto the UI that can be shared by all label components. */
    private final static HyperlinkLabelUI hyperlinkLabelUI = new HyperlinkLabelUI();

    /**
     * Static method to fetch the UI
     * @param c The component that we are fetching UI for.  This is ignored, but assumed to be an
     * instance of a JLabel
     * @return ComponentUI returns the singleton object for this class.
     */
    public static ComponentUI createUI(JComponent c){
        return hyperlinkLabelUI;
    }

    /**
     * If the label is an instance of HyperlinkedExplorerCellRenderer and it is set to render as a
     * hyperlink then the font colour is changed to blue and the text is underlined.  Otherwise the
     * text is painted as ordinary text.
     * @param l The label that this UI is associated with
     * @param g The graphics used for painting
     * @param s The string that should be painted
     * @param textX The X offset to start painting at
     * @param textY the Y offset to start painting at
     */
    private void paintHyperlinkedText(JLabel l, Graphics g, String s, int textX, int textY) {
        // The label should actually be a HyperlinkedExplorerCellRenderer
        if (l instanceof ExplorerCellRenderer) {
            ExplorerCellRenderer renderer = (ExplorerCellRenderer)l;
            if (renderer.renderAsHyperlink()) {
                // Create an attributed string so that the characters are underlined and blue
                Map<TextAttribute, Object> attrs = new HashMap<TextAttribute, Object>();
                attrs.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL);
                attrs.put(TextAttribute.FONT, renderer.getFont());

                // If the label is using the selected colour then render the hyperlink in white text
                // since it will look a lot better than blue given the default dark blue selection colour.
                // Otherwise the text should be rendered blue like a normal hyperlink.
                if (renderer.getForeground() == renderer.getTextSelectionColor()) {
                    attrs.put(TextAttribute.FOREGROUND, Color.WHITE);
                } else {
                    attrs.put(TextAttribute.FOREGROUND, Color.BLUE);
                }

                AttributedString attrString = new AttributedString(s, attrs);

                // Draw the 'hyperlink' string
                g.drawString(attrString.getIterator(), textX, textY);
                return;
            }
        }

        // If this is not the right renderer or not a hyperlink then simply draw the plain text
        g.drawString(s, textX, textY);
    }

    /**
     * Paints the text for an enabled node.
     * @param l The label that this UI is associated with
     * @param g The graphics used for painting
     * @param s The string that should be painted
     * @param textX The X offset to start painting at
     * @param textY the Y offset to start painting at
     */
    @Override
    protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, int textY) {
        paintHyperlinkedText(l, g, s, textX, textY);
    }

    /**
     * Paints the text for a disabled node.  This currently paints the node exactly the same as an
     * enabled node.
     * @param l The label that this UI is associated with
     * @param g The graphics used for painting
     * @param s The string that should be painted
     * @param textX The X offset to start painting at
     * @param textY the Y offset to start painting at
     */
    @Override
    protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, int textY) {
        paintHyperlinkedText(l, g, s, textX, textY);
    }
}
TOP

Related Classes of org.openquark.gems.client.explorer.HyperlinkLabelUI

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.