~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to refactoring/java/src/org/netbeans/modules/refactoring/java/ui/ExtractInterfacePanel.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
package org.netbeans.modules.refactoring.java.ui;
 
42
 
 
43
import com.sun.source.tree.ClassTree;
 
44
import com.sun.source.tree.Tree;
 
45
import com.sun.source.tree.VariableTree;
 
46
import com.sun.source.util.TreePath;
 
47
import java.awt.Component;
 
48
import java.awt.Dimension;
 
49
import java.io.IOException;
 
50
import java.util.ArrayList;
 
51
import java.util.Collections;
 
52
import java.util.Comparator;
 
53
import java.util.List;
 
54
import java.util.Set;
 
55
import javax.lang.model.element.Element;
 
56
import javax.lang.model.element.ElementKind;
 
57
import javax.lang.model.element.ExecutableElement;
 
58
import javax.lang.model.element.Modifier;
 
59
import javax.lang.model.element.VariableElement;
 
60
import javax.lang.model.type.TypeMirror;
 
61
import javax.swing.Icon;
 
62
import javax.swing.JPanel;
 
63
import javax.swing.JTable;
 
64
import javax.swing.UIManager;
 
65
import javax.swing.event.ChangeListener;
 
66
import javax.swing.event.DocumentEvent;
 
67
import javax.swing.event.DocumentListener;
 
68
import javax.swing.table.AbstractTableModel;
 
69
import javax.swing.table.DefaultTableCellRenderer;
 
70
import org.netbeans.api.java.source.CancellableTask;
 
71
import org.netbeans.api.java.source.CompilationController;
 
72
import org.netbeans.api.java.source.ElementHandle;
 
73
import org.netbeans.api.java.source.JavaSource;
 
74
import org.netbeans.api.java.source.TreePathHandle;
 
75
import org.netbeans.api.java.source.TypeMirrorHandle;
 
76
import org.netbeans.api.java.source.UiUtils;
 
77
import org.netbeans.api.java.source.UiUtils.PrintPart;
 
78
import org.netbeans.modules.refactoring.java.api.ExtractInterfaceRefactoring;
 
79
import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
 
80
import org.openide.filesystems.FileObject;
 
81
import org.openide.util.NbBundle;
 
82
 
 
83
/** UI panel for collecting refactoring parameters.
 
84
 *
 
85
 * @author Martin Matula, Jan Becicka, Jan Pokorsky
 
86
 */
 
87
public final class ExtractInterfacePanel extends JPanel implements CustomRefactoringPanel {
 
88
    // helper constants describing columns in the table of members
 
89
    private static final String[] COLUMN_NAMES = {"LBL_Selected", "LBL_ExtractInterface_Member"}; // NOI18N
 
90
    private static final Class[] COLUMN_CLASSES = {Boolean.class, TreePathHandle.class};
 
91
    
 
92
    // refactoring this panel provides parameters for
 
93
    private final ExtractInterfaceRefactoring refactoring;
 
94
    // table model for the table of members
 
95
    private final TableModel tableModel;
 
96
    // data for the members table (first dimension - rows, second dimension - columns)
 
97
    // the columns are: 0 = Selected (true/false), 1 = ExtractInterfaceInfo (Java element)
 
98
    private Object[][] members = new Object[0][0];
 
99
    
 
100
    /** Creates new form ExtractInterfacePanel
 
101
     * @param refactoring The refactoring this panel provides parameters for.
 
102
     */
 
103
    public ExtractInterfacePanel(ExtractInterfaceRefactoring refactoring, final ChangeListener parent) {
 
104
        this.refactoring = refactoring;
 
105
        this.tableModel = new TableModel();
 
106
        initComponents();
 
107
        setPreferredSize(new Dimension(420, 380));
 
108
        String defaultName = "NewInterface"; //NOI18N
 
109
        nameText.setText(defaultName); 
 
110
        nameText.setSelectionStart(0);
 
111
        nameText.setSelectionEnd(defaultName.length());
 
112
        nameText.getDocument().addDocumentListener(new DocumentListener() {
 
113
            public void changedUpdate(DocumentEvent event) {
 
114
                parent.stateChanged(null);
 
115
            }
 
116
            public void insertUpdate(DocumentEvent event) {
 
117
                parent.stateChanged(null);
 
118
            }
 
119
            public void removeUpdate(DocumentEvent event) {
 
120
                parent.stateChanged(null);
 
121
            }
 
122
        });
 
123
    }
 
124
    
 
125
    public void requestFocus() {
 
126
        super.requestFocus();
 
127
        nameText.requestFocus();
 
128
    }
 
129
    
 
130
 
 
131
    /** Initialization of the panel (called by the parent window).
 
132
     */
 
133
    public void initialize() {
 
134
        // *** initialize table
 
135
        // set renderer for the second column ("Member") to display name of the feature
 
136
        membersTable.setDefaultRenderer(COLUMN_CLASSES[1], new DefaultTableCellRenderer() {
 
137
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
 
138
                super.getTableCellRendererComponent(table, extractText(value), isSelected, hasFocus, row, column);
 
139
                if (value instanceof ExtractInterfaceInfo) {
 
140
                    setIcon(((ExtractInterfaceInfo) value).icon);
 
141
                }
 
142
                return this;
 
143
            }
 
144
            protected String extractText(Object value) {
 
145
                String displayValue;
 
146
                if (value instanceof ExtractInterfaceInfo) {
 
147
                    displayValue = ((ExtractInterfaceInfo) value).htmlText;
 
148
                } else {
 
149
                    displayValue = String.valueOf(value);
 
150
                }
 
151
                return displayValue;
 
152
            }
 
153
        });
 
154
        // set background color of the scroll pane to be the same as the background
 
155
        // of the table
 
156
        scrollPane.setBackground(membersTable.getBackground());
 
157
        scrollPane.getViewport().setBackground(membersTable.getBackground());
 
158
        // set default row height
 
159
        membersTable.setRowHeight(18);
 
160
        // set grid color to be consistent with other netbeans tables
 
161
        if (UIManager.getColor("control") != null) { // NOI18N
 
162
            membersTable.setGridColor(UIManager.getColor("control")); // NOI18N
 
163
        }
 
164
        // compute and set the preferred width for the first and the third column
 
165
        UIUtilities.initColumnWidth(membersTable, 0, Boolean.TRUE, 4);
 
166
    }
 
