18dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye/* 28dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * Copyright (C) 2011 The Android Open Source Project 38dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * 48dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 58dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * you may not use this file except in compliance with the License. 68dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * You may obtain a copy of the License at 78dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * 88dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * http://www.eclipse.org/org/documents/epl-v10.php 98dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * 108dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * Unless required by applicable law or agreed to in writing, software 118dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * distributed under the License is distributed on an "AS IS" BASIS, 128dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * See the License for the specific language governing permissions and 148dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * limitations under the License. 158dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye */ 168dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyepackage com.android.ide.eclipse.adt.internal.editors.layout.refactoring; 178dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1812d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ANDROID_URI; 1912d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ANDROID_WIDGET_PREFIX; 2012d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_BASELINE_ALIGNED; 2112d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_LAYOUT_ALIGN_BASELINE; 2212d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_LAYOUT_BELOW; 2312d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_LAYOUT_HEIGHT; 2412d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_LAYOUT_RESOURCE_PREFIX; 2512d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_LAYOUT_TO_RIGHT_OF; 2612d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_LAYOUT_WIDTH; 2712d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.ATTR_ORIENTATION; 2812d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.EXT_XML; 2912d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.FQCN_GESTURE_OVERLAY_VIEW; 3012d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.FQCN_GRID_LAYOUT; 3112d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.FQCN_LINEAR_LAYOUT; 3212d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.FQCN_RELATIVE_LAYOUT; 3312d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.FQCN_TABLE_LAYOUT; 3412d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.GESTURE_OVERLAY_VIEW; 3512d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.LINEAR_LAYOUT; 3612d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.TABLE_ROW; 3712d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.VALUE_FALSE; 3812d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.VALUE_VERTICAL; 3912d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport static com.android.SdkConstants.VALUE_WRAP_CONTENT; 4012d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye 4112d4581faa6438941e65a9dc83213be34c6ca970Tor Norbyeimport com.android.SdkConstants; 427e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbyeimport com.android.annotations.NonNull; 430757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbyeimport com.android.annotations.VisibleForTesting; 444cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbyeimport com.android.ide.eclipse.adt.AdtPlugin; 458dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor; 46f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbyeimport com.android.ide.eclipse.adt.internal.editors.formatting.XmlFormatStyle; 47e50549f54810c29bffc681e39d33158ab2a8f26eRaphaelimport com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; 488dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor; 490757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo; 5078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; 510757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.gle2.LayoutCanvas; 520757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbyeimport com.android.ide.eclipse.adt.internal.editors.layout.gle2.ViewHierarchy; 53f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbyeimport com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 548dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 558dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.core.resources.IFile; 568dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.core.runtime.CoreException; 578dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.core.runtime.IProgressMonitor; 584cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbyeimport org.eclipse.core.runtime.IStatus; 598dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.core.runtime.OperationCanceledException; 608dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.jface.text.ITextSelection; 618dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.jface.viewers.ITreeSelection; 628dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.ltk.core.refactoring.Change; 638dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.ltk.core.refactoring.Refactoring; 648dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.ltk.core.refactoring.RefactoringStatus; 658dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.ltk.core.refactoring.TextFileChange; 664cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbyeimport org.eclipse.text.edits.MalformedTreeException; 678dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.text.edits.MultiTextEdit; 688dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.text.edits.ReplaceEdit; 699e6db060854d0e890190919a27a1846f50f69d1aTor Norbyeimport org.eclipse.text.edits.TextEdit; 709e6db060854d0e890190919a27a1846f50f69d1aTor Norbyeimport org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; 718dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; 729e6db060854d0e890190919a27a1846f50f69d1aTor Norbyeimport org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; 738dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.w3c.dom.Attr; 748dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.w3c.dom.Element; 7578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbyeimport org.w3c.dom.NamedNodeMap; 768dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.w3c.dom.Node; 778dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport org.w3c.dom.NodeList; 788dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 798dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport java.util.ArrayList; 808dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport java.util.HashSet; 818dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport java.util.List; 828dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport java.util.Map; 838dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyeimport java.util.Set; 848dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 858dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye/** 868dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * Converts the selected layout into a layout of a different type. 878dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye */ 888dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye@SuppressWarnings("restriction") // XML model 898dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbyepublic class ChangeLayoutRefactoring extends VisualRefactoring { 900757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye private static final String KEY_TYPE = "type"; //$NON-NLS-1$ 910757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye private static final String KEY_FLATTEN = "flatten"; //$NON-NLS-1$ 928dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 938dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye private String mTypeFqcn; 941294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye private String mInitializedAttributes; 950757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye private boolean mFlatten; 968dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 978dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye /** 988dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * This constructor is solely used by {@link Descriptor}, 998dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * to replay a previous refactoring. 1008dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * @param arguments argument map created by #createArgumentMap. 1018dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye */ 1028dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye ChangeLayoutRefactoring(Map<String, String> arguments) { 1038dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye super(arguments); 1048dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye mTypeFqcn = arguments.get(KEY_TYPE); 1050757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye mFlatten = Boolean.parseBoolean(arguments.get(KEY_FLATTEN)); 1060757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 1070757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 1080757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye @VisibleForTesting 109e50549f54810c29bffc681e39d33158ab2a8f26eRaphael ChangeLayoutRefactoring(List<Element> selectedElements, LayoutEditorDelegate delegate) { 110e50549f54810c29bffc681e39d33158ab2a8f26eRaphael super(selectedElements, delegate); 1118dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1128dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 113e50549f54810c29bffc681e39d33158ab2a8f26eRaphael public ChangeLayoutRefactoring( 114e50549f54810c29bffc681e39d33158ab2a8f26eRaphael IFile file, 115e50549f54810c29bffc681e39d33158ab2a8f26eRaphael LayoutEditorDelegate delegate, 116e50549f54810c29bffc681e39d33158ab2a8f26eRaphael ITextSelection selection, 1178dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye ITreeSelection treeSelection) { 118e50549f54810c29bffc681e39d33158ab2a8f26eRaphael super(file, delegate, selection, treeSelection); 1198dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1208dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1218dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye @Override 1228dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, 1238dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye OperationCanceledException { 1248dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye RefactoringStatus status = new RefactoringStatus(); 1258dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1268dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye try { 1278dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye pm.beginTask("Checking preconditions...", 2); 1288dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1298dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (mSelectionStart == -1 || mSelectionEnd == -1) { 1308dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye status.addFatalError("No selection to convert"); 1318dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return status; 1328dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1338dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1348dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (mElements.size() != 1) { 1358dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye status.addFatalError("Select precisely one layout to convert"); 1368dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return status; 1378dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1388dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1398dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye pm.worked(1); 1408dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return status; 1418dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1428dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } finally { 1438dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye pm.done(); 1448dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1458dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1468dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1478dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye @Override 1488dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye protected VisualRefactoringDescriptor createDescriptor() { 1498dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String comment = getName(); 1508dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return new Descriptor( 1518dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye mProject.getName(), //project 1528dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye comment, //description 1538dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye comment, //comment 1548dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye createArgumentMap()); 1558dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1568dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1578dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye @Override 1588dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye protected Map<String, String> createArgumentMap() { 1598dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Map<String, String> args = super.createArgumentMap(); 1608dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye args.put(KEY_TYPE, mTypeFqcn); 1610757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye args.put(KEY_FLATTEN, Boolean.toString(mFlatten)); 1628dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1638dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return args; 1648dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1658dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1668dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye @Override 1678dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye public String getName() { 1688dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return "Change Layout"; 1698dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1708dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1718dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye void setType(String typeFqcn) { 1728dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye mTypeFqcn = typeFqcn; 1738dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 1748dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 1751294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye void setInitializedAttributes(String initializedAttributes) { 1761294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye mInitializedAttributes = initializedAttributes; 1771294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye } 1781294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye 1790757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye void setFlatten(boolean flatten) { 1800757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye mFlatten = flatten; 1810757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 1820757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 1830757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye @Override 1840757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye protected List<Element> initElements() { 1850757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye List<Element> elements = super.initElements(); 1860757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 1870757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // Don't convert a root GestureOverlayView; convert its child. This looks for 1880757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // gesture overlays, and if found, it generates a new child list where the gesture 1890757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // overlay children are replaced by their first element children 1900757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye for (Element element : elements) { 1910757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye String tagName = element.getTagName(); 1920757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye if (tagName.equals(GESTURE_OVERLAY_VIEW) 1930757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye || tagName.equals(FQCN_GESTURE_OVERLAY_VIEW)) { 1940757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye List<Element> replacement = new ArrayList<Element>(elements.size()); 1950757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye for (Element e : elements) { 1960757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye tagName = e.getTagName(); 1970757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye if (tagName.equals(GESTURE_OVERLAY_VIEW) 1980757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye || tagName.equals(FQCN_GESTURE_OVERLAY_VIEW)) { 1990757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye NodeList children = e.getChildNodes(); 2000757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye Element first = null; 2010757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye for (int i = 0, n = children.getLength(); i < n; i++) { 2020757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye Node node = children.item(i); 2030757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye if (node.getNodeType() == Node.ELEMENT_NODE) { 2040757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye first = (Element) node; 2050757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye break; 2060757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2070757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2080757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye if (first != null) { 2090757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye e = first; 2100757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2110757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2120757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye replacement.add(e); 2130757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2140757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye return replacement; 2150757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2160757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2170757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 2180757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye return elements; 2190757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 2200757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 2218dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye @Override 2227e4b8e9d595e45baa9d87cdb8282f02759e73abcTor Norbye protected @NonNull List<Change> computeChanges(IProgressMonitor monitor) { 2238dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String name = getViewClass(mTypeFqcn); 2248dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 225e50549f54810c29bffc681e39d33158ab2a8f26eRaphael IFile file = mDelegate.getEditor().getInputFile(); 2268dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye List<Change> changes = new ArrayList<Change>(); 227f14914e59366377316c70f068347d3e34a1dea3cTor Norbye if (file == null) { 228f14914e59366377316c70f068347d3e34a1dea3cTor Norbye return changes; 229f14914e59366377316c70f068347d3e34a1dea3cTor Norbye } 2308dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye TextFileChange change = new TextFileChange(file.getName(), file); 2318dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye MultiTextEdit rootEdit = new MultiTextEdit(); 2328dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye change.setTextType(EXT_XML); 2338dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye changes.add(change); 2348dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 2358dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String text = getText(mSelectionStart, mSelectionEnd); 2368dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Element layout = getPrimaryElement(); 2378dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String oldName = layout.getNodeName(); 2388dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int open = text.indexOf(oldName); 2398dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int close = text.lastIndexOf(oldName); 2408dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 2418dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (open != -1 && close != -1) { 2428dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int oldLength = oldName.length(); 2438dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye rootEdit.addChild(new ReplaceEdit(mSelectionStart + open, oldLength, name)); 2448dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (close != open) { // Gracefully handle <FooLayout/> 2458dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye rootEdit.addChild(new ReplaceEdit(mSelectionStart + close, oldLength, name)); 2468dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 2478dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 2488dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 2499e6db060854d0e890190919a27a1846f50f69d1aTor Norbye String oldId = getId(layout); 2509e6db060854d0e890190919a27a1846f50f69d1aTor Norbye String newId = ensureIdMatchesType(layout, mTypeFqcn, rootEdit); 2519e6db060854d0e890190919a27a1846f50f69d1aTor Norbye // Update any layout references to the old id with the new id 2529e6db060854d0e890190919a27a1846f50f69d1aTor Norbye if (oldId != null && newId != null) { 253e50549f54810c29bffc681e39d33158ab2a8f26eRaphael IStructuredModel model = mDelegate.getEditor().getModelForRead(); 2549e6db060854d0e890190919a27a1846f50f69d1aTor Norbye try { 2559e6db060854d0e890190919a27a1846f50f69d1aTor Norbye IStructuredDocument doc = model.getStructuredDocument(); 2569e6db060854d0e890190919a27a1846f50f69d1aTor Norbye if (doc != null) { 2579e6db060854d0e890190919a27a1846f50f69d1aTor Norbye List<TextEdit> replaceIds = replaceIds(getAndroidNamespacePrefix(), doc, 2589e6db060854d0e890190919a27a1846f50f69d1aTor Norbye mSelectionStart, 2599e6db060854d0e890190919a27a1846f50f69d1aTor Norbye mSelectionEnd, oldId, newId); 2609e6db060854d0e890190919a27a1846f50f69d1aTor Norbye for (TextEdit edit : replaceIds) { 2619e6db060854d0e890190919a27a1846f50f69d1aTor Norbye rootEdit.addChild(edit); 2629e6db060854d0e890190919a27a1846f50f69d1aTor Norbye } 2639e6db060854d0e890190919a27a1846f50f69d1aTor Norbye } 2649e6db060854d0e890190919a27a1846f50f69d1aTor Norbye } finally { 2659e6db060854d0e890190919a27a1846f50f69d1aTor Norbye model.releaseFromRead(); 2669e6db060854d0e890190919a27a1846f50f69d1aTor Norbye } 2679e6db060854d0e890190919a27a1846f50f69d1aTor Norbye } 2680757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 2698dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String oldType = getOldType(); 2708dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String newType = mTypeFqcn; 27178d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye 2720757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye if (newType.equals(FQCN_RELATIVE_LAYOUT)) { 2730757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye if (oldType.equals(FQCN_LINEAR_LAYOUT) && !mFlatten) { 2740757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // Hand-coded conversion specifically tailored for linear to relative, provided 2750757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // there is no hierarchy flattening 2760757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // TODO: use the RelativeLayoutConversionHelper for this; it does a better job 2770757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // analyzing gravities etc. 2780757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye convertLinearToRelative(rootEdit); 27978d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye removeUndefinedAttrs(rootEdit, layout); 28078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null); 2810757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } else { 2820757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // Generic conversion to relative - can also flatten the hierarchy 28378d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye convertAnyToRelative(rootEdit, oldType, newType); 2840757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // This already handles removing undefined layout attributes -- right? 2850757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye //removeUndefinedLayoutAttrs(rootEdit, layout); 2860757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 287564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye } else if (newType.equals(FQCN_GRID_LAYOUT)) { 288564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye convertAnyToGridLayout(rootEdit); 2894cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye // Layout attributes on children have already been removed as part of conversion 2904cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye // during the flattening 2914cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye removeUndefinedAttrs(rootEdit, layout, false /*removeLayoutAttrs*/); 2928dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } else if (oldType.equals(FQCN_RELATIVE_LAYOUT) && newType.equals(FQCN_LINEAR_LAYOUT)) { 2938dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye convertRelativeToLinear(rootEdit); 29478d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye removeUndefinedAttrs(rootEdit, layout); 29578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null); 2968dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } else if (oldType.equals(FQCN_LINEAR_LAYOUT) && newType.equals(FQCN_TABLE_LAYOUT)) { 2978dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye convertLinearToTable(rootEdit); 29878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye removeUndefinedAttrs(rootEdit, layout); 29978d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null); 3008dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } else { 301564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye convertGeneric(rootEdit, oldType, newType, layout); 3028dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3038dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 3041294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye if (mInitializedAttributes != null && mInitializedAttributes.length() > 0) { 3051294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye String namespace = getAndroidNamespacePrefix(); 3061294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye for (String s : mInitializedAttributes.split(",")) { //$NON-NLS-1$ 3071294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye String[] nameValue = s.split("="); //$NON-NLS-1$ 3081294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye String attribute = nameValue[0]; 3091294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye String value = nameValue[1]; 3101294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye String prefix = null; 3111294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye String namespaceUri = null; 31212d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye if (attribute.startsWith(SdkConstants.ANDROID_NS_NAME_PREFIX)) { 3131294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye prefix = namespace; 3141294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye namespaceUri = ANDROID_URI; 31512d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye attribute = attribute.substring(SdkConstants.ANDROID_NS_NAME_PREFIX.length()); 3161294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye } 3171294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye setAttribute(rootEdit, layout, namespaceUri, 3181294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye prefix, attribute, value); 3191294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye } 3201294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye } 3211294048c3a602ab0de89f46b0f11cbb19d083befTor Norbye 322f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye if (AdtPrefs.getPrefs().getFormatGuiXml()) { 323f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye MultiTextEdit formatted = reformat(rootEdit, XmlFormatStyle.LAYOUT); 324f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye if (formatted != null) { 325f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye rootEdit = formatted; 326f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye } 327f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye } 328f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye change.setEdit(rootEdit); 329f5256a38ef2e429b5efd4482808bc902bf7634e3Tor Norbye 3308dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return changes; 3318dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3328dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 33378d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye /** Checks whether we need to add any missing attributes on the elements */ 33478d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye private void addMissingWrapContentAttributes(MultiTextEdit rootEdit, Element layout, 33578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye String oldType, String newType, Set<Element> skip) { 33678d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye if (oldType.equals(FQCN_GRID_LAYOUT) && !newType.equals(FQCN_GRID_LAYOUT)) { 33778d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye String namespace = getAndroidNamespacePrefix(); 33878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye 33978d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye for (Element child : DomUtilities.getChildren(layout)) { 34078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye if (skip != null && skip.contains(child)) { 34178d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye continue; 34278d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 34378d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye 34478d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye if (!child.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_WIDTH)) { 34578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye setAttribute(rootEdit, child, ANDROID_URI, 34678d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye namespace, ATTR_LAYOUT_WIDTH, VALUE_WRAP_CONTENT); 34778d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 34878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye if (!child.hasAttributeNS(ANDROID_URI, ATTR_LAYOUT_HEIGHT)) { 34978d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye setAttribute(rootEdit, child, ANDROID_URI, 35078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye namespace, ATTR_LAYOUT_HEIGHT, VALUE_WRAP_CONTENT); 35178d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 35278d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 35378d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 35478d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 35578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye 3568dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye /** Hand coded conversion from a LinearLayout to a TableLayout */ 3578dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye private void convertLinearToTable(MultiTextEdit rootEdit) { 3588dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // This is pretty easy; just switch the root tag (already done by the initial generic 3598dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // conversion) and then convert all the children into <TableRow> elements. 3608dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // Finally, get rid of the orientation attribute, if any. 3618dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Element layout = getPrimaryElement(); 3628dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye removeOrientationAttribute(rootEdit, layout); 3638dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 3648dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye NodeList children = layout.getChildNodes(); 3658dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye for (int i = 0, n = children.getLength(); i < n; i++) { 3668dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Node node = children.item(i); 3678dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (node.getNodeType() == Node.ELEMENT_NODE) { 3688dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Element child = (Element) node; 3698dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (node instanceof IndexedRegion) { 3708dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye IndexedRegion region = (IndexedRegion) node; 3718dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int start = region.getStartOffset(); 3728dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int end = region.getEndOffset(); 3738dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String text = getText(start, end); 3748dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String oldName = child.getNodeName(); 3758dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (oldName.equals(LINEAR_LAYOUT)) { 3768dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye removeOrientationAttribute(rootEdit, child); 3778dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int open = text.indexOf(oldName); 3788dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int close = text.lastIndexOf(oldName); 3798dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 3808dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (open != -1 && close != -1) { 3818dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye int oldLength = oldName.length(); 3828dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye rootEdit.addChild(new ReplaceEdit(mSelectionStart + open, oldLength, 3838dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye TABLE_ROW)); 3848dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (close != open) { // Gracefully handle <FooLayout/> 3858dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye rootEdit.addChild(new ReplaceEdit(mSelectionStart + close, 3868dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye oldLength, TABLE_ROW)); 3878dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3888dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3898dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } // else: WRAP in TableLayout! 3908dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3918dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3928dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3938dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 3948dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 3958dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye /** Hand coded conversion from a LinearLayout to a RelativeLayout */ 3968dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye private void convertLinearToRelative(MultiTextEdit rootEdit) { 3978dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // This can be done accurately. 3988dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Element layout = getPrimaryElement(); 3998dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // Horizontal is the default, so if no value is specified it is horizontal. 4008dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye boolean isVertical = VALUE_VERTICAL.equals(layout.getAttributeNS(ANDROID_URI, 4018dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye ATTR_ORIENTATION)); 4028dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 4038dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String attributePrefix = getAndroidNamespacePrefix(); 4048dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 4058dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // TODO: Consider gravity of each element 4068dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // TODO: Consider weight of each element 4078dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // Right now it simply makes a single attachment to keep the order. 4088dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 4098dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (isVertical) { 4108dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // Align each child to the bottom and left of its parent 4118dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye NodeList children = layout.getChildNodes(); 4128dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String prevId = null; 4138dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye for (int i = 0, n = children.getLength(); i < n; i++) { 4148dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Node node = children.item(i); 4158dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (node.getNodeType() == Node.ELEMENT_NODE) { 4168dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Element child = (Element) node; 4170757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye String id = ensureHasId(rootEdit, child, null); 4188dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (prevId != null) { 4190757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye setAttribute(rootEdit, child, ANDROID_URI, attributePrefix, 4208dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye ATTR_LAYOUT_BELOW, prevId); 4218dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4228dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye prevId = id; 4238dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4248dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4258dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } else { 4268dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // Align each child to the left 4278dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye NodeList children = layout.getChildNodes(); 4288dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye boolean isBaselineAligned = 4298dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye !VALUE_FALSE.equals(layout.getAttributeNS(ANDROID_URI, ATTR_BASELINE_ALIGNED)); 4308dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 4318dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String prevId = null; 4328dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye for (int i = 0, n = children.getLength(); i < n; i++) { 4338dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Node node = children.item(i); 4348dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (node.getNodeType() == Node.ELEMENT_NODE) { 4358dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Element child = (Element) node; 4360757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye String id = ensureHasId(rootEdit, child, null); 4378dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (prevId != null) { 4380757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye setAttribute(rootEdit, child, ANDROID_URI, attributePrefix, 4398dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye ATTR_LAYOUT_TO_RIGHT_OF, prevId); 4408dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (isBaselineAligned) { 4410757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye setAttribute(rootEdit, child, ANDROID_URI, attributePrefix, 4428dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye ATTR_LAYOUT_ALIGN_BASELINE, prevId); 4438dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4448dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4458dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye prevId = id; 4468dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4478dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4488dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4498dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4508dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 4518dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye /** Strips out the android:orientation attribute from the given linear layout element */ 4528dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye private void removeOrientationAttribute(MultiTextEdit rootEdit, Element layout) { 4538dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye assert layout.getTagName().equals(LINEAR_LAYOUT); 4548dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye removeAttribute(rootEdit, layout, ANDROID_URI, ATTR_ORIENTATION); 4558dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4568dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 4578dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye /** 4588dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * Hand coded conversion from a RelativeLayout to a LinearLayout 4598dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * 4608dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * @param rootEdit the root multi text edit to add edits to 4618dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye */ 4628dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye private void convertRelativeToLinear(MultiTextEdit rootEdit) { 4638dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // This is going to be lossy... 4648dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // TODO: Attempt to "order" the items based on their visual positions 4658dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // and insert them in that order in the LinearLayout. 4668dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // TODO: Possibly use nesting if necessary, by spatial subdivision, 4678dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // to accomplish roughly the same layout as the relative layout specifies. 4688dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 4698dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 4708dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye /** 4718dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * Hand coded -generic- conversion from one layout to another. This is not going to be 4728dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * an accurate layout transformation; instead it simply migrates the layout attributes 4738dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * that are supported, and adds defaults for any new required layout attributes. In 4748dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * addition, it attempts to order the children visually based on where they fit in a 4758dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * rendering. (Unsupported layout attributes will be removed by the caller at the 4768dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * end.) 4778dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * <ul> 4788dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * <li>Try to handle nesting. Converting a *hierarchy* of layouts into a flatter 4798dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * layout for powerful layouts that support it, like RelativeLayout. 4808dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * <li>Try to do automatic "inference" about the layout. I can render it and look at 4818dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * the ViewInfo positions and sizes. I can render it multiple times, at different 4828dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * sizes, to infer "stretchiness" and "weight" properties of the children. 4838dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * <li>Try to do indirect transformations. E.g. if I can go from A to B, and B to C, 4848dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * then an attempt to go from A to C should perform conversions A to B and then B to 4858dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * C. 4868dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * </ul> 4878dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * 4888dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * @param rootEdit the root multi text edit to add edits to 4898dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * @param oldType the fully qualified class name of the layout type we are converting 4908dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * from 4918dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * @param newType the fully qualified class name of the layout type we are converting 4928dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye * to 493564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye * @param layout the layout to be converted 4948dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye */ 495564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye private void convertGeneric(MultiTextEdit rootEdit, String oldType, String newType, 496564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye Element layout) { 4978dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // TODO: Add hooks for 3rd party conversions getting registered through the 4988dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // IViewRule interface. 4998dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 5008dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // For now we simply go with the default behavior, which is to just strip the 5018dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye // layout attributes that aren't supported. 50278d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye removeUndefinedAttrs(rootEdit, layout); 50378d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, null); 5048dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 5058dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 50678d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye /** 50778d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye * Removes all the unavailable attributes after a conversion, both on the 50878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye * layout element itself as well as the layout attributes of any of the 50978d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye * children 51078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye */ 51178d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye private void removeUndefinedAttrs(MultiTextEdit rootEdit, Element layout) { 5124cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye removeUndefinedAttrs(rootEdit, layout, true /*removeLayoutAttrs*/); 5134cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye } 5144cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye 5154cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye private void removeUndefinedAttrs(MultiTextEdit rootEdit, Element layout, 5164cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye boolean removeLayoutAttrs) { 5170757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye ViewElementDescriptor descriptor = getElementDescriptor(mTypeFqcn); 5188dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (descriptor == null) { 5198dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return; 5208dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 5218dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 5224cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye if (removeLayoutAttrs) { 5234cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye Set<String> defined = new HashSet<String>(); 5244cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye AttributeDescriptor[] layoutAttributes = descriptor.getLayoutAttributes(); 5254cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye for (AttributeDescriptor attribute : layoutAttributes) { 5264cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye defined.add(attribute.getXmlLocalName()); 5274cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye } 5288dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 5294cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye NodeList children = layout.getChildNodes(); 5304cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye for (int i = 0, n = children.getLength(); i < n; i++) { 5314cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye Node node = children.item(i); 5324cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye if (node.getNodeType() == Node.ELEMENT_NODE) { 5334cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye Element child = (Element) node; 5348dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 5354cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye List<Attr> attributes = findLayoutAttributes(child); 5364cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye for (Attr attribute : attributes) { 5374cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye String name = attribute.getLocalName(); 5384cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye if (!defined.contains(name)) { 5394cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye // Remove it 5404cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye try { 5414cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye removeAttribute(rootEdit, child, attribute.getNamespaceURI(), name); 5424cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye } catch (MalformedTreeException mte) { 5434cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye // Sometimes refactoring has modified attribute; not removing 5444cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye // it is non-fatal so just warn instead of letting refactoring 5454cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye // operation abort 5464cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye AdtPlugin.log(IStatus.WARNING, 5474cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye "Could not remove unsupported attribute %1$s; " + //$NON-NLS-1$ 5484cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye "already modified during refactoring?", //$NON-NLS-1$ 5494cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye attribute.getLocalName()); 5504cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye } 5514cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye } 5528dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 5538dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 5548dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 5558dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 55678d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye 55778d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye // Also remove the unavailable attributes (not layout attributes) on the 55878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye // converted element 5594cd282c7b21dc06c2d2d02748278f07c94282fc1Tor Norbye Set<String> defined = new HashSet<String>(); 56078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye AttributeDescriptor[] attributes = descriptor.getAttributes(); 56178d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye for (AttributeDescriptor attribute : attributes) { 56278d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye defined.add(attribute.getXmlLocalName()); 56378d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 56478d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye 56578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye // Remove undefined attributes on the layout element itself 56678d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye NamedNodeMap attributeMap = layout.getAttributes(); 56778d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye for (int i = 0, n = attributeMap.getLength(); i < n; i++) { 56878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye Node attributeNode = attributeMap.item(i); 56978d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye 57078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye String name = attributeNode.getLocalName(); 57112d4581faa6438941e65a9dc83213be34c6ca970Tor Norbye if (!name.startsWith(ATTR_LAYOUT_RESOURCE_PREFIX) 57278d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye && ANDROID_URI.equals(attributeNode.getNamespaceURI())) { 57378d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye if (!defined.contains(name)) { 57478d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye // Remove it 57578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye removeAttribute(rootEdit, layout, ANDROID_URI, name); 57678d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 57778d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 57878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 5798dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 5808dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 5810757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye /** Hand coded conversion from any layout to a RelativeLayout */ 58278d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye private void convertAnyToRelative(MultiTextEdit rootEdit, String oldType, String newType) { 5830757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye // To perform a conversion from any other layout type, including nested conversion, 5840757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye Element layout = getPrimaryElement(); 5850757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye CanvasViewInfo rootView = mRootView; 5860757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye if (rootView == null) { 587e50549f54810c29bffc681e39d33158ab2a8f26eRaphael LayoutCanvas canvas = mDelegate.getGraphicalEditor().getCanvasControl(); 5880757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye ViewHierarchy viewHierarchy = canvas.getViewHierarchy(); 5890757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye rootView = viewHierarchy.getRoot(); 5908dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 5918dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 5920757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye RelativeLayoutConversionHelper helper = 5930757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye new RelativeLayoutConversionHelper(this, layout, mFlatten, rootEdit, rootView); 5940757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye helper.convertToRelative(); 59578d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye List<Element> deletedElements = helper.getDeletedElements(); 59678d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye Set<Element> deleted = null; 59778d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye if (deletedElements != null && deletedElements.size() > 0) { 59878d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye deleted = new HashSet<Element>(deletedElements); 59978d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye } 60078d3947aeebf2d8c0d17fe35d0fd94e53013b60eTor Norbye addMissingWrapContentAttributes(rootEdit, layout, oldType, newType, deleted); 6018dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 6028dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 603564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye /** Hand coded conversion from any layout to a GridLayout */ 604564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye private void convertAnyToGridLayout(MultiTextEdit rootEdit) { 605564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye // To perform a conversion from any other layout type, including nested conversion, 606564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye Element layout = getPrimaryElement(); 607564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye CanvasViewInfo rootView = mRootView; 608564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye if (rootView == null) { 609e50549f54810c29bffc681e39d33158ab2a8f26eRaphael LayoutCanvas canvas = mDelegate.getGraphicalEditor().getCanvasControl(); 610564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye ViewHierarchy viewHierarchy = canvas.getViewHierarchy(); 611564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye rootView = viewHierarchy.getRoot(); 612564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye } 613564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye 614564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye GridLayoutConverter converter = new GridLayoutConverter(this, layout, mFlatten, 615564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye rootEdit, rootView); 616564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye converter.convertToGridLayout(); 617564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye } 618564e4b80f642af7fa13c01f407c112778e25ae1eTor Norbye 6198dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye public static class Descriptor extends VisualRefactoringDescriptor { 6208dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye public Descriptor(String project, String description, String comment, 6218dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Map<String, String> arguments) { 6228dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye super("com.android.ide.eclipse.adt.refactoring.convert", //$NON-NLS-1$ 6238dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye project, description, comment, arguments); 6248dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 6258dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 6268dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye @Override 6278dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye protected Refactoring createRefactoring(Map<String, String> args) { 6288dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return new ChangeLayoutRefactoring(args); 6298dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 6308dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 6318dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 6328dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String getOldType() { 6338dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye Element primary = getPrimaryElement(); 6348dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (primary != null) { 6358dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye String oldType = primary.getTagName(); 6368dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye if (oldType.indexOf('.') == -1) { 6378dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye oldType = ANDROID_WIDGET_PREFIX + oldType; 6388dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 6398dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return oldType; 6408dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 6418dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye 6428dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye return null; 6438dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye } 6440757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 6450757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye @VisibleForTesting 6460757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye protected CanvasViewInfo mRootView; 6470757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye 6480757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye @VisibleForTesting 6490757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye public void setRootView(CanvasViewInfo rootView) { 6500757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye mRootView = rootView; 6510757ce4af2764e4dd564acc0b1a013e910abc8daTor Norbye } 652891fe684c31864eab0ef4372ea6379f2c3b5fb4fTor Norbye 653891fe684c31864eab0ef4372ea6379f2c3b5fb4fTor Norbye @Override 654891fe684c31864eab0ef4372ea6379f2c3b5fb4fTor Norbye VisualRefactoringWizard createWizard() { 655e50549f54810c29bffc681e39d33158ab2a8f26eRaphael return new ChangeLayoutWizard(this, mDelegate); 656891fe684c31864eab0ef4372ea6379f2c3b5fb4fTor Norbye } 6578dc4366bbaad39d56e1c2ded4046c86a95a17666Tor Norbye} 658