001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.refactoring.java.ui;
042:
043: import java.awt.Component;
044: import java.awt.Dimension;
045: import java.io.IOException;
046: import java.util.ArrayList;
047: import java.util.Collection;
048: import java.util.Comparator;
049: import java.util.HashMap;
050: import java.util.Iterator;
051: import java.util.List;
052: import java.util.Map;
053: import java.util.Set;
054: import java.util.TreeMap;
055: import javax.lang.model.element.Element;
056: import javax.lang.model.element.ElementKind;
057: import javax.lang.model.element.Modifier;
058: import javax.lang.model.element.TypeElement;
059: import javax.lang.model.type.TypeMirror;
060: import javax.swing.AbstractListModel;
061: import javax.swing.ComboBoxModel;
062: import javax.swing.JPanel;
063: import javax.swing.JTable;
064: import javax.swing.UIManager;
065: import javax.swing.event.ChangeListener;
066: import javax.swing.event.TableModelEvent;
067: import javax.swing.event.TableModelListener;
068: import javax.swing.table.AbstractTableModel;
069: import org.netbeans.api.java.source.CancellableTask;
070: import org.netbeans.api.java.source.CancellableTask;
071: import org.netbeans.api.java.source.CompilationController;
072: import org.netbeans.api.java.source.CompilationController;
073: import org.netbeans.api.java.source.ElementHandle;
074: import org.netbeans.api.java.source.JavaSource;
075: import org.netbeans.api.java.source.TreePathHandle;
076: import org.netbeans.api.java.source.UiUtils;
077: import org.netbeans.modules.refactoring.java.RetoucheUtils;
078: import org.netbeans.modules.refactoring.java.api.MemberInfo;
079: import org.netbeans.modules.refactoring.java.api.MemberInfo;
080: import org.netbeans.modules.refactoring.java.api.MemberInfo;
081: import org.netbeans.modules.refactoring.java.api.MemberInfo;
082: import org.netbeans.modules.refactoring.java.api.PullUpRefactoring;
083: import org.netbeans.modules.refactoring.spi.ui.CustomRefactoringPanel;
084: import org.openide.util.NbBundle;
085: import org.openide.util.lookup.Lookups;
086:
087: /** UI panel for collecting refactoring parameters.
088: *
089: * @author Martin Matula, Jan Becicka
090: */
091: public class PullUpPanel extends JPanel implements
092: CustomRefactoringPanel {
093: // helper constants describing columns in the table of members
094: private static final String[] COLUMN_NAMES = {
095: "LBL_PullUp_Selected", "LBL_PullUp_Member",
096: "LBL_PullUp_MakeAbstract" }; // NOI18N
097: private static final Class[] COLUMN_CLASSES = { Boolean.class,
098: TreePathHandle.class, Boolean.class };
099:
100: // refactoring this panel provides parameters for
101: private final PullUpRefactoring refactoring;
102: // table model for the table of members
103: private final TableModel tableModel;
104: // pre-selected members (comes from the refactoring action - the elements
105: // that should be pre-selected in the table of members)
106: private Set<MemberInfo<ElementHandle>> selectedMembers;
107: // target type to move the members to
108: private MemberInfo<ElementHandle> targetType;
109: // data for the members table (first dimension - rows, second dimension - columns)
110: // the columns are: 0 = Selected (true/false), 1 = Member (Java element), 2 = Make Abstract (true/false)
111: private Object[][] members = new Object[0][0];
112: private ElementKind sourceKind;
113:
114: /** Creates new form PullUpPanel
115: * @param refactoring The refactoring this panel provides parameters for.
116: * @param selectedMembers Members that should be pre-selected in the panel
117: * (determined by which nodes the action was invoked on - e.g. if it was
118: * invoked on a method, the method will be pre-selected to be pulled up)
119: */
120: public PullUpPanel(PullUpRefactoring refactoring,
121: Set<MemberInfo<ElementHandle>> selectedMembers,
122: final ChangeListener parent) {
123: this .refactoring = refactoring;
124: this .tableModel = new TableModel();
125: this .selectedMembers = selectedMembers;
126: initComponents();
127: setPreferredSize(new Dimension(420, 380));
128: membersTable.getModel().addTableModelListener(
129: new TableModelListener() {
130: public void tableChanged(TableModelEvent e) {
131: parent.stateChanged(null);
132: }
133: });
134: }
135:
136: /** Initialization of the panel (called by the parent window).
137: */
138: public void initialize() {
139: final TreePathHandle handle = refactoring.getSourceType();
140: JavaSource source = JavaSource.forFileObject(handle
141: .getFileObject());
142: try {
143: source.runUserActionTask(
144: new CancellableTask<CompilationController>() {
145: public void cancel() {
146: }
147:
148: public void run(CompilationController controller)
149: throws Exception {
150: controller
151: .toPhase(JavaSource.Phase.RESOLVED);
152: // retrieve supertypes (will be used in the combo)
153: Collection<TypeElement> super types = RetoucheUtils
154: .getSuperTypes(
155: (TypeElement) handle
156: .resolveElement(controller),
157: controller, true);
158: MemberInfo[] minfo = new MemberInfo[super types
159: .size()];
160: int i = 0;
161: for (Element e : super types) {
162: minfo[i++] = MemberInfo.create(e,
163: controller);
164: }
165:
166: TypeElement sourceTypeElement = (TypeElement) handle
167: .resolveElement(controller);
168: sourceKind = sourceTypeElement.getKind();
169:
170: // *** initialize combo
171: // set renderer for the combo (to display name of the class)
172: super typeCombo
173: .setRenderer(new UIUtilities.JavaElementListCellRenderer()); // set combo model
174: super typeCombo.setModel(new ComboModel(
175: minfo));
176:
177: // *** initialize table
178: // set renderer for the second column ("Member") do display name of the feature
179: membersTable
180: .setDefaultRenderer(
181: COLUMN_CLASSES[1],
182: new UIUtilities.JavaElementTableCellRenderer() {
183: // override the extractText method to add "implements " prefix to the text
184: // in case the value is instance of MultipartId (i.e. it represents an interface
185: // name from implements clause)
186: protected String extractText(
187: Object value) {
188: String displayValue = super
189: .extractText(value);
190: if (value instanceof MemberInfo
191: && (((MemberInfo) value)
192: .getGroup() == MemberInfo.Group.IMPLEMENTS)) {
193: displayValue = "implements "
194: + displayValue; // NOI18N
195: }
196: return displayValue;
197: }
198: });
199: // send renderer for the third column ("Make Abstract") to make the checkbox:
200: // 1. hidden for elements that are not methods
201: // 2. be disabled for static methods
202: // 3. be disabled and checked for methods if the target type is an interface
203: // 4. be disabled and check for abstract methods
204: membersTable
205: .getColumnModel()
206: .getColumn(2)
207: .setCellRenderer(
208: new UIUtilities.BooleanTableCellRenderer() {
209: public Component getTableCellRendererComponent(
210: JTable table,
211: Object value,
212: boolean isSelected,
213: boolean hasFocus,
214: int row,
215: int column) {
216: // make the checkbox checked (even if "Make Abstract" is not set)
217: // for non-static methods if the target type is an interface
218: MemberInfo<ElementHandle> object = (MemberInfo<ElementHandle>) table
219: .getModel()
220: .getValueAt(
221: row,
222: 1);
223: if (object
224: .getElementHandle()
225: .getKind() == ElementKind.METHOD) {
226: if (targetType
227: .getElementHandle()
228: .getKind()
229: .isInterface()
230: && !((MemberInfo) object)
231: .getModifiers()
232: .contains(
233: Modifier.STATIC)
234: && !((MemberInfo) object)
235: .getModifiers()
236: .contains(
237: Modifier.ABSTRACT)) {
238: value = Boolean.TRUE;
239: }
240: }
241: //`the super method automatically makes sure the checkbox is not visible if the
242: // "Make Abstract" value is null (which holds for non-methods)
243: // and that the checkbox is disabled if the cell is not editable (which holds for
244: // static methods all the time and for all methods in case the target type is an interface
245: // - see the table model)
246: return super
247: .getTableCellRendererComponent(
248: table,
249: value,
250: isSelected,
251: hasFocus,
252: row,
253: column);
254: }
255: });
256: // set background color of the scroll pane to be the same as the background
257: // of the table
258: scrollPane.setBackground(membersTable
259: .getBackground());
260: scrollPane.getViewport().setBackground(
261: membersTable.getBackground());
262: // set default row height
263: membersTable.setRowHeight(18);
264: // set grid color to be consistent with other netbeans tables
265: if (UIManager.getColor("control") != null) { // NOI18N
266: membersTable.setGridColor(UIManager
267: .getColor("control")); // NOI18N
268: }
269: // compute and set the preferred width for the first and the third column
270: UIUtilities.initColumnWidth(membersTable,
271: 0, Boolean.TRUE, 4);
272: UIUtilities.initColumnWidth(membersTable,
273: 2, Boolean.TRUE, 4);
274: String name = UiUtils.getHeader(handle
275: .resolve(controller), controller,
276: UiUtils.PrintPart.NAME);
277: setName(org.openide.util.NbBundle
278: .getMessage(PullUpPanel.class,
279: "LBL_PullUpHeader",
280: new Object[] { name }) /* NOI18N */); // NOI18N
281: }
282: }, true);
283: } catch (IOException ioe) {
284: throw (RuntimeException) new RuntimeException()
285: .initCause(ioe);
286: }
287: }
288:
289: // --- GETTERS FOR REFACTORING PARAMETERS ----------------------------------
290:
291: /** Getter used by the refactoring UI to get value
292: * of target type.
293: * @return Target type.
294: */
295: public MemberInfo<ElementHandle> getTargetType() {
296: return targetType;
297: }
298:
299: /** Getter used by the refactoring UI to get members to be pulled up.
300: * @return Descriptors of members to be pulled up.
301: */
302: public MemberInfo[] getMembers() {
303: final List list = new ArrayList();
304: final TreePathHandle handle = refactoring.getSourceType();
305: JavaSource source = JavaSource.forFileObject(handle
306: .getFileObject());
307: try {
308: source.runUserActionTask(
309: new CancellableTask<CompilationController>() {
310: public void cancel() {
311: }
312:
313: public void run(CompilationController parameter)
314: throws Exception {
315:
316: // remeber if the target type is an interface (will be used in the loop)
317: boolean targetIsInterface = targetType
318: .getElementHandle().getKind()
319: .isInterface();
320: // go through all rows of a table and collect selected members
321: for (int i = 0; i < members.length; i++) {
322: // if the current row is selected, create MemberInfo for it and
323: // add it to the list of selected members
324: if (members[i][0].equals(Boolean.TRUE)) {
325: MemberInfo<ElementHandle> element = (MemberInfo<ElementHandle>) members[i][1];
326: // for methods the makeAbstract is always set to true if the
327: // target type is an interface
328: element
329: .setMakeAbstract(((element
330: .getElementHandle()
331: .getKind() == ElementKind.METHOD) && targetIsInterface)
332: || ((Boolean) members[i][2] == null ? Boolean.FALSE
333: : (Boolean) members[i][2]));
334: list.add(element);
335: }
336: }
337: }
338: }, true);
339: } catch (IOException ioe) {
340: throw (RuntimeException) new RuntimeException()
341: .initCause(ioe);
342: }
343: // return the array of selected members
344: return (MemberInfo[]) list.toArray(new MemberInfo[list.size()]);
345: }
346:
347: // --- GENERATED CODE ------------------------------------------------------
348:
349: /** This method is called from within the constructor to
350: * initialize the form.
351: * WARNING: Do NOT modify this code. The content of this method is
352: * always regenerated by the Form Editor.
353: */
354: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
355: private void initComponents() {
356:
357: super typePanel = new javax.swing.JPanel();
358: super typeCombo = new javax.swing.JComboBox();
359: super typeLabel = new javax.swing.JLabel();
360: chooseLabel = new javax.swing.JLabel();
361: scrollPane = new javax.swing.JScrollPane();
362: membersTable = new javax.swing.JTable();
363:
364: setBorder(javax.swing.BorderFactory.createEmptyBorder(12, 12,
365: 11, 11));
366: setLayout(new java.awt.BorderLayout());
367:
368: super typePanel.setBorder(javax.swing.BorderFactory
369: .createEmptyBorder(1, 1, 1, 1));
370: super typePanel.setLayout(new java.awt.BorderLayout(12, 0));
371: super typePanel
372: .add(super typeCombo, java.awt.BorderLayout.CENTER);
373:
374: super typeLabel.setLabelFor(super typeCombo);
375: java.util.ResourceBundle bundle = java.util.ResourceBundle
376: .getBundle("org/netbeans/modules/refactoring/java/ui/Bundle"); // NOI18N
377: org.openide.awt.Mnemonics.setLocalizedText(super typeLabel,
378: bundle.getString("LBL_PullUp_Supertype")); // NOI18N
379: super typePanel.add(super typeLabel, java.awt.BorderLayout.WEST);
380: super typeLabel.getAccessibleContext().setAccessibleName(
381: org.openide.util.NbBundle.getMessage(PullUpPanel.class,
382: "ACSD_DestinationSupertypeName")); // NOI18N
383: super typeLabel.getAccessibleContext().setAccessibleDescription(
384: org.openide.util.NbBundle.getMessage(PullUpPanel.class,
385: "ACSD_DestinationSupertypeDescription")); // NOI18N
386:
387: chooseLabel.setLabelFor(membersTable);
388: org.openide.awt.Mnemonics.setLocalizedText(chooseLabel,
389: org.openide.util.NbBundle.getMessage(PullUpPanel.class,
390: "LBL_PullUpLabel")); // NOI18N
391: chooseLabel.setBorder(javax.swing.BorderFactory
392: .createEmptyBorder(6, 0, 0, 0));
393: super typePanel.add(chooseLabel, java.awt.BorderLayout.SOUTH);
394:
395: add(super typePanel, java.awt.BorderLayout.NORTH);
396:
397: membersTable.setModel(tableModel);
398: membersTable
399: .setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN);
400: scrollPane.setViewportView(membersTable);
401: membersTable.getAccessibleContext().setAccessibleName(
402: org.openide.util.NbBundle.getMessage(PullUpPanel.class,
403: "ACSD_MembersToPullUp")); // NOI18N
404: membersTable.getAccessibleContext().setAccessibleDescription(
405: org.openide.util.NbBundle.getMessage(PullUpPanel.class,
406: "ACSD_MembersToPullUpDescription")); // NOI18N
407:
408: add(scrollPane, java.awt.BorderLayout.CENTER);
409: }// </editor-fold>//GEN-END:initComponents
410:
411: // Variables declaration - do not modify//GEN-BEGIN:variables
412: private javax.swing.JLabel chooseLabel;
413: private javax.swing.JTable membersTable;
414: private javax.swing.JScrollPane scrollPane;
415: private javax.swing.JComboBox super typeCombo;
416: private javax.swing.JLabel super typeLabel;
417: private javax.swing.JPanel super typePanel;
418:
419: // End of variables declaration//GEN-END:variables
420:
421: public Component getComponent() {
422: return this ;
423: }
424:
425: // --- MODELS --------------------------------------------------------------
426:
427: /** Model for the members table.
428: */
429: private class TableModel extends AbstractTableModel {
430: public int getColumnCount() {
431: return COLUMN_NAMES.length;
432: }
433:
434: public String getColumnName(int column) {
435: return UIUtilities.getColumnName(NbBundle.getMessage(
436: PullUpPanel.class, COLUMN_NAMES[column]));
437: }
438:
439: public Class getColumnClass(int columnIndex) {
440: return COLUMN_CLASSES[columnIndex];
441: }
442:
443: public int getRowCount() {
444: return members.length;
445: }
446:
447: public Object getValueAt(int rowIndex, int columnIndex) {
448: return members[rowIndex][columnIndex];
449: }
450:
451: public void setValueAt(Object value, int rowIndex,
452: int columnIndex) {
453: members[rowIndex][columnIndex] = value;
454: fireTableDataChanged();
455: }
456:
457: public boolean isCellEditable(int rowIndex, int columnIndex) {
458: if (columnIndex == 2) {
459: // column 2 is editable only in case of non-static methods
460: // if the target type is not an interface
461: // if the method is abstract
462: if (members[rowIndex][2] == null) {
463: return false;
464: }
465: Object element = members[rowIndex][1];
466: return !sourceKind.isInterface()
467: && !(((MemberInfo) element).getModifiers()
468: .contains(Modifier.STATIC))
469: && !(((MemberInfo) element).getModifiers()
470: .contains(Modifier.ABSTRACT));
471: } else {
472: // column 0 is always editable, column 1 is never editable
473: return columnIndex == 0;
474: }
475: }
476:
477: /** Method called by target type combo box model when the selection changes
478: * (i.e. when the selected target type changes).
479: * Updates table rows based on the change (all members from the source type
480: * up to the direct subtypes of the target type need to be displayed).
481: * @param classes Classes the members of which should be displayed (these are all classes
482: * that are supertypes of source type (including the source type) and at the same time subtypes
483: * of the target type (excluding the target type).
484: */
485: void update(final MemberInfo<ElementHandle>[] classes) {
486: JavaSource source = JavaSource.forFileObject(refactoring
487: .getSourceType().getFileObject());
488: try {
489: source.runUserActionTask(
490: new CancellableTask<CompilationController>() {
491: public void cancel() {
492: }
493:
494: public void run(CompilationController info) {
495: try {
496: info
497: .toPhase(JavaSource.Phase.RESOLVED);
498: } catch (IOException ioe) {
499: throw (RuntimeException) new RuntimeException()
500: .initCause(ioe);
501: }
502: Map map = new HashMap();
503: // go through the passed classes, collect all members from them and
504: // create a map mapping a member to an array of java.lang.Object representing
505: // a future table row corresponding to that member
506: for (int i = 0; i < classes.length; i++) {
507: // collect interface names
508: for (TypeMirror tm : ((TypeElement) (classes[i]
509: .getElementHandle()
510: .resolve(info)))
511: .getInterfaces()) {
512: MemberInfo ifcName = MemberInfo
513: .create(
514: RetoucheUtils
515: .typeToElement(
516: tm,
517: info),
518: info,
519: MemberInfo.Group.IMPLEMENTS);
520: map.put(ifcName, new Object[] {
521: Boolean.FALSE, ifcName,
522: null });
523: }
524: // collect fields, methods and inner classes
525: List<? extends Element> features = classes[i]
526: .getElementHandle()
527: .resolve(info)
528: .getEnclosedElements();
529: int j = 0;
530: for (Element e : features) {
531: switch (e.getKind()) {
532: case CONSTRUCTOR:
533: case STATIC_INIT:
534: case INSTANCE_INIT:
535: continue;
536: default: {
537: MemberInfo mi = MemberInfo
538: .create(e, info);
539: map
540: .put(
541: mi,
542: new Object[] {
543: Boolean.FALSE,
544: mi,
545: (e
546: .getKind() == ElementKind.METHOD) ? Boolean.FALSE
547: : null });
548: }
549: }
550: }
551: }
552: // select some members if applicable
553: if (selectedMembers != null) {
554: // if the collection of pre-selected members is not null
555: // this is the first creation of the table data ->
556: // -> select the members from the selectedMembers collection
557: for (Iterator it = selectedMembers
558: .iterator(); it.hasNext();) {
559: Object[] value = (Object[]) map
560: .get(it.next());
561: if (value != null) {
562: value[0] = Boolean.TRUE;
563: }
564: }
565: selectedMembers = null;
566: } else {
567: // this is not the first update of the table content ->
568: // -> select elements that were selected before the update
569: // (if they will still be present in the table)
570: for (int i = 0; i < members.length; i++) {
571: Object[] value = (Object[]) map
572: .get(members[i][1]);
573: if (value != null) {
574: map.put(value[1],
575: members[i]);
576: }
577: }
578: }
579:
580: // TODO: remove overrides, since they cannot be pulled up
581: // Did not work even in 5.5
582:
583: // the members are collected
584: // now, create a tree map (to sort them) and create the table data
585: TreeMap treeMap = new TreeMap(
586: new Comparator() {
587: public int compare(
588: Object o1, Object o2) {
589: return ((MemberInfo) o1)
590: .getHtmlText()
591: .compareTo(
592: ((MemberInfo) o2)
593: .getHtmlText());
594:
595: //TODO: sorting
596: // NamedElement ne1 = (NamedElement) o1, ne2 = (NamedElement) o2;
597: // // elements are sorted primarily by their class name
598: // int result = ne1.getClass().getName().compareTo(ne2.getClass().getName());
599: // if (result == 0) {
600: // // then by their display text
601: // result = UIUtilities.getDisplayText(ne1).compareTo(UIUtilities.getDisplayText(ne2));
602: // }
603: // if (result == 0) {
604: // // then the mofid is compared (to not take two non-identical
605: // // elements as equals)
606: // result = ne1.refMofId().compareTo(ne2.refMofId());
607: // }
608: // return result;
609: }
610: });
611: treeMap.putAll(map);
612: members = new Object[treeMap.size()][];
613: int i = 0;
614: for (Iterator it = treeMap.values()
615: .iterator(); it.hasNext(); i++) {
616: members[i] = (Object[]) it.next();
617: }
618: }
619: }, true);
620: } catch (IOException ioe) {
621: throw (RuntimeException) new RuntimeException()
622: .initCause(ioe);
623: }
624: // fire event to repaint the table
625: this .fireTableDataChanged();
626: }
627: }
628:
629: /** Model for combo box for choosing target type.
630: */
631: private class ComboModel extends AbstractListModel implements
632: ComboBoxModel {
633: private final MemberInfo<ElementHandle>[] super types;
634:
635: /** Creates the combo model.
636: * @param supertypes List of applicable supertypes that may be chosen to be
637: * target types.
638: */
639: ComboModel(MemberInfo[] super types) {
640: this .super types = super types;
641: if (super types.length > 0) {
642: setSelectedItem(super types[0]);
643: }
644: }
645:
646: /** Gets invoked when the selection changes. Computes the classes the members
647: * of which can be pulled up and calls table model's update() method to
648: * update the table content with changed set of members.
649: * @param anItem Class selected to be the target.
650: */
651: public void setSelectedItem(final Object anItem) {
652: JavaSource source = JavaSource.forFileObject(refactoring
653: .getSourceType().getFileObject());
654: try {
655: source.runUserActionTask(
656: new CancellableTask<CompilationController>() {
657: public void cancel() {
658: }
659:
660: public void run(CompilationController info) {
661: try {
662: info
663: .toPhase(JavaSource.Phase.RESOLVED);
664: } catch (IOException ioe) {
665: throw (RuntimeException) new RuntimeException()
666: .initCause(ioe);
667: }
668: if (targetType != anItem) {
669: targetType = ((MemberInfo) anItem);
670: // must fire this (according to the ComboBoxModel interface contract)
671: fireContentsChanged(this , -1, -1);
672: // compute the classes (they must be superclasses of source type - including it -
673: // and subtypes of target type)
674: List classes = new ArrayList();
675: // add source type (it is always included)
676: Element e = refactoring
677: .getSourceType()
678: .resolveElement(info);
679: MemberInfo m = MemberInfo.create(e,
680: info);
681: classes.add(m);
682: for (int i = 0; i < super types.length; i++) {
683: TypeMirror targetTM = targetType
684: .getElementHandle()
685: .resolve(info).asType();
686: TypeMirror super TM = super types[i]
687: .getElementHandle()
688: .resolve(info).asType();
689: // add the other subtypes of the target type
690: if (info.getTypes().isSubtype(
691: super TM, targetTM)
692: && !info
693: .getTypes()
694: .isSameType(
695: super TM,
696: targetTM)) {
697: classes.add(super types[i]);
698: }
699: }
700: // update the table
701: tableModel
702: .update((MemberInfo[]) classes
703: .toArray(new MemberInfo[classes
704: .size()]));
705: }
706: }
707: }, true);
708: } catch (IOException ioe) {
709: throw (RuntimeException) new RuntimeException()
710: .initCause(ioe);
711: }
712: }
713:
714: public Object getSelectedItem() {
715: return targetType;
716: }
717:
718: public Object getElementAt(int index) {
719: return super types[index];
720: }
721:
722: public int getSize() {
723: return supertypes.length;
724: }
725: }
726: }
|