167
    
 
168
    // --- GETTERS FOR REFACTORING PARAMETERS ----------------------------------
 
169
    
 
170
    /** stores data collected via the panel.
 
171
     */
 
172
    public void storeSettings() {
 
173
        List<ElementHandle<VariableElement>> fields = new ArrayList<ElementHandle<VariableElement>>();
 
174
        List<ElementHandle<ExecutableElement>> methods = new ArrayList<ElementHandle<ExecutableElement>>();
 
175
        List<TypeMirrorHandle<TypeMirror>> implementz = new ArrayList<TypeMirrorHandle<TypeMirror>>();
 
176
        
 
177
        List<TreePathHandle> list = new ArrayList<TreePathHandle>();
 
178
        // go through all rows of a table and collect selected members
 
179
        for (int i = 0; i < members.length; i++) {
 
180
            if (members[i][0].equals(Boolean.TRUE)) {
 
181
                ExtractInterfaceInfo info = (ExtractInterfaceInfo) members[i][1];
 
182
                switch(info.group) {
 
183
                case FIELD: fields.add((ElementHandle<VariableElement>) info.handle); break;
 
184
                case METHOD: methods.add((ElementHandle<ExecutableElement>) info.handle); break;
 
185
                case IMPLEMENTS: implementz.add((TypeMirrorHandle<TypeMirror>) info.handle); break;
 
186
                }
 
187
            }
 
188
        }
 
189
        
 
190
        refactoring.setFields(fields);
 
191
        refactoring.setImplements(implementz);
 
192
        refactoring.setMethods(methods);
 
193
        refactoring.setInterfaceName(nameText.getText());
 
194
    }
 
195
    
 
196
    // --- GENERATED CODE ------------------------------------------------------
 
197
    
 
198
    /** This method is called from within the constructor to
 
199
     * initialize the form.
 
200
     * WARNING: Do NOT modify this code. The content of this method is
 
201
     * always regenerated by the Form Editor.
 
202
     */
 
203
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
 
204
    private void initComponents() {
 
205
 
 
206
        namePanel = new javax.swing.JPanel();
 
207
        nameLabel = new javax.swing.JLabel();
 
208
        chooseLabel = new javax.swing.JLabel();
 
209
        nameText = new javax.swing.JTextField();
 
210
        scrollPane = new javax.swing.JScrollPane();
 
211
        membersTable = new javax.swing.JTable();
 
212
 
 
213
        setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12, 11, 11));
 
214
        setLayout(new java.awt.BorderLayout());
 
215
 
 
216
        namePanel.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
 
217
        namePanel.setLayout(new java.awt.BorderLayout(12, 0));
 
218
 
 
219
        nameLabel.setLabelFor(nameText);
 
220
        org.openide.awt.Mnemonics.setLocalizedText(nameLabel, org.openide.util.NbBundle.getMessage(ExtractInterfacePanel.class, "LBL_ExtractInterface_Name")); // NOI18N
 
221
        namePanel.add(nameLabel, java.awt.BorderLayout.WEST);
 
