001    // GraphLab Project: http://graphlab.sharif.edu
002    // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
003    // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
004    package graphlab.ui.components.gpropertyeditor;
005    
006    import graphlab.ui.AttributeSetView;
007    
008    import javax.swing.*;
009    import javax.swing.table.TableCellRenderer;
010    import java.awt.*;
011    import java.util.HashMap;
012    import java.util.Set;
013    import java.util.Map;
014    import java.util.Collections;
015    
016    /**
017     * this class is a part of gpropertyeditor, which creates a property editor with a jtable
018     * so it is implementation os TableCellRenderer. it returns a renderer for a cell by the
019     * "type of Object" that is stored in that cell.
020     * u can register for each class a renderer by the method registerRenderer.
021     *
022     * @see graphlab.ui.components.gpropertyeditor.GPropertyEditor
023     *
024     * @author azin azadi
025     */
026    public class GCellRenderer implements TableCellRenderer, ListCellRenderer {
027    
028        public static HashMap<Class, GBasicCellRenderer> knownRenderers = new HashMap<Class, GBasicCellRenderer>();
029        private AttributeSetView attributes;
030        //private int lastRow,lastColumn;
031        private HashMap<Integer, Component> lastRenderers = new HashMap<Integer, Component>();
032    
033        public static final Color SELECTED_COLOR = Color.red;
034        /**
035         * returns the last generated renderer by this object for the given row,
036         * note that this is not a very safe method, It may return a generated renderer for another table,
037         * so use it carefully
038         */
039        public Component getLastCreatedRenderer(int row) {
040            return lastRenderers.get(row);
041        }
042    
043    
044        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
045            String name = attributes.getNameAt(row);
046            GBasicCellRenderer ren = attributes.getrenderer(name);
047            Component rend = (ren != null ? ren.getRendererComponent(value) : getRendererFor(value));
048            lastRenderers.put(row, rend);
049            if (rend == null) {
050                return null;
051            }
052            int h = (int) rend.getPreferredSize().getHeight();
053            if (h > 5)
054                setRowHeight(table, row, h);
055            if (isSelected) {
056                rend.setForeground(SELECTED_COLOR);
057            }
058            return rend;
059        }
060    
061        private void setRowHeight(JTable table, int row, int h) {
062            if (table.getRowHeight(row) != h)
063                table.setRowHeight(row, h);
064        }
065    
066        /**
067         * return a renderer for he object from previously registered renderers
068         */
069        public static Component getRendererFor(Object value) {
070            //todo: value=null => bug
071            //  lastRow=row;lastColumn=column;
072            if (value == null)
073                return null;
074    
075            //try to find the best renderer for value
076            GBasicCellRenderer renderer = null;
077            Class<? extends Object> valueClass = value.getClass();
078            Class c = valueClass;
079            //search super classes
080            while (renderer == null && c != Object.class) {
081                renderer = knownRenderers.get(c);
082                c = c.getSuperclass();
083            }
084            if (renderer == null)
085                for (Class cc : c.getInterfaces())
086                    if ((renderer = knownRenderers.get(cc)) != null) break;
087            if (renderer == null) {
088                //search implementing interfaces
089                Set<Class> keys = knownRenderers.keySet();
090    //            Class cc[] = value.getClass().getInterfaces();
091                for (Class cc : keys) {
092                    if (cc.isAssignableFrom(valueClass)) {
093                        renderer = knownRenderers.get(cc);
094                        break;
095                    }
096                }
097            }
098            if (renderer == null)
099                return new JLabel(value + "");
100            else return renderer.getRendererComponent(value);
101        }
102    
103        /**
104         * register the "renderer" for the "clazz". so after this, calls to getTableCellRendererComponent method will
105         * return this renderer if the value passed to that method has the same class with "clazz"
106         */
107        public static void registerRenderer(Class clazz, GBasicCellRenderer renderer) {
108    //        renderers.put(clazz, renderer);
109            knownRenderers.put(clazz, renderer);
110        }
111    
112        public void setAtrView(AttributeSetView attributes) {
113    
114            this.attributes = attributes;
115        }
116    
117        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
118            Component rendererFor = getRendererFor(value);
119            if (isSelected) {
120                rendererFor.setForeground(Color.red);
121                rendererFor.setBackground(Color.blue);
122            }
123            lastRenderers.put(index, rendererFor);
124            return rendererFor;
125        }
126    
127        /**
128         * @return known editors as an unmodifiable map
129         */
130        public static Map<Class, GBasicCellRenderer> getKnownRenderers(){
131            return Collections.unmodifiableMap(knownRenderers);
132        }
133    
134    }