001    /*
002     * $Id: DefaultXTreeCellEditor.java,v 1.3 2006/01/12 15:15:56 kleopatra Exp $
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     */
021    package org.jdesktop.swingx.tree;
022    
023    import java.awt.ComponentOrientation;
024    import java.awt.Container;
025    import java.awt.Dimension;
026    import java.awt.Graphics;
027    
028    import javax.swing.Icon;
029    import javax.swing.JTree;
030    import javax.swing.tree.DefaultTreeCellEditor;
031    import javax.swing.tree.DefaultTreeCellRenderer;
032    import javax.swing.tree.TreeCellEditor;
033    
034    /**
035     * Subclassed to hack around core bug with RtoL editing (#4980473).
036     * 
037     * The price to pay is currently is to guarantee a minimum size of the
038     * editing field (is only one char wide if the node value is null).
039     * 
040     * PENDING: any possibility to position the editorContainer? 
041     * BasicTreeUI adds it to the tree and positions at the node location. 
042     * That's not a problem in LToR, only
043     * in RToL 
044     *
045     * 
046     * @author Jeanette Winzenburg
047     */
048    public class DefaultXTreeCellEditor extends DefaultTreeCellEditor {
049    
050        public DefaultXTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer) {
051            super(tree, renderer);
052        }
053    
054        public DefaultXTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer,
055                TreeCellEditor editor) {
056            super(tree, renderer, editor);
057        }
058    
059        public void setRenderer(DefaultTreeCellRenderer renderer) {
060            this.renderer = renderer;
061        }
062        
063        public class XEditorContainer extends EditorContainer {
064    
065            @Override
066            public Dimension getPreferredSize() {
067                if (isRightToLeft()) {
068                    if(editingComponent != null) {
069                        Dimension         pSize = editingComponent.getPreferredSize();
070        
071                        pSize.width += offset + 5;
072        
073                        Dimension         rSize = (renderer != null) ?
074                                                  renderer.getPreferredSize() : null;
075        
076                        if(rSize != null)
077                            pSize.height = Math.max(pSize.height, rSize.height);
078                        if(editingIcon != null)
079                            pSize.height = Math.max(pSize.height,
080                                                    editingIcon.getIconHeight());
081        
082                        // trying to enforce a minimum size leads to field being painted over the icon
083                        // Make sure width is at least 100.
084        //                pSize.width = Math.max(pSize.width, 100);
085                        return pSize;
086                    }
087                    return new Dimension(0, 0);
088                }
089                return super.getPreferredSize();
090                
091            }
092    
093            @Override
094            public void doLayout() {
095                if (isRightToLeft()) {
096                    Dimension             cSize = getSize();
097    
098                    editingComponent.getPreferredSize();
099                    editingComponent.setLocation(0, 0);
100                    editingComponent.setBounds(0, 0,
101                                               cSize.width - offset,
102                                               cSize.height);
103                } else {
104    
105                    super.doLayout();
106                }
107            }
108    
109    
110            @Override
111            public void paint(Graphics g) {
112                if (isRightToLeft()) {
113                    Dimension size = getSize();
114    
115                    // Then the icon.
116                    if (editingIcon != null) {
117                        int yLoc = Math.max(0, (size.height - editingIcon
118                                .getIconHeight()) / 2);
119                        int xLoc = Math.max(0, size.width - offset);
120                        editingIcon.paintIcon(this, g, xLoc, yLoc);
121                    }
122                    // need to prevent super from painting the icon
123                    Icon rememberIcon = editingIcon;
124                    editingIcon = null;
125                    super.paint(g);
126                    editingIcon = rememberIcon;
127                    
128                } else {
129                    super.paint(g);
130                }
131            }
132            
133        }
134    
135    
136        @Override
137        protected Container createContainer() {
138            return new XEditorContainer();
139        }
140    
141        @Override
142        protected void prepareForEditing() {
143            super.prepareForEditing();
144            applyComponentOrientation();
145        }
146    
147        protected void applyComponentOrientation() {
148            if (tree != null) {
149                editingContainer.applyComponentOrientation(tree.getComponentOrientation());
150            }
151            
152        }
153    
154        /**
155         * @return
156         */
157        private boolean isRightToLeft() {
158            return (tree != null) && (!tree.getComponentOrientation().isLeftToRight());
159        }
160    
161    }