222
        nameLabel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(ExtractInterfacePanel.class, "ACSD_InterfaceName")); // NOI18N
 
223
        nameLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ExtractInterfacePanel.class, "ACSD_InterfaceNameDescription")); // NOI18N
 
224
 
 
225
        chooseLabel.setLabelFor(membersTable);
 
226
        org.openide.awt.Mnemonics.setLocalizedText(chooseLabel, org.openide.util.NbBundle.getMessage(ExtractInterfacePanel.class, "LBL_ExtractInterfaceLabel")); // NOI18N
 
227
        chooseLabel.setBorder(javax.swing.BorderFactory.createEmptyBorder(6, 0, 0, 0));
 
228
        namePanel.add(chooseLabel, java.awt.BorderLayout.SOUTH);
 
229
        chooseLabel.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(ExtractInterfacePanel.class, "ExtractInterfacePanel.chooseLabel.AccessibleContext.accessibleDescription")); // NOI18N
 
230
 
 
231
        namePanel.add(nameText, java.awt.BorderLayout.CENTER);
 
232
 
 
233
        add(namePanel, java.awt.BorderLayout.NORTH);
 
234
 
 
235
        membersTable.setModel(tableModel);
 
236
        membersTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
 
237
        scrollPane.setViewportView(membersTable);
 
238
        membersTable.getAccessibleContext().setAccessibleName(null);
 
239
        membersTable.getAccessibleContext().setAccessibleDescription(null);
 
240
 
 
241
        add(scrollPane, java.awt.BorderLayout.CENTER);
 
242
    }// </editor-fold>//GEN-END:initComponents
 
243
    
 
244
    
 
245
    // Variables declaration - do not modify//GEN-BEGIN:variables
 
246
    private javax.swing.JLabel chooseLabel;
 
247
    private javax.swing.JTable membersTable;
 
248
    private javax.swing.JLabel nameLabel;
 
249
    private javax.swing.JPanel namePanel;
 
250
    private javax.swing.JTextField nameText;
 
251
    private javax.swing.JScrollPane scrollPane;
 
252
    // End of variables declaration//GEN-END:variables
 
253
    
 
254
    // --- MODELS --------------------------------------------------------------
 
255
    
 
256
    /** Model for the members table.
 
257
     */
 
