| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Eclipse Public License, Version 1.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.eclipse.org/org/documents/epl-v10.php |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.ide.eclipse.adt.internal.editors.layout.gre; |
| |
| import static com.android.SdkConstants.ANDROID_URI; |
| import static com.android.SdkConstants.ATTR_ID; |
| import static com.android.SdkConstants.AUTO_URI; |
| import static com.android.SdkConstants.CLASS_FRAGMENT; |
| import static com.android.SdkConstants.CLASS_V4_FRAGMENT; |
| import static com.android.SdkConstants.CLASS_VIEW; |
| import static com.android.SdkConstants.NEW_ID_PREFIX; |
| import static com.android.SdkConstants.URI_PREFIX; |
| |
| import com.android.annotations.NonNull; |
| import com.android.annotations.Nullable; |
| import com.android.ide.common.api.IClientRulesEngine; |
| import com.android.ide.common.api.INode; |
| import com.android.ide.common.api.IValidator; |
| import com.android.ide.common.api.IViewMetadata; |
| import com.android.ide.common.api.IViewRule; |
| import com.android.ide.common.api.Margins; |
| import com.android.ide.common.api.Rect; |
| import com.android.ide.common.layout.BaseViewRule; |
| import com.android.ide.common.resources.ResourceRepository; |
| import com.android.ide.eclipse.adt.AdtPlugin; |
| import com.android.ide.eclipse.adt.internal.actions.AddSupportJarAction; |
| import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; |
| import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils; |
| import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; |
| import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationChooser; |
| import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo; |
| import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart; |
| import com.android.ide.eclipse.adt.internal.editors.layout.gle2.LayoutCanvas; |
| import com.android.ide.eclipse.adt.internal.editors.layout.gle2.RenderService; |
| import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SelectionManager; |
| import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ViewHierarchy; |
| import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; |
| import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode; |
| import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; |
| import com.android.ide.eclipse.adt.internal.refactorings.core.RenameResult; |
| import com.android.ide.eclipse.adt.internal.resources.CyclicDependencyValidator; |
| import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator; |
| import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; |
| import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; |
| import com.android.ide.eclipse.adt.internal.sdk.ProjectState; |
| import com.android.ide.eclipse.adt.internal.sdk.Sdk; |
| import com.android.ide.eclipse.adt.internal.ui.MarginChooser; |
| import com.android.ide.eclipse.adt.internal.ui.ReferenceChooserDialog; |
| import com.android.ide.eclipse.adt.internal.ui.ResourceChooser; |
| import com.android.ide.eclipse.adt.internal.ui.ResourcePreviewHelper; |
| import com.android.resources.ResourceType; |
| import com.android.sdklib.IAndroidTarget; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.ITypeHierarchy; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.search.IJavaSearchScope; |
| import org.eclipse.jdt.core.search.SearchEngine; |
| import org.eclipse.jdt.ui.IJavaElementSearchConstants; |
| import org.eclipse.jdt.ui.JavaUI; |
| import org.eclipse.jdt.ui.actions.OpenNewClassWizardAction; |
| import org.eclipse.jdt.ui.dialogs.ITypeInfoFilterExtension; |
| import org.eclipse.jdt.ui.dialogs.ITypeInfoRequestor; |
| import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension; |
| import org.eclipse.jdt.ui.wizards.NewClassWizardPage; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.IInputValidator; |
| import org.eclipse.jface.dialogs.InputDialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.dialogs.ProgressMonitorDialog; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.dialogs.SelectionDialog; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.atomic.AtomicReference; |
| |
| /** |
| * Implementation of {@link IClientRulesEngine}. This provides {@link IViewRule} clients |
| * with a few methods they can use to access functionality from this {@link RulesEngine}. |
| */ |
| class ClientRulesEngine implements IClientRulesEngine { |
| /** The return code from the dialog for the user choosing "Clear" */ |
| public static final int CLEAR_RETURN_CODE = -5; |
| /** The dialog button ID for the user choosing "Clear" */ |
| private static final int CLEAR_BUTTON_ID = CLEAR_RETURN_CODE; |
| |
| private final RulesEngine mRulesEngine; |
| private final String mFqcn; |
| |
| public ClientRulesEngine(RulesEngine rulesEngine, String fqcn) { |
| mRulesEngine = rulesEngine; |
| mFqcn = fqcn; |
| } |
| |
| @Override |
| public @NonNull String getFqcn() { |
| return mFqcn; |
| } |
| |
| @Override |
| public void debugPrintf(@NonNull String msg, Object... params) { |
| AdtPlugin.printToConsole( |
| mFqcn == null ? "<unknown>" : mFqcn, |
| String.format(msg, params) |
| ); |
| } |
| |
| @Override |
| public IViewRule loadRule(@NonNull String fqcn) { |
| return mRulesEngine.loadRule(fqcn, fqcn); |
| } |
| |
| @Override |
| public void displayAlert(@NonNull String message) { |
| MessageDialog.openInformation( |
| AdtPlugin.getShell(), |
| mFqcn, // title |
| message); |
| } |
| |
| @Override |
| public boolean rename(INode node) { |
| GraphicalEditorPart editor = mRulesEngine.getEditor(); |
| SelectionManager manager = editor.getCanvasControl().getSelectionManager(); |
| RenameResult result = manager.performRename(node, null); |
| |
| return !result.isCanceled() && !result.isUnavailable(); |
| } |
| |
| @Override |
| public String displayInput(@NonNull String message, @Nullable String value, |
| final @Nullable IValidator filter) { |
| IInputValidator validator = null; |
| if (filter != null) { |
| validator = new IInputValidator() { |
| @Override |
| public String isValid(String newText) { |
| // IValidator has the same interface as SWT's IInputValidator |
| try { |
| return filter.validate(newText); |
| } catch (Exception e) { |
| AdtPlugin.log(e, "Custom validator failed: %s", e.toString()); |
| return ""; //$NON-NLS-1$ |
| } |
| } |
| }; |
| } |
| |
| InputDialog d = new InputDialog( |
| AdtPlugin.getShell(), |
| mFqcn, // title |
| message, |
| value == null ? "" : value, //$NON-NLS-1$ |
| validator) { |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| createButton(parent, CLEAR_BUTTON_ID, "Clear", false /*defaultButton*/); |
| super.createButtonsForButtonBar(parent); |
| } |
| |
| @Override |
| protected void buttonPressed(int buttonId) { |
| super.buttonPressed(buttonId); |
| |
| if (buttonId == CLEAR_BUTTON_ID) { |
| assert CLEAR_RETURN_CODE != Window.OK && CLEAR_RETURN_CODE != Window.CANCEL; |
| setReturnCode(CLEAR_RETURN_CODE); |
| close(); |
| } |
| } |
| }; |
| int result = d.open(); |
| if (result == ResourceChooser.CLEAR_RETURN_CODE) { |
| return ""; |
| } else if (result == Window.OK) { |
| return d.getValue(); |
| } |
| return null; |
| } |
| |
| @Override |
| @Nullable |
| public Object getViewObject(@NonNull INode node) { |
| ViewHierarchy views = mRulesEngine.getEditor().getCanvasControl().getViewHierarchy(); |
| CanvasViewInfo vi = views.findViewInfoFor(node); |
| if (vi != null) { |
| return vi.getViewObject(); |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public @NonNull IViewMetadata getMetadata(final @NonNull String fqcn) { |
| return new IViewMetadata() { |
| @Override |
| public @NonNull String getDisplayName() { |
| // This also works when there is no "." |
| return fqcn.substring(fqcn.lastIndexOf('.') + 1); |
| } |
| |
| @Override |
| public @NonNull FillPreference getFillPreference() { |
| return ViewMetadataRepository.get().getFillPreference(fqcn); |
| } |
| |
| @Override |
| public @NonNull Margins getInsets() { |
| return mRulesEngine.getEditor().getCanvasControl().getInsets(fqcn); |
| } |
| |
| @Override |
| public @NonNull List<String> getTopAttributes() { |
| return ViewMetadataRepository.get().getTopAttributes(fqcn); |
| } |
| }; |
| } |
| |
| @Override |
| public int getMinApiLevel() { |
| Sdk currentSdk = Sdk.getCurrent(); |
| if (currentSdk != null) { |
| IAndroidTarget target = currentSdk.getTarget(mRulesEngine.getEditor().getProject()); |
| if (target != null) { |
| return target.getVersion().getApiLevel(); |
| } |
| } |
| |
| return -1; |
| } |
| |
| @Override |
| public IValidator getResourceValidator( |
| @NonNull final String resourceTypeName, final boolean uniqueInProject, |
| final boolean uniqueInLayout, final boolean exists, final String... allowed) { |
| return new IValidator() { |
| private ResourceNameValidator mValidator; |
| |
| @Override |
| public String validate(@NonNull String text) { |
| if (mValidator == null) { |
| ResourceType type = ResourceType.getEnum(resourceTypeName); |
| if (uniqueInLayout) { |
| assert !uniqueInProject; |
| assert !exists; |
| Set<String> existing = new HashSet<String>(); |
| Document doc = mRulesEngine.getEditor().getModel().getXmlDocument(); |
| if (doc != null) { |
| addIds(doc, existing); |
| } |
| for (String s : allowed) { |
| existing.remove(s); |
| } |
| mValidator = ResourceNameValidator.create(false, existing, type); |
| } else { |
| assert allowed.length == 0; |
| IProject project = mRulesEngine.getEditor().getProject(); |
| mValidator = ResourceNameValidator.create(false, project, type); |
| if (uniqueInProject) { |
| mValidator.unique(); |
| } |
| } |
| if (exists) { |
| mValidator.exist(); |
| } |
| } |
| |
| return mValidator.isValid(text); |
| } |
| }; |
| } |
| |
| /** Find declared ids under the given DOM node */ |
| private static void addIds(Node node, Set<String> ids) { |
| if (node.getNodeType() == Node.ELEMENT_NODE) { |
| Element element = (Element) node; |
| String id = element.getAttributeNS(ANDROID_URI, ATTR_ID); |
| if (id != null && id.startsWith(NEW_ID_PREFIX)) { |
| ids.add(BaseViewRule.stripIdPrefix(id)); |
| } |
| } |
| |
| NodeList children = node.getChildNodes(); |
| for (int i = 0, n = children.getLength(); i < n; i++) { |
| Node child = children.item(i); |
| addIds(child, ids); |
| } |
| } |
| |
| @Override |
| public String displayReferenceInput(@Nullable String currentValue) { |
| GraphicalEditorPart graphicalEditor = mRulesEngine.getEditor(); |
| LayoutEditorDelegate delegate = graphicalEditor.getEditorDelegate(); |
| IProject project = delegate.getEditor().getProject(); |
| if (project != null) { |
| // get the resource repository for this project and the system resources. |
| ResourceRepository projectRepository = |
| ResourceManager.getInstance().getProjectResources(project); |
| Shell shell = AdtPlugin.getShell(); |
| if (shell == null) { |
| return null; |
| } |
| ReferenceChooserDialog dlg = new ReferenceChooserDialog( |
| project, |
| projectRepository, |
| shell); |
| dlg.setPreviewHelper(new ResourcePreviewHelper(dlg, graphicalEditor)); |
| |
| dlg.setCurrentResource(currentValue); |
| |
| if (dlg.open() == Window.OK) { |
| return dlg.getCurrentResource(); |
| } |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public String displayResourceInput(@NonNull String resourceTypeName, |
| @Nullable String currentValue) { |
| return displayResourceInput(resourceTypeName, currentValue, null); |
| } |
| |
| private String displayResourceInput(String resourceTypeName, String currentValue, |
| IInputValidator validator) { |
| ResourceType type = ResourceType.getEnum(resourceTypeName); |
| GraphicalEditorPart graphicalEditor = mRulesEngine.getEditor(); |
| return ResourceChooser.chooseResource(graphicalEditor, type, currentValue, validator); |
| } |
| |
| @Override |
| public String[] displayMarginInput(@Nullable String all, @Nullable String left, |
| @Nullable String right, @Nullable String top, @Nullable String bottom) { |
| GraphicalEditorPart editor = mRulesEngine.getEditor(); |
| IProject project = editor.getProject(); |
| if (project != null) { |
| Shell shell = AdtPlugin.getShell(); |
| if (shell == null) { |
| return null; |
| } |
| AndroidTargetData data = editor.getEditorDelegate().getEditor().getTargetData(); |
| MarginChooser dialog = new MarginChooser(shell, editor, data, all, left, right, |
| top, bottom); |
| if (dialog.open() == Window.OK) { |
| return dialog.getMargins(); |
| } |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public String displayIncludeSourceInput() { |
| AndroidXmlEditor editor = mRulesEngine.getEditor().getEditorDelegate().getEditor(); |
| IInputValidator validator = CyclicDependencyValidator.create(editor.getInputFile()); |
| return displayResourceInput(ResourceType.LAYOUT.getName(), null, validator); |
| } |
| |
| @Override |
| public void select(final @NonNull Collection<INode> nodes) { |
| LayoutCanvas layoutCanvas = mRulesEngine.getEditor().getCanvasControl(); |
| final SelectionManager selectionManager = layoutCanvas.getSelectionManager(); |
| selectionManager.select(nodes); |
| // ALSO run an async select since immediately after nodes are created they |
| // may not be selectable. We can't ONLY run an async exec since |
| // code may depend on operating on the selection. |
| layoutCanvas.getDisplay().asyncExec(new Runnable() { |
| @Override |
| public void run() { |
| selectionManager.select(nodes); |
| } |
| }); |
| } |
| |
| @Override |
| public String displayFragmentSourceInput() { |
| try { |
| // Compute a search scope: We need to merge all the subclasses |
| // android.app.Fragment and android.support.v4.app.Fragment |
| IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); |
| IProject project = mRulesEngine.getProject(); |
| final IJavaProject javaProject = BaseProjectHelper.getJavaProject(project); |
| if (javaProject != null) { |
| IType oldFragmentType = javaProject.findType(CLASS_V4_FRAGMENT); |
| |
| // First check to make sure fragments are available, and if not, |
| // warn the user. |
| IAndroidTarget target = Sdk.getCurrent().getTarget(project); |
| // No, this should be using the min SDK instead! |
| if (target.getVersion().getApiLevel() < 11 && oldFragmentType == null) { |
| // Compatibility library must be present |
| MessageDialog dialog = |
| new MessageDialog( |
| Display.getCurrent().getActiveShell(), |
| "Fragment Warning", |
| null, |
| "Fragments require API level 11 or higher, or a compatibility " |
| + "library for older versions.\n\n" |
| + " Do you want to install the compatibility library?", |
| MessageDialog.QUESTION, |
| new String[] { "Install", "Cancel" }, |
| 1 /* default button: Cancel */); |
| int answer = dialog.open(); |
| if (answer == 0) { |
| if (!AddSupportJarAction.install(project)) { |
| return null; |
| } |
| } else { |
| return null; |
| } |
| } |
| |
| // Look up sub-types of each (new fragment class and compatibility fragment |
| // class, if any) and merge the two arrays - then create a scope from these |
| // elements. |
| IType[] fragmentTypes = new IType[0]; |
| IType[] oldFragmentTypes = new IType[0]; |
| if (oldFragmentType != null) { |
| ITypeHierarchy hierarchy = |
| oldFragmentType.newTypeHierarchy(new NullProgressMonitor()); |
| oldFragmentTypes = hierarchy.getAllSubtypes(oldFragmentType); |
| } |
| IType fragmentType = javaProject.findType(CLASS_FRAGMENT); |
| if (fragmentType != null) { |
| ITypeHierarchy hierarchy = |
| fragmentType.newTypeHierarchy(new NullProgressMonitor()); |
| fragmentTypes = hierarchy.getAllSubtypes(fragmentType); |
| } |
| IType[] subTypes = new IType[fragmentTypes.length + oldFragmentTypes.length]; |
| System.arraycopy(fragmentTypes, 0, subTypes, 0, fragmentTypes.length); |
| System.arraycopy(oldFragmentTypes, 0, subTypes, fragmentTypes.length, |
| oldFragmentTypes.length); |
| scope = SearchEngine.createJavaSearchScope(subTypes, IJavaSearchScope.SOURCES); |
| } |
| |
| Shell parent = AdtPlugin.getShell(); |
| final AtomicReference<String> returnValue = |
| new AtomicReference<String>(); |
| final AtomicReference<SelectionDialog> dialogHolder = |
| new AtomicReference<SelectionDialog>(); |
| final SelectionDialog dialog = JavaUI.createTypeDialog( |
| parent, |
| new ProgressMonitorDialog(parent), |
| scope, |
| IJavaElementSearchConstants.CONSIDER_CLASSES, false, |
| // Use ? as a default filter to fill dialog with matches |
| "?", //$NON-NLS-1$ |
| new TypeSelectionExtension() { |
| @Override |
| public Control createContentArea(Composite parentComposite) { |
| Composite composite = new Composite(parentComposite, SWT.NONE); |
| composite.setLayout(new GridLayout(1, false)); |
| Button button = new Button(composite, SWT.PUSH); |
| button.setText("Create New..."); |
| button.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| String fqcn = createNewFragmentClass(javaProject); |
| if (fqcn != null) { |
| returnValue.set(fqcn); |
| dialogHolder.get().close(); |
| } |
| } |
| }); |
| return composite; |
| } |
| |
| @Override |
| public ITypeInfoFilterExtension getFilterExtension() { |
| return new ITypeInfoFilterExtension() { |
| @Override |
| public boolean select(ITypeInfoRequestor typeInfoRequestor) { |
| int modifiers = typeInfoRequestor.getModifiers(); |
| if (!Flags.isPublic(modifiers) |
| || Flags.isInterface(modifiers) |
| || Flags.isEnum(modifiers) |
| || Flags.isAbstract(modifiers)) { |
| return false; |
| } |
| return true; |
| } |
| }; |
| } |
| }); |
| dialogHolder.set(dialog); |
| |
| dialog.setTitle("Choose Fragment Class"); |
| dialog.setMessage("Select a Fragment class (? = any character, * = any string):"); |
| if (dialog.open() == IDialogConstants.CANCEL_ID) { |
| return null; |
| } |
| if (returnValue.get() != null) { |
| return returnValue.get(); |
| } |
| |
| Object[] types = dialog.getResult(); |
| if (types != null && types.length > 0) { |
| return ((IType) types[0]).getFullyQualifiedName(); |
| } |
| } catch (JavaModelException e) { |
| AdtPlugin.log(e, null); |
| } catch (CoreException e) { |
| AdtPlugin.log(e, null); |
| } |
| return null; |
| } |
| |
| @Override |
| public String displayCustomViewClassInput() { |
| try { |
| IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); |
| IProject project = mRulesEngine.getProject(); |
| final IJavaProject javaProject = BaseProjectHelper.getJavaProject(project); |
| if (javaProject != null) { |
| // Look up sub-types of each (new fragment class and compatibility fragment |
| // class, if any) and merge the two arrays - then create a scope from these |
| // elements. |
| IType[] viewTypes = new IType[0]; |
| IType fragmentType = javaProject.findType(CLASS_VIEW); |
| if (fragmentType != null) { |
| ITypeHierarchy hierarchy = |
| fragmentType.newTypeHierarchy(new NullProgressMonitor()); |
| viewTypes = hierarchy.getAllSubtypes(fragmentType); |
| } |
| scope = SearchEngine.createJavaSearchScope(viewTypes, IJavaSearchScope.SOURCES); |
| } |
| |
| Shell parent = AdtPlugin.getShell(); |
| final AtomicReference<String> returnValue = |
| new AtomicReference<String>(); |
| final AtomicReference<SelectionDialog> dialogHolder = |
| new AtomicReference<SelectionDialog>(); |
| final SelectionDialog dialog = JavaUI.createTypeDialog( |
| parent, |
| new ProgressMonitorDialog(parent), |
| scope, |
| IJavaElementSearchConstants.CONSIDER_CLASSES, false, |
| // Use ? as a default filter to fill dialog with matches |
| "?", //$NON-NLS-1$ |
| new TypeSelectionExtension() { |
| @Override |
| public Control createContentArea(Composite parentComposite) { |
| Composite composite = new Composite(parentComposite, SWT.NONE); |
| composite.setLayout(new GridLayout(1, false)); |
| Button button = new Button(composite, SWT.PUSH); |
| button.setText("Create New..."); |
| button.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| String fqcn = createNewCustomViewClass(javaProject); |
| if (fqcn != null) { |
| returnValue.set(fqcn); |
| dialogHolder.get().close(); |
| } |
| } |
| }); |
| return composite; |
| } |
| |
| @Override |
| public ITypeInfoFilterExtension getFilterExtension() { |
| return new ITypeInfoFilterExtension() { |
| @Override |
| public boolean select(ITypeInfoRequestor typeInfoRequestor) { |
| int modifiers = typeInfoRequestor.getModifiers(); |
| if (!Flags.isPublic(modifiers) |
| || Flags.isInterface(modifiers) |
| || Flags.isEnum(modifiers) |
| || Flags.isAbstract(modifiers)) { |
| return false; |
| } |
| return true; |
| } |
| }; |
| } |
| }); |
| dialogHolder.set(dialog); |
| |
| dialog.setTitle("Choose Custom View Class"); |
| dialog.setMessage("Select a Custom View class (? = any character, * = any string):"); |
| if (dialog.open() == IDialogConstants.CANCEL_ID) { |
| return null; |
| } |
| if (returnValue.get() != null) { |
| return returnValue.get(); |
| } |
| |
| Object[] types = dialog.getResult(); |
| if (types != null && types.length > 0) { |
| return ((IType) types[0]).getFullyQualifiedName(); |
| } |
| } catch (JavaModelException e) { |
| AdtPlugin.log(e, null); |
| } catch (CoreException e) { |
| AdtPlugin.log(e, null); |
| } |
| return null; |
| } |
| |
| @Override |
| public void redraw() { |
| mRulesEngine.getEditor().getCanvasControl().redraw(); |
| } |
| |
| @Override |
| public void layout() { |
| mRulesEngine.getEditor().recomputeLayout(); |
| } |
| |
| @Override |
| public Map<INode, Rect> measureChildren(@NonNull INode parent, |
| @Nullable IClientRulesEngine.AttributeFilter filter) { |
| RenderService renderService = RenderService.create(mRulesEngine.getEditor()); |
| Map<INode, Rect> map = renderService.measureChildren(parent, filter); |
| if (map == null) { |
| map = Collections.emptyMap(); |
| } |
| return map; |
| } |
| |
| @Override |
| public int pxToDp(int px) { |
| ConfigurationChooser chooser = mRulesEngine.getEditor().getConfigurationChooser(); |
| float dpi = chooser.getConfiguration().getDensity().getDpiValue(); |
| return (int) (px * 160 / dpi); |
| } |
| |
| @Override |
| public int dpToPx(int dp) { |
| ConfigurationChooser chooser = mRulesEngine.getEditor().getConfigurationChooser(); |
| float dpi = chooser.getConfiguration().getDensity().getDpiValue(); |
| return (int) (dp * dpi / 160); |
| } |
| |
| @Override |
| public int screenToLayout(int pixels) { |
| return (int) (pixels / mRulesEngine.getEditor().getCanvasControl().getScale()); |
| } |
| |
| private String createNewFragmentClass(IJavaProject javaProject) { |
| NewClassWizardPage page = new NewClassWizardPage(); |
| |
| IProject project = mRulesEngine.getProject(); |
| Sdk sdk = Sdk.getCurrent(); |
| if (sdk == null) { |
| return null; |
| } |
| IAndroidTarget target = sdk.getTarget(project); |
| String superClass; |
| if (target == null || target.getVersion().getApiLevel() < 11) { |
| superClass = CLASS_V4_FRAGMENT; |
| } else { |
| superClass = CLASS_FRAGMENT; |
| } |
| page.setSuperClass(superClass, true /* canBeModified */); |
| IPackageFragmentRoot root = ManifestInfo.getSourcePackageRoot(javaProject); |
| if (root != null) { |
| page.setPackageFragmentRoot(root, true /* canBeModified */); |
| } |
| ManifestInfo manifestInfo = ManifestInfo.get(project); |
| IPackageFragment pkg = manifestInfo.getPackageFragment(); |
| if (pkg != null) { |
| page.setPackageFragment(pkg, true /* canBeModified */); |
| } |
| OpenNewClassWizardAction action = new OpenNewClassWizardAction(); |
| action.setConfiguredWizardPage(page); |
| action.run(); |
| IType createdType = page.getCreatedType(); |
| if (createdType != null) { |
| return createdType.getFullyQualifiedName(); |
| } else { |
| return null; |
| } |
| } |
| |
| private String createNewCustomViewClass(IJavaProject javaProject) { |
| NewClassWizardPage page = new NewClassWizardPage(); |
| |
| IProject project = mRulesEngine.getProject(); |
| String superClass = CLASS_VIEW; |
| page.setSuperClass(superClass, true /* canBeModified */); |
| IPackageFragmentRoot root = ManifestInfo.getSourcePackageRoot(javaProject); |
| if (root != null) { |
| page.setPackageFragmentRoot(root, true /* canBeModified */); |
| } |
| ManifestInfo manifestInfo = ManifestInfo.get(project); |
| IPackageFragment pkg = manifestInfo.getPackageFragment(); |
| if (pkg != null) { |
| page.setPackageFragment(pkg, true /* canBeModified */); |
| } |
| OpenNewClassWizardAction action = new OpenNewClassWizardAction(); |
| action.setConfiguredWizardPage(page); |
| action.run(); |
| IType createdType = page.getCreatedType(); |
| if (createdType != null) { |
| return createdType.getFullyQualifiedName(); |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public @NonNull String getUniqueId(@NonNull String fqcn) { |
| UiDocumentNode root = mRulesEngine.getEditor().getModel(); |
| String prefix = fqcn.substring(fqcn.lastIndexOf('.') + 1); |
| prefix = Character.toLowerCase(prefix.charAt(0)) + prefix.substring(1); |
| return DescriptorsUtils.getFreeWidgetId(root, prefix); |
| } |
| |
| @Override |
| public @NonNull String getAppNameSpace() { |
| IProject project = mRulesEngine.getEditor().getProject(); |
| |
| ProjectState projectState = Sdk.getProjectState(project); |
| if (projectState != null && projectState.isLibrary()) { |
| return AUTO_URI; |
| } |
| |
| ManifestInfo info = ManifestInfo.get(project); |
| return URI_PREFIX + info.getPackage(); |
| } |
| } |