1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.editors.layout.refactoring; 18 19 import static com.android.SdkConstants.REQUEST_FOCUS; 20 import static com.android.SdkConstants.VIEW_FRAGMENT; 21 import static com.android.SdkConstants.VIEW_INCLUDE; 22 23 import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; 24 import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; 25 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CustomViewFinder; 26 import com.android.ide.eclipse.adt.internal.editors.layout.gre.ViewMetadataRepository; 27 import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; 28 import com.android.ide.eclipse.adt.internal.sdk.Sdk; 29 import com.android.sdklib.IAndroidTarget; 30 import com.android.utils.Pair; 31 32 import org.eclipse.core.resources.IProject; 33 import org.eclipse.swt.SWT; 34 import org.eclipse.swt.layout.GridData; 35 import org.eclipse.swt.layout.GridLayout; 36 import org.eclipse.swt.widgets.Combo; 37 import org.eclipse.swt.widgets.Composite; 38 import org.eclipse.swt.widgets.Label; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 43 class ChangeViewWizard extends VisualRefactoringWizard { 44 private static final String SEPARATOR_LABEL = 45 "----------------------------------------"; //$NON-NLS-1$ 46 47 public ChangeViewWizard(ChangeViewRefactoring ref, LayoutEditorDelegate editor) { 48 super(ref, editor); 49 setDefaultPageTitle("Change Widget Type"); 50 } 51 52 @Override 53 protected void addUserInputPages() { 54 ChangeViewRefactoring ref = (ChangeViewRefactoring) getRefactoring(); 55 List<String> oldTypes = ref.getOldTypes(); 56 String oldType = null; 57 for (String type : oldTypes) { 58 if (oldType == null) { 59 oldType = type; 60 } else if (!oldType.equals(type)) { 61 // If the types differ, don't offer related categories 62 oldType = null; 63 break; 64 } 65 } 66 addPage(new InputPage(mDelegate.getEditor().getProject(), oldType)); 67 } 68 69 /** Wizard page which inputs parameters for the {@link ChangeViewRefactoring} operation */ 70 private static class InputPage extends VisualRefactoringInputPage { 71 private final IProject mProject; 72 private Combo mTypeCombo; 73 private final String mOldType; 74 private List<String> mClassNames; 75 76 public InputPage(IProject project, String oldType) { 77 super("ChangeViewInputPage"); //$NON-NLS-1$ 78 mProject = project; 79 mOldType = oldType; 80 } 81 82 @Override 83 public void createControl(Composite parent) { 84 Composite composite = new Composite(parent, SWT.NONE); 85 composite.setLayout(new GridLayout(2, false)); 86 87 Label typeLabel = new Label(composite, SWT.NONE); 88 typeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); 89 typeLabel.setText("New Widget Type:"); 90 91 mTypeCombo = new Combo(composite, SWT.READ_ONLY); 92 mTypeCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); 93 mTypeCombo.addSelectionListener(mSelectionValidateListener); 94 95 mClassNames = getWidgetTypes(mOldType, mTypeCombo); 96 mTypeCombo.select(0); 97 98 setControl(composite); 99 validatePage(); 100 101 mTypeCombo.setFocus(); 102 } 103 104 private List<String> getWidgetTypes(String oldType, Combo combo) { 105 List<String> classNames = new ArrayList<String>(); 106 107 // Populate type combo 108 Sdk currentSdk = Sdk.getCurrent(); 109 if (currentSdk != null) { 110 IAndroidTarget target = currentSdk.getTarget(mProject); 111 if (target != null) { 112 // Try to pick "related" widgets to the one you have selected. 113 // For example, for an AnalogClock, display DigitalClock first. 114 // For a Text, offer EditText, AutoComplete, etc. 115 if (oldType != null) { 116 ViewMetadataRepository repository = ViewMetadataRepository.get(); 117 List<String> relatedTo = repository.getRelatedTo(oldType); 118 if (relatedTo.size() > 0) { 119 for (String className : relatedTo) { 120 String base = className.substring(className.lastIndexOf('.') + 1); 121 combo.add(base); 122 classNames.add(className); 123 } 124 combo.add(SEPARATOR_LABEL); 125 classNames.add(null); 126 } 127 } 128 129 Pair<List<String>,List<String>> result = 130 CustomViewFinder.findViews(mProject, false); 131 List<String> customViews = result.getFirst(); 132 List<String> thirdPartyViews = result.getSecond(); 133 if (customViews.size() > 0) { 134 for (String view : customViews) { 135 combo.add(view); 136 classNames.add(view); 137 } 138 combo.add(SEPARATOR_LABEL); 139 classNames.add(null); 140 } 141 142 if (thirdPartyViews.size() > 0) { 143 for (String view : thirdPartyViews) { 144 combo.add(view); 145 classNames.add(view); 146 } 147 combo.add(SEPARATOR_LABEL); 148 classNames.add(null); 149 } 150 151 AndroidTargetData targetData = currentSdk.getTargetData(target); 152 if (targetData != null) { 153 // Now add ALL known layout descriptors in case the user has 154 // a special case 155 List<ViewElementDescriptor> descriptors = 156 targetData.getLayoutDescriptors().getViewDescriptors(); 157 for (ViewElementDescriptor d : descriptors) { 158 String className = d.getFullClassName(); 159 if (className.equals(VIEW_INCLUDE) 160 || className.equals(VIEW_FRAGMENT) 161 || className.equals(REQUEST_FOCUS)) { 162 continue; 163 } 164 combo.add(d.getUiName()); 165 classNames.add(className); 166 167 } 168 } 169 } 170 } else { 171 combo.add("SDK not initialized"); 172 classNames.add(null); 173 } 174 175 return classNames; 176 } 177 178 @Override 179 protected boolean validatePage() { 180 boolean ok = true; 181 int selectionIndex = mTypeCombo.getSelectionIndex(); 182 String type = selectionIndex != -1 ? mClassNames.get(selectionIndex) : null; 183 if (type == null) { 184 setErrorMessage("Select a widget type to convert to"); 185 ok = false; // The user has chosen a separator 186 } else { 187 setErrorMessage(null); 188 } 189 190 // Record state 191 ChangeViewRefactoring refactoring = 192 (ChangeViewRefactoring) getRefactoring(); 193 refactoring.setType(type); 194 195 setPageComplete(ok); 196 return ok; 197 } 198 } 199 } 200