258
    private class TableModel extends AbstractTableModel {
 
259
        TableModel() {
 
260
            initialize();
 
261
        }
 
262
        
 
263
        public int getColumnCount() {
 
264
            return COLUMN_NAMES.length;
 
265
        }
 
266
 
 
267
        public String getColumnName(int column) {
 
268
            return UIUtilities.getColumnName(NbBundle.getMessage(ExtractInterfacePanel.class, COLUMN_NAMES[column]));
 
269
        }
 
270
 
 
271
        public Class getColumnClass(int columnIndex) {
 
272
            return COLUMN_CLASSES[columnIndex];
 
273
        }
 
274
 
 
275
        public int getRowCount() {
 
276
            return members.length;
 
277
        }
 
278
 
 
279
        public Object getValueAt(int rowIndex, int columnIndex) {
 
280
            return members[rowIndex][columnIndex];
 
281
        }
 
282
 
 
283
        public void setValueAt(Object value, int rowIndex, int columnIndex) {
 
284
            members[rowIndex][columnIndex] = value;
 
285
        }
 
286
 
 
287
        public boolean isCellEditable(int rowIndex, int columnIndex) {
 
288
            // column 0 is always editable, column 1 is never editable
 
289
            return columnIndex == 0;
 
290
        }
 
291
        
 
292
 
 
293
        private void initialize() {
 
294
            final TreePathHandle sourceType = refactoring.getSourceType();
 
295
            if (sourceType == null) return;
 
296
            
 
297
            FileObject fo = sourceType.getFileObject();
 
298
            JavaSource js = JavaSource.forFileObject(fo);
 
299
            try {
 
300
                js.runUserActionTask(new CancellableTask<CompilationController>() {
 
301
                        public void cancel() {
 
302
                        }
 
303
 
 
304
                        public void run(CompilationController javac) throws Exception {
 
305
                            javac.toPhase(JavaSource.Phase.RESOLVED);
 
306
                            initializeInTransaction(javac, sourceType);
 
307
                        }
 
308
 
 
309
                    }, true);
 
310
            } catch (IOException ex) {
 
311
                new IllegalStateException(ex);
 
312
            }
 
313
        }
 
314
        
 
315
        private void initializeInTransaction(CompilationController javac, TreePathHandle sourceType) {
 
316
            TreePath sourceTreePath = sourceType.resolve(javac);
 
317
            ClassTree sourceTree = (ClassTree) sourceTreePath.getLeaf();
 
318
            List result = new ArrayList();
 
319
            
 
320
            for (Tree implTree : sourceTree.getImplementsClause()) {
 
321
                TreePath implPath = javac.getTrees().getPath(javac.getCompilationUnit(), implTree);
 
322
                TypeMirror implMirror = javac.getTrees().getTypeMirror(implPath);
 
323
                result.add(new ExtractInterfaceInfo<TypeMirrorHandle>(
 
324
                        TypeMirrorHandle.create(implMirror),
 
325
                        "implements " + implTree.toString(), // NOI18N
 
326
                        UiUtils.getElementIcon(ElementKind.INTERFACE, null),
 
327
                        implTree.toString(),
 
328
                        Group.IMPLEMENTS
 
329
                        ));
 
330
            }
 
331
            
 
332
            for (Tree member : sourceTree.getMembers()) {
 
333
                TreePath memberTreePath = javac.getTrees().getPath(javac.getCompilationUnit(), member);
 
334
                if (javac.getTreeUtilities().isSynthetic(memberTreePath))
 
335
                    continue;
 
336
                
 
337
                Element memberElm = javac.getTrees().getElement(memberTreePath);
 
338
                Set<Modifier> mods;
 
339
                if (memberElm == null || !(mods = memberElm.getModifiers()).contains(Modifier.PUBLIC))
 
340
                    continue;
 
341
                
 
342
                Group group;
 
343
                String format = PrintPart.NAME;
 
344
                if (memberElm.getKind() == ElementKind.FIELD) {
 
345
                    if (!mods.contains(Modifier.STATIC) || !mods.contains(Modifier.FINAL)
 
346
                            || ((VariableTree) member).getInitializer() == null)
 
347
                        continue;
 
348
                    group = Group.FIELD;
 
349
                    format += " : " + PrintPart.TYPE; // NOI18N
 
350
// XXX see ExtractInterfaceRefactoringPlugin class description
 
351
//                } else if (member.getKind() == Tree.Kind.CLASS) {
 
352
//                    if (!mods.contains(Modifier.STATIC))
 
353
//                        continue;
 
354
//                    group = 3;
 
355
                } else if (memberElm.getKind() == ElementKind.METHOD) {
 
356
                    if (mods.contains(Modifier.STATIC))
 
357
                        continue;
 
358
                    group = Group.METHOD;
 
359
                    format += PrintPart.PARAMETERS + " : " + PrintPart.TYPE; // NOI18N
 
360
                } else {
 
361
                    continue;
 
362
                }
 
363
                result.add(new ExtractInterfaceInfo<ElementHandle>(
 
364
                        ElementHandle.create(memberElm),
 
365
                        UiUtils.getHeader(memberElm, javac, format),
 
366
                        UiUtils.getElementIcon(memberElm.getKind(), mods),
 
367
                        memberElm.getSimpleName().toString(),
 
368
                        group
 
369
                        ));
 
370
            }
 
371
 
 
372
            // the members are collected
 
373
            // now, create a tree map (to sort them) and create the table data
 
374
            Collections.sort(result, new Comparator() {
 
375
                public int compare(Object o1, Object o2) {
 
376
                    ExtractInterfaceInfo i1 = (ExtractInterfaceInfo) o1;
 
377
                    ExtractInterfaceInfo i2 = (ExtractInterfaceInfo) o2;
 
378
                    int result = i1.group.compareTo(i2.group);
 
379
                    
 
380
                    if (result == 0) {
 
381
                        result = i1.name.compareTo(i2.name);
 
382
                    }
 
383
                    
 
384
                    return result;
 
385
                }
 
386
            });
 
387
            members = new Object[result.size()][2];
 
388
            for (int i = 0; i < members.length; i++) {
 
389
                members[i][0] = Boolean.FALSE;
 
390
                members[i][1] = result.get(i);
 
391
            }
 
392
            // fire event to repaint the table
 
393
            this.fireTableDataChanged();
 
394
        }
 
395
    }
 
396
 
 
397
    public Component getComponent() {
 
398
        return this;
 
399
    }
 
400
    
 
401
    private static final class ExtractInterfaceInfo<H> {
 
402
        final H handle;
 
403
        final String htmlText;
 
404
        final Icon icon;
 
405
        final String name;
 
406
        final Group group;
 
407
        
 
408
        public ExtractInterfaceInfo(H handle, String htmlText, Icon icon, String name, Group group) {
 
409
            this.handle = handle;
 
410
            this.htmlText = htmlText;
 
411
            this.icon = icon;
 
412
            this.name = name;
 
413
            this.group = group;
 
414
        }
 
415
    }
 
416
    
 
417
    private enum Group {
 
418
        IMPLEMENTS, METHOD, FIELD;
 
419
    }
 
420
}