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
17package com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
18
19import static com.android.SdkConstants.FQCN_GRID_LAYOUT;
20import static com.android.SdkConstants.FQCN_RELATIVE_LAYOUT;
21import static com.android.SdkConstants.GRID_LAYOUT;
22import static com.android.SdkConstants.RELATIVE_LAYOUT;
23import static com.android.SdkConstants.VIEW_FRAGMENT;
24import static com.android.SdkConstants.VIEW_INCLUDE;
25import static com.android.SdkConstants.VIEW_MERGE;
26
27import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
28import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
29import com.android.ide.eclipse.adt.internal.editors.layout.gre.PaletteMetadataDescriptor;
30import com.android.utils.Pair;
31
32import org.eclipse.core.resources.IProject;
33import org.eclipse.swt.SWT;
34import org.eclipse.swt.events.SelectionAdapter;
35import org.eclipse.swt.events.SelectionEvent;
36import org.eclipse.swt.layout.GridData;
37import org.eclipse.swt.layout.GridLayout;
38import org.eclipse.swt.widgets.Button;
39import org.eclipse.swt.widgets.Combo;
40import org.eclipse.swt.widgets.Composite;
41import org.eclipse.swt.widgets.Label;
42
43import java.util.HashSet;
44import java.util.List;
45import java.util.Set;
46
47class ChangeLayoutWizard extends VisualRefactoringWizard {
48
49    public ChangeLayoutWizard(ChangeLayoutRefactoring ref, LayoutEditorDelegate editor) {
50        super(ref, editor);
51        setDefaultPageTitle("Change Layout");
52    }
53
54    @Override
55    protected void addUserInputPages() {
56        ChangeLayoutRefactoring ref = (ChangeLayoutRefactoring) getRefactoring();
57        String oldType = ref.getOldType();
58        addPage(new InputPage(mDelegate.getEditor().getProject(), oldType));
59    }
60
61    /** Wizard page which inputs parameters for the {@link ChangeLayoutRefactoring} operation */
62    private static class InputPage extends VisualRefactoringInputPage {
63        private final IProject mProject;
64        private final String mOldType;
65        private Combo mTypeCombo;
66        private Button mFlatten;
67        private List<Pair<String, ViewElementDescriptor>> mClassNames;
68
69        public InputPage(IProject project, String oldType) {
70            super("ChangeLayoutInputPage");  //$NON-NLS-1$
71            mProject = project;
72            mOldType = oldType;
73        }
74
75        @Override
76        public void createControl(Composite parent) {
77            Composite composite = new Composite(parent, SWT.NONE);
78            composite.setLayout(new GridLayout(2, false));
79
80            Label fromLabel = new Label(composite, SWT.NONE);
81            fromLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
82            String oldTypeBase = mOldType.substring(mOldType.lastIndexOf('.') + 1);
83            fromLabel.setText(String.format("Change from %1$s", oldTypeBase));
84
85            Label typeLabel = new Label(composite, SWT.NONE);
86            typeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
87            typeLabel.setText("New Layout Type:");
88
89            mTypeCombo = new Combo(composite, SWT.READ_ONLY);
90            mTypeCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
91            SelectionAdapter selectionListener = new SelectionAdapter() {
92                @Override
93                public void widgetSelected(SelectionEvent e) {
94                    validatePage();
95                    // Hierarchy flattening only works for relative layout (and any future
96                    // layouts that can also support arbitrary layouts).
97                    String text = mTypeCombo.getText();
98                    mFlatten.setVisible(text.equals(RELATIVE_LAYOUT) || text.equals(GRID_LAYOUT));
99                }
100            };
101            mTypeCombo.addSelectionListener(selectionListener);
102            mTypeCombo.addSelectionListener(mSelectionValidateListener);
103
104            mFlatten = new Button(composite, SWT.CHECK);
105            mFlatten.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER,
106                    false, false, 2, 1));
107            mFlatten.setText("Flatten hierarchy");
108            mFlatten.addSelectionListener(selectionListener);
109            // Should flattening be selected by default?
110            mFlatten.setSelection(true);
111            mFlatten.addSelectionListener(mSelectionValidateListener);
112
113            // We don't exclude RelativeLayout even if the current layout is RelativeLayout,
114            // in case you are trying to flatten the hierarchy for a hierarchy that has a
115            // RelativeLayout at the root.
116            Set<String> exclude = new HashSet<String>();
117            exclude.add(VIEW_INCLUDE);
118            exclude.add(VIEW_MERGE);
119            exclude.add(VIEW_FRAGMENT);
120            boolean oldIsRelativeLayout = mOldType.equals(FQCN_RELATIVE_LAYOUT);
121            boolean oldIsGridLayout = mOldType.equals(FQCN_GRID_LAYOUT);
122            if (oldIsRelativeLayout || oldIsGridLayout) {
123                exclude.add(mOldType);
124            }
125            mClassNames = WrapInWizard.addLayouts(mProject, mOldType, mTypeCombo, exclude, false);
126
127            boolean gridLayoutAvailable = false;
128            for (int i = 0; i < mTypeCombo.getItemCount(); i++) {
129                if (mTypeCombo.getItem(i).equals(GRID_LAYOUT)) {
130                    gridLayoutAvailable = true;
131                    break;
132                }
133            }
134
135            mTypeCombo.select(0);
136            // The default should be GridLayout (if available) and if not RelativeLayout,
137            // if available (and not the old Type)
138            if (gridLayoutAvailable && !oldIsGridLayout) {
139                for (int i = 0; i < mTypeCombo.getItemCount(); i++) {
140                    if (mTypeCombo.getItem(i).equals(GRID_LAYOUT)) {
141                        mTypeCombo.select(i);
142                        break;
143                    }
144                }
145            } else if (!oldIsRelativeLayout) {
146                for (int i = 0; i < mTypeCombo.getItemCount(); i++) {
147                    if (mTypeCombo.getItem(i).equals(RELATIVE_LAYOUT)) {
148                        mTypeCombo.select(i);
149                        break;
150                    }
151                }
152            }
153            mFlatten.setVisible(mTypeCombo.getText().equals(RELATIVE_LAYOUT)
154                    || mTypeCombo.getText().equals(GRID_LAYOUT));
155
156            setControl(composite);
157            validatePage();
158        }
159
160        @Override
161        protected boolean validatePage() {
162            boolean ok = true;
163
164            int selectionIndex = mTypeCombo.getSelectionIndex();
165            String type = selectionIndex != -1 ? mClassNames.get(selectionIndex).getFirst() : null;
166            if (type == null) {
167                setErrorMessage("Select a layout type");
168                ok = false; // The user has chosen a separator
169            } else {
170                setErrorMessage(null);
171
172                // Record state
173                ChangeLayoutRefactoring refactoring =
174                    (ChangeLayoutRefactoring) getRefactoring();
175                refactoring.setType(type);
176                refactoring.setFlatten(mFlatten.getSelection());
177
178                ViewElementDescriptor descriptor = mClassNames.get(selectionIndex).getSecond();
179                if (descriptor instanceof PaletteMetadataDescriptor) {
180                    PaletteMetadataDescriptor paletteDescriptor =
181                        (PaletteMetadataDescriptor) descriptor;
182                    String initializedAttributes = paletteDescriptor.getInitializedAttributes();
183                    if (initializedAttributes != null && initializedAttributes.length() > 0) {
184                        refactoring.setInitializedAttributes(initializedAttributes);
185                    }
186                } else {
187                    refactoring.setInitializedAttributes(null);
188                }
189            }
190
191            setPageComplete(ok);
192            return ok;
193        }
194    }
195}
196