| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.ui.refactoring; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Item; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.TableColumn; |
| |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.jface.viewers.ArrayContentProvider; |
| import org.eclipse.jface.viewers.CellEditor; |
| import org.eclipse.jface.viewers.CheckStateChangedEvent; |
| import org.eclipse.jface.viewers.ColumnWeightData; |
| import org.eclipse.jface.viewers.ComboBoxCellEditor; |
| import org.eclipse.jface.viewers.DoubleClickEvent; |
| import org.eclipse.jface.viewers.ICellModifier; |
| import org.eclipse.jface.viewers.ICheckStateListener; |
| import org.eclipse.jface.viewers.IDoubleClickListener; |
| import org.eclipse.jface.viewers.ILabelProvider; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.ITableLabelProvider; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.TableLayout; |
| |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.help.WorkbenchHelp; |
| |
| import org.eclipse.jdt.core.JavaModelException; |
| |
| import org.eclipse.jdt.ui.JavaElementLabelProvider; |
| |
| import org.eclipse.jdt.internal.ui.IJavaHelpContextIds; |
| import org.eclipse.jdt.internal.ui.util.ExceptionHandler; |
| import org.eclipse.jdt.internal.ui.util.SWTUtil; |
| import org.eclipse.jdt.internal.ui.util.TableLayoutComposite; |
| |
| import org.eclipse.jdt.internal.corext.Assert; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.PushDownRefactoring; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.PushDownRefactoring.MemberActionInfo; |
| |
| class PushDownInputPage extends UserInputWizardPage { |
| |
| private class PullUpCellModifier implements ICellModifier { |
| /* |
| * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object, java.lang.String) |
| */ |
| public Object getValue(Object element, String property) { |
| if (! ACTION_PROPERTY.equals(property)) |
| return null; |
| |
| MemberActionInfo mac= (MemberActionInfo)element; |
| return new Integer(mac.getAction()); |
| } |
| /* |
| * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object, java.lang.String) |
| */ |
| public boolean canModify(Object element, String property) { |
| if (! ACTION_PROPERTY.equals(property)) |
| return false; |
| return ((MemberActionInfo)element).isEditable(); |
| } |
| /* |
| * @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object, java.lang.String, java.lang.Object) |
| */ |
| public void modify(Object element, String property, Object value) { |
| if (! ACTION_PROPERTY.equals(property)) |
| return; |
| |
| int action= ((Integer)value).intValue(); |
| MemberActionInfo mac; |
| if (element instanceof Item) { |
| mac= (MemberActionInfo)((Item)element).getData(); |
| } else |
| mac= (MemberActionInfo)element; |
| mac.setAction(action); |
| PushDownInputPage.this.updateUIElements(null); |
| } |
| } |
| |
| private static class MemberActionInfoLabelProvider extends LabelProvider implements ITableLabelProvider { |
| private final ILabelProvider fJavaElementLabelProvider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT | JavaElementLabelProvider.SHOW_SMALL_ICONS); |
| |
| /* |
| * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) |
| */ |
| public String getColumnText(Object element, int columnIndex) { |
| MemberActionInfo mac= (MemberActionInfo)element; |
| switch (columnIndex) { |
| case MEMBER_COLUMN : return fJavaElementLabelProvider.getText(mac.getMember()); |
| case ACTION_COLUMN : return getActionLabel(mac); |
| default : |
| Assert.isTrue(false); |
| return null; |
| } |
| } |
| |
| static String[] getAvailableActionLabels(MemberActionInfo mac){ |
| int[] actions= mac.getAvailableActions(); |
| String[] result= new String[actions.length]; |
| for(int i= 0; i < actions.length; i++){ |
| result[i]= getActionLabel(actions[i]); |
| } |
| return result; |
| } |
| |
| static String getActionLabel(MemberActionInfo mac) { |
| return getActionLabel(mac.getAction()); |
| } |
| |
| static String getActionLabel(int action) { |
| switch(action){ |
| case MemberActionInfo.NO_ACTION: return ""; //$NON-NLS-1$ |
| case MemberActionInfo.PUSH_ABSTRACT_ACTION: return RefactoringMessages.getString("PushDownInputPage.leave_abstract"); //$NON-NLS-1$ |
| case MemberActionInfo.PUSH_DOWN_ACTION: return RefactoringMessages.getString("PushDownInputPage.push_down"); //$NON-NLS-1$ |
| default: |
| Assert.isTrue(false); |
| return null; |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) |
| */ |
| public Image getColumnImage(Object element, int columnIndex) { |
| MemberActionInfo mac= (MemberActionInfo)element; |
| switch (columnIndex) { |
| case MEMBER_COLUMN: return fJavaElementLabelProvider.getImage(mac.getMember()); |
| case ACTION_COLUMN: return null; |
| default : |
| Assert.isTrue(false); |
| return null; |
| } |
| } |
| /* |
| * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() |
| */ |
| public void dispose() { |
| super.dispose(); |
| fJavaElementLabelProvider.dispose(); |
| } |
| } |
| |
| private static final int MEMBER_COLUMN= 0; |
| private static final int ACTION_COLUMN= 1; |
| public static final String PAGE_NAME= "PushDownInputPage"; //$NON-NLS-1$ |
| private final static String ACTION_PROPERTY= "action"; //$NON-NLS-1$ |
| private final static String MEMBER_PROPERTY= "member"; //$NON-NLS-1$ |
| |
| private static final int ROW_COUNT= 10; |
| |
| private Button fEditButton; |
| private PullPushCheckboxTableViewer fTableViewer; |
| private Label fStatusLine; |
| |
| public PushDownInputPage() { |
| super(PAGE_NAME, true); |
| } |
| |
| /* |
| * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) |
| */ |
| public void createControl(Composite parent) { |
| Composite composite= new Composite(parent, SWT.NONE); |
| GridLayout gl= new GridLayout(); |
| composite.setLayout(gl); |
| |
| createMemberTableLabel(composite); |
| createMemberTableComposite(composite); |
| createStatusLine(composite); |
| |
| setControl(composite); |
| Dialog.applyDialogFont(composite); |
| WorkbenchHelp.setHelp(getControl(), IJavaHelpContextIds.PUSH_DOWN_WIZARD_PAGE); |
| } |
| |
| private void createStatusLine(Composite composite) { |
| fStatusLine= new Label(composite, SWT.NONE); |
| GridData gd= new GridData(); |
| gd.horizontalSpan= 2; |
| updateStatusLine(); |
| fStatusLine.setLayoutData(gd); |
| } |
| |
| private void createMemberTableLabel(Composite parent) { |
| Label label= new Label(parent, SWT.NONE) ; |
| label.setText(RefactoringMessages.getString("PushDownInputPage.Specify_actions")); //$NON-NLS-1$ |
| GridData gd0= new GridData(); |
| label.setLayoutData(gd0); |
| } |
| |
| private void createMemberTableComposite(Composite parent) { |
| Composite composite= new Composite(parent, SWT.NONE); |
| GridData gd= new GridData(GridData.FILL_HORIZONTAL); |
| composite.setLayoutData(gd); |
| GridLayout gl= new GridLayout(); |
| gl.numColumns= 2; |
| gl.marginWidth= 0; |
| gl.marginHeight= 0; |
| composite.setLayout(gl); |
| |
| createMemberTable(composite); |
| createButtonComposite(composite); |
| } |
| |
| private void createMemberTable(Composite parent) { |
| TableLayoutComposite layouter= new TableLayoutComposite(parent, SWT.NONE); |
| layouter.addColumnData(new ColumnWeightData(60, true)); |
| layouter.addColumnData(new ColumnWeightData(40, true)); |
| |
| final Table table= new Table(layouter, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.CHECK); |
| table.setHeaderVisible(true); |
| table.setLinesVisible(true); |
| |
| GridData gd= new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING); |
| gd.heightHint= table.getHeaderHeight() + (table.getGridLineWidth() + table.getItemHeight()) * ROW_COUNT; |
| layouter.setLayoutData(gd); |
| |
| |
| TableLayout tableLayout= new TableLayout(); |
| table.setLayout(tableLayout); |
| |
| TableColumn column0= new TableColumn(table, SWT.NONE); |
| column0.setText(RefactoringMessages.getString("PushDownInputPage.Member")); //$NON-NLS-1$ |
| |
| TableColumn column1= new TableColumn(table, SWT.NONE); |
| column1.setText(RefactoringMessages.getString("PushDownInputPage.Action")); //$NON-NLS-1$ |
| |
| fTableViewer= new PullPushCheckboxTableViewer(table); |
| fTableViewer.setUseHashlookup(true); |
| fTableViewer.setContentProvider(new ArrayContentProvider()); |
| fTableViewer.setLabelProvider(new MemberActionInfoLabelProvider()); |
| fTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){ |
| public void selectionChanged(SelectionChangedEvent event) { |
| PushDownInputPage.this.updateButtonEnablementState((IStructuredSelection)event.getSelection()); |
| } |
| }); |
| fTableViewer.addCheckStateListener(new ICheckStateListener(){ |
| public void checkStateChanged(CheckStateChangedEvent event) { |
| boolean checked= event.getChecked(); |
| MemberActionInfo info= (MemberActionInfo)event.getElement(); |
| if (checked) |
| info.setAction(MemberActionInfo.PUSH_DOWN_ACTION); |
| else |
| info.setAction(MemberActionInfo.NO_ACTION); |
| updateUIElements(null); |
| } |
| }); |
| fTableViewer.addDoubleClickListener(new IDoubleClickListener(){ |
| public void doubleClick(DoubleClickEvent event) { |
| PushDownInputPage.this.editSelectedMembers(); |
| } |
| }); |
| |
| |
| fTableViewer.setInput(getPushDownRefactoring().getMemberActionInfos()); |
| updateUIElements(null); |
| setupCellEditors(table); |
| } |
| |
| private MemberActionInfo[] getActiveInfos() { |
| MemberActionInfo[] infos= getPushDownRefactoring().getMemberActionInfos(); |
| List result= new ArrayList(infos.length); |
| for (int i= 0; i < infos.length; i++) { |
| PushDownRefactoring.MemberActionInfo info= infos[i]; |
| if (info.isActive()) |
| result.add(info); |
| } |
| return (MemberActionInfo[]) result.toArray(new MemberActionInfo[result.size()]); |
| } |
| |
| private void setupCellEditors(final Table table) { |
| final ComboBoxCellEditor comboBoxCellEditor= new ComboBoxCellEditor(); |
| comboBoxCellEditor.setStyle(SWT.READ_ONLY); |
| fTableViewer.setCellEditors(new CellEditor [] {null, comboBoxCellEditor}); |
| fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| public void selectionChanged(SelectionChangedEvent event) { |
| if (comboBoxCellEditor.getControl() == null & ! table.isDisposed()) |
| comboBoxCellEditor.create(table); |
| Assert.isTrue(event.getSelection() instanceof IStructuredSelection); |
| IStructuredSelection ss= (IStructuredSelection)event.getSelection(); |
| if (ss.size() != 1) |
| return; |
| MemberActionInfo mac= (MemberActionInfo)ss.getFirstElement(); |
| comboBoxCellEditor.setItems(MemberActionInfoLabelProvider.getAvailableActionLabels(mac)); |
| comboBoxCellEditor.setValue(new Integer(mac.getAction())); |
| } |
| }); |
| |
| ICellModifier cellModifier = new PullUpCellModifier(); |
| fTableViewer.setCellModifier(cellModifier); |
| fTableViewer.setColumnProperties(new String[] {MEMBER_PROPERTY, ACTION_PROPERTY}); |
| } |
| |
| private void createButtonComposite(Composite parent) { |
| Composite composite= new Composite(parent, SWT.NONE); |
| composite.setLayoutData(new GridData(GridData.FILL_VERTICAL)); |
| GridLayout gl= new GridLayout(); |
| gl.marginHeight= 0; |
| gl.marginWidth= 0; |
| composite.setLayout(gl); |
| |
| fEditButton= new Button(composite, SWT.PUSH); |
| fEditButton.setText(RefactoringMessages.getString("PushDownInputPage.Edit")); //$NON-NLS-1$ |
| fEditButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| fEditButton.setEnabled(false); |
| SWTUtil.setButtonDimensionHint(fEditButton); |
| fEditButton.addSelectionListener(new SelectionAdapter(){ |
| public void widgetSelected(SelectionEvent event) { |
| PushDownInputPage.this.editSelectedMembers(); |
| } |
| }); |
| |
| Button addButton= new Button(composite, SWT.PUSH); |
| addButton.setText(RefactoringMessages.getString("PushDownInputPage.Add_Required")); //$NON-NLS-1$ |
| addButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| SWTUtil.setButtonDimensionHint(addButton); |
| addButton.addSelectionListener(new SelectionAdapter(){ |
| public void widgetSelected(SelectionEvent event) { |
| PushDownInputPage.this.markAdditionalRequiredMembersAsMembersToPushDown(); |
| } |
| }); |
| } |
| |
| public void markAdditionalRequiredMembersAsMembersToPushDown() { |
| try { |
| PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(false, false, new IRunnableWithProgress() { |
| public void run(IProgressMonitor pm) throws InvocationTargetException { |
| try { |
| getPushDownRefactoring().computeAdditionalRequiredMembersToPushDown(pm); |
| updateUIElements(null); |
| } catch (JavaModelException e) { |
| throw new InvocationTargetException(e); |
| } finally { |
| pm.done(); |
| } |
| } |
| }); |
| } catch(InvocationTargetException e) { |
| ExceptionHandler.handle(e, getShell(), RefactoringMessages.getString("PushDownInputPage.Push_Down"), RefactoringMessages.getString("PushDownInputPage.Internal_Error")); //$NON-NLS-1$ //$NON-NLS-2$ |
| } catch(InterruptedException e) { |
| Assert.isTrue(false);//not cancellable |
| } |
| } |
| |
| private void editSelectedMembers() { |
| if (! fEditButton.isEnabled()) |
| return; |
| ISelection preserved= fTableViewer.getSelection(); |
| try{ |
| String shellTitle= RefactoringMessages.getString("PushDownInputPage.Edit_members"); //$NON-NLS-1$ |
| String labelText= RefactoringMessages.getString("PushDownInputPage.Mark_selected_members"); //$NON-NLS-1$ |
| Map stringMapping= createStringMappingForSelectedElements(); |
| String[] keys= (String[]) stringMapping.keySet().toArray(new String[stringMapping.keySet().size()]); |
| Arrays.sort(keys); |
| int initialSelectionIndex= getInitialSelectionIndexForEditDialog(stringMapping, keys); |
| |
| ComboSelectionDialog dialog= new ComboSelectionDialog(getShell(), shellTitle, labelText, keys, initialSelectionIndex); |
| dialog.setBlockOnOpen(true); |
| if (dialog.open() == Dialog.CANCEL) |
| return; |
| int action= ((Integer)stringMapping.get(dialog.getSelectedString())).intValue(); |
| setInfoAction(getSelectedMemberActionInfos(), action); |
| } finally{ |
| updateUIElements(preserved); |
| } |
| } |
| |
| private int getInitialSelectionIndexForEditDialog(Map stringMapping, String[] keys) { |
| int commonActionCode= getCommonActionCodeForSelectedInfos(); |
| if (commonActionCode == -1) |
| return 0; |
| for (Iterator iter= stringMapping.keySet().iterator(); iter.hasNext();) { |
| String key= (String) iter.next(); |
| int action= ((Integer)stringMapping.get(key)).intValue(); |
| if (commonActionCode == action){ |
| for (int i= 0; i < keys.length; i++) { |
| if (key.equals(keys[i])) |
| return i; |
| } |
| Assert.isTrue(false);//there's no way |
| } |
| } |
| return 0; |
| } |
| |
| private int getCommonActionCodeForSelectedInfos() { |
| MemberActionInfo[] infos= getSelectedMemberActionInfos(); |
| if (infos.length == 0) |
| return -1; |
| |
| int code= infos[0].getAction(); |
| for (int i= 0; i < infos.length; i++) { |
| if (code != infos[i].getAction()) |
| return -1; |
| } |
| return code; |
| } |
| |
| //String -> Integer |
| private Map createStringMappingForSelectedElements() { |
| Map result= new HashMap(); |
| addToStringMapping(result, MemberActionInfo.PUSH_DOWN_ACTION); |
| addToStringMapping(result, MemberActionInfo.PUSH_ABSTRACT_ACTION); |
| return result; |
| } |
| private void addToStringMapping(Map result, int action) { |
| result.put(MemberActionInfoLabelProvider.getActionLabel(action), new Integer(action)); |
| } |
| |
| private static void setInfoAction(MemberActionInfo[] infos, int action) { |
| for (int i = 0; i < infos.length; i++) { |
| infos[i].setAction(action); |
| } |
| } |
| |
| private MemberActionInfo[] getSelectedMemberActionInfos() { |
| Assert.isTrue(fTableViewer.getSelection() instanceof IStructuredSelection); |
| List result= getTableSelection().toList(); |
| return (MemberActionInfo[]) result.toArray(new MemberActionInfo[result.size()]); |
| } |
| |
| private IStructuredSelection getTableSelection() { |
| return (IStructuredSelection)fTableViewer.getSelection(); |
| } |
| |
| private void updateUIElements(ISelection preserved) { |
| fTableViewer.refresh(); |
| if (preserved != null){ |
| fTableViewer.getControl().setFocus(); |
| fTableViewer.setSelection(preserved); |
| } |
| checkPageCompletionStatus(); |
| updateButtonEnablementState(getTableSelection()); |
| updateStatusLine(); |
| } |
| |
| private void updateStatusLine(){ |
| if (fStatusLine == null) |
| return; |
| int selected= fTableViewer.getCheckedElements().length; |
| String[] keys= {String.valueOf(selected)}; |
| String msg= RefactoringMessages.getFormattedString("PushDownInputPage.status_line", keys); //$NON-NLS-1$ |
| fStatusLine.setText(msg); |
| } |
| |
| private void checkPageCompletionStatus() { |
| if (areAllElementsMarkedAsNoAction()){ |
| setErrorMessage(RefactoringMessages.getString("PushDownInputPage.Select_members_to_push_down")); //$NON-NLS-1$ |
| setPageComplete(false); |
| } else { |
| setErrorMessage(null); |
| setPageComplete(true); |
| } |
| } |
| |
| private boolean areAllElementsMarkedAsNoAction() { |
| return countInfosForAction(MemberActionInfo.NO_ACTION) == getTableInputAsMemberActionInfoArray().length; |
| } |
| |
| private int countInfosForAction(int action) { |
| MemberActionInfo[] macs= getTableInputAsMemberActionInfoArray(); |
| int count= 0; |
| for (int i= 0; i < macs.length; i++) { |
| MemberActionInfo info= macs[i]; |
| if (info.getAction() == action) |
| count++; |
| } |
| return count; |
| } |
| |
| private MemberActionInfo[] getTableInputAsMemberActionInfoArray() { |
| return (MemberActionInfo[])fTableViewer.getInput(); |
| } |
| |
| private void updateButtonEnablementState(IStructuredSelection tableSelection) { |
| if (tableSelection == null || fEditButton == null) |
| return; |
| |
| fEditButton.setEnabled(enableEditButton(tableSelection)); |
| } |
| private boolean enableEditButton(IStructuredSelection tableSelection) { |
| if (tableSelection.isEmpty() || tableSelection.size() == 0) |
| return false; |
| return tableSelection.size() == countEditableInfos(getSelectedMemberActionInfos()); |
| } |
| |
| private static int countEditableInfos(MemberActionInfo[] memberActionInfos) { |
| int result= 0; |
| for (int i= 0; i < memberActionInfos.length; i++) { |
| if (memberActionInfos[i].isEditable()) |
| result++; |
| } |
| return result; |
| } |
| |
| private PushDownRefactoring getPushDownRefactoring(){ |
| return (PushDownRefactoring)getRefactoring(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean) |
| */ |
| public void setVisible(boolean visible) { |
| super.setVisible(visible); |
| if (visible){ |
| fTableViewer.setSelection(new StructuredSelection(getActiveInfos()), true); |
| fTableViewer.getControl().setFocus(); |
| } |
| } |
| } |