001/*
002 * $Id: DefaultXTreeCellEditor.java 3927 2011-02-22 16:34:11Z kleopatra $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 * 
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 * Lesser General Public License for more details.
016 * 
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020 */
021package org.jdesktop.swingx.tree;
022
023import java.awt.Container;
024import java.awt.Dimension;
025import java.awt.Graphics;
026
027import javax.swing.Icon;
028import javax.swing.JComponent;
029import javax.swing.JTree;
030import javax.swing.SwingUtilities;
031import javax.swing.tree.DefaultTreeCellEditor;
032import javax.swing.tree.DefaultTreeCellRenderer;
033import javax.swing.tree.TreeCellEditor;
034
035import org.jdesktop.swingx.plaf.UIDependent;
036
037/**
038 * Subclassed to hack around core bug with RtoL editing (#4980473).
039 * 
040 * The price to pay is currently is to guarantee a minimum size of the
041 * editing field (is only one char wide if the node value is null).
042 * 
043 * PENDING: any possibility to position the editorContainer? 
044 * BasicTreeUI adds it to the tree and positions at the node location. 
045 * That's not a problem in LToR, only
046 * in RToL 
047 *
048 * 
049 * @author Jeanette Winzenburg
050 */
051public class DefaultXTreeCellEditor extends DefaultTreeCellEditor implements UIDependent {
052
053    public DefaultXTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
054        super(tree, renderer);
055    }
056
057    public DefaultXTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer,
058            TreeCellEditor editor) {
059        super(tree, renderer, editor);
060    }
061
062    public void setRenderer(DefaultTreeCellRenderer renderer) {
063        this.renderer = renderer;
064    }
065    
066    public DefaultTreeCellRenderer getRenderer() {
067        return renderer;
068    }
069    
070    public class XEditorContainer extends EditorContainer {
071
072        @Override
073        public Dimension getPreferredSize() {
074            if (isRightToLeft()) {
075                if(editingComponent != null) {
076                    Dimension         pSize = editingComponent.getPreferredSize();
077    
078                    pSize.width += offset + 5;
079    
080                    Dimension         rSize = (renderer != null) ?
081                                              renderer.getPreferredSize() : null;
082    
083                    if(rSize != null)
084                        pSize.height = Math.max(pSize.height, rSize.height);
085                    if(editingIcon != null)
086                        pSize.height = Math.max(pSize.height,
087                                                editingIcon.getIconHeight());
088    
089                    // trying to enforce a minimum size leads to field being painted over the icon
090                    // Make sure width is at least 100.
091    //                pSize.width = Math.max(pSize.width, 100);
092                    return pSize;
093                }
094                return new Dimension(0, 0);
095            }
096            return super.getPreferredSize();
097            
098        }
099
100        @Override
101        public void doLayout() {
102            if (isRightToLeft()) {
103                Dimension             cSize = getSize();
104
105                editingComponent.getPreferredSize();
106                editingComponent.setLocation(0, 0);
107                editingComponent.setBounds(0, 0,
108                                           cSize.width - offset,
109                                           cSize.height);
110            } else {
111
112                super.doLayout();
113            }
114        }
115
116
117        @Override
118        public void paint(Graphics g) {
119            if (isRightToLeft()) {
120                Dimension size = getSize();
121
122                // Then the icon.
123                if (editingIcon != null) {
124                    int yLoc = Math.max(0, (size.height - editingIcon
125                            .getIconHeight()) / 2);
126                    int xLoc = Math.max(0, size.width - offset);
127                    editingIcon.paintIcon(this, g, xLoc, yLoc);
128                }
129                // need to prevent super from painting the icon
130                Icon rememberIcon = editingIcon;
131                editingIcon = null;
132                super.paint(g);
133                editingIcon = rememberIcon;
134                
135            } else {
136                super.paint(g);
137            }
138        }
139        
140    }
141
142
143    @Override
144    protected Container createContainer() {
145        return new XEditorContainer();
146    }
147
148    @Override
149    protected void prepareForEditing() {
150        super.prepareForEditing();
151        applyComponentOrientation();
152    }
153
154    protected void applyComponentOrientation() {
155        if (tree != null) {
156            editingContainer.applyComponentOrientation(tree.getComponentOrientation());
157        }
158        
159    }
160
161    /**
162     * @return
163     */
164    private boolean isRightToLeft() {
165        return (tree != null) && (!tree.getComponentOrientation().isLeftToRight());
166    }
167
168    /**
169     * Implement UIDependent. Quick hack for #1060-swingx: icons lost on laf toggle.
170     */
171    @Override
172    public void updateUI() {
173        if (getRenderer() != null) {
174            SwingUtilities.updateComponentTreeUI(getRenderer());
175        }
176        if (realEditor instanceof JComponent) {
177            SwingUtilities.updateComponentTreeUI((JComponent) realEditor);
178        } else if (realEditor instanceof UIDependent) {
179            ((UIDependent) realEditor).updateUI();
180        }
181        
182    }
183
184}