aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java517
1 files changed, 0 insertions, 517 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java
deleted file mode 100644
index 19d5e16b0..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/NodeProxy.java
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Copyright (C) 2009 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 com.android.annotations.NonNull;
-import com.android.annotations.Nullable;
-import com.android.ide.common.api.IAttributeInfo;
-import com.android.ide.common.api.INode;
-import com.android.ide.common.api.INodeHandler;
-import com.android.ide.common.api.Margins;
-import com.android.ide.common.api.Rect;
-import com.android.ide.common.resources.platform.AttributeInfo;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate;
-import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SimpleAttribute;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.SwtUtils;
-import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ViewHierarchy;
-import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-import com.android.ide.eclipse.adt.internal.project.SupportLibraryHelper;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.swt.graphics.Rectangle;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- *
- */
-public class NodeProxy implements INode {
- private static final Margins NO_MARGINS = new Margins(0, 0, 0, 0);
- private final UiViewElementNode mNode;
- private final Rect mBounds;
- private final NodeFactory mFactory;
- /** Map from URI to Map(key=>value) (where no namespace uses "" as a key) */
- private Map<String, Map<String, String>> mPendingAttributes;
-
- /**
- * Creates a new {@link INode} that wraps an {@link UiViewElementNode} that is
- * actually valid in the current UI/XML model. The view may not be part of the canvas
- * yet (e.g. if it has just been dynamically added and the canvas hasn't reloaded yet.)
- * <p/>
- * This method is package protected. To create a node, please use {@link NodeFactory} instead.
- *
- * @param uiNode The node to wrap.
- * @param bounds The bounds of a the view in the canvas. Must be either: <br/>
- * - a valid rect for a view that is actually in the canvas <br/>
- * - <b>*or*</b> null (or an invalid rect) for a view that has just been added dynamically
- * to the model. We never store a null bounds rectangle in the node, a null rectangle
- * will be converted to an invalid rectangle.
- * @param factory A {@link NodeFactory} to create unique children nodes.
- */
- /*package*/ NodeProxy(UiViewElementNode uiNode, Rectangle bounds, NodeFactory factory) {
- mNode = uiNode;
- mFactory = factory;
- if (bounds == null) {
- mBounds = new Rect();
- } else {
- mBounds = SwtUtils.toRect(bounds);
- }
- }
-
- @Override
- public @NonNull Rect getBounds() {
- return mBounds;
- }
-
- @Override
- public @NonNull Margins getMargins() {
- ViewHierarchy viewHierarchy = mFactory.getCanvas().getViewHierarchy();
- CanvasViewInfo view = viewHierarchy.findViewInfoFor(this);
- if (view != null) {
- Margins margins = view.getMargins();
- if (margins != null) {
- return margins;
- }
- }
-
- return NO_MARGINS;
- }
-
-
- @Override
- public int getBaseline() {
- ViewHierarchy viewHierarchy = mFactory.getCanvas().getViewHierarchy();
- CanvasViewInfo view = viewHierarchy.findViewInfoFor(this);
- if (view != null) {
- return view.getBaseline();
- }
-
- return -1;
- }
-
- /**
- * Updates the bounds of this node proxy. Bounds cannot be null, but it can be invalid.
- * This is a package-protected method, only the {@link NodeFactory} uses this method.
- */
- /*package*/ void setBounds(Rectangle bounds) {
- SwtUtils.set(mBounds, bounds);
- }
-
- /**
- * Returns the {@link UiViewElementNode} corresponding to this
- * {@link NodeProxy}.
- *
- * @return The {@link UiViewElementNode} corresponding to this
- * {@link NodeProxy}
- */
- public UiViewElementNode getNode() {
- return mNode;
- }
-
- @Override
- public @NonNull String getFqcn() {
- if (mNode != null) {
- ElementDescriptor desc = mNode.getDescriptor();
- if (desc instanceof ViewElementDescriptor) {
- return ((ViewElementDescriptor) desc).getFullClassName();
- }
- }
-
- return "";
- }
-
-
- // ---- Hierarchy handling ----
-
-
- @Override
- public INode getRoot() {
- if (mNode != null) {
- UiElementNode p = mNode.getUiRoot();
- // The node root should be a document. Instead what we really mean to
- // return is the top level view element.
- if (p instanceof UiDocumentNode) {
- List<UiElementNode> children = p.getUiChildren();
- if (children.size() > 0) {
- p = children.get(0);
- }
- }
-
- // Cope with a badly structured XML layout
- while (p != null && !(p instanceof UiViewElementNode)) {
- p = p.getUiNextSibling();
- }
-
- if (p == mNode) {
- return this;
- }
- if (p instanceof UiViewElementNode) {
- return mFactory.create((UiViewElementNode) p);
- }
- }
-
- return null;
- }
-
- @Override
- public INode getParent() {
- if (mNode != null) {
- UiElementNode p = mNode.getUiParent();
- if (p instanceof UiViewElementNode) {
- return mFactory.create((UiViewElementNode) p);
- }
- }
-
- return null;
- }
-
- @Override
- public @NonNull INode[] getChildren() {
- if (mNode != null) {
- List<UiElementNode> uiChildren = mNode.getUiChildren();
- List<INode> nodes = new ArrayList<INode>(uiChildren.size());
- for (UiElementNode uiChild : uiChildren) {
- if (uiChild instanceof UiViewElementNode) {
- nodes.add(mFactory.create((UiViewElementNode) uiChild));
- }
- }
-
- return nodes.toArray(new INode[nodes.size()]);
- }
-
- return new INode[0];
- }
-
-
- // ---- XML Editing ---
-
- @Override
- public void editXml(@NonNull String undoName, final @NonNull INodeHandler c) {
- final AndroidXmlEditor editor = mNode.getEditor();
-
- if (editor != null) {
- // Create an undo edit XML wrapper, which takes a runnable
- editor.wrapUndoEditXmlModel(
- undoName,
- new Runnable() {
- @Override
- public void run() {
- // Here editor.isEditXmlModelPending returns true and it
- // is safe to edit the model using any method from INode.
-
- // Finally execute the closure that will act on the XML
- c.handle(NodeProxy.this);
- applyPendingChanges();
- }
- });
- }
- }
-
- private void checkEditOK() {
- final AndroidXmlEditor editor = mNode.getEditor();
- if (!editor.isEditXmlModelPending()) {
- throw new RuntimeException("Error: XML edit call without using INode.editXml!");
- }
- }
-
- @Override
- public @NonNull INode appendChild(@NonNull String viewFqcn) {
- return insertOrAppend(viewFqcn, -1);
- }
-
- @Override
- public @NonNull INode insertChildAt(@NonNull String viewFqcn, int index) {
- return insertOrAppend(viewFqcn, index);
- }
-
- @Override
- public void removeChild(@NonNull INode node) {
- checkEditOK();
-
- ((NodeProxy) node).mNode.deleteXmlNode();
- }
-
- private INode insertOrAppend(String viewFqcn, int index) {
- checkEditOK();
-
- AndroidXmlEditor editor = mNode.getEditor();
- if (editor != null) {
- // Possibly replace the tag with a compatibility version if the
- // minimum SDK requires it
- IProject project = editor.getProject();
- if (project != null) {
- viewFqcn = SupportLibraryHelper.getTagFor(project, viewFqcn);
- }
- }
-
- // Find the descriptor for this FQCN
- ViewElementDescriptor vd = getFqcnViewDescriptor(viewFqcn);
- if (vd == null) {
- warnPrintf("Can't create a new %s element", viewFqcn);
- return null;
- }
-
- final UiElementNode uiNew;
- if (index == -1) {
- // Append at the end.
- uiNew = mNode.appendNewUiChild(vd);
- } else {
- // Insert at the requested position or at the end.
- int n = mNode.getUiChildren().size();
- if (index < 0 || index >= n) {
- uiNew = mNode.appendNewUiChild(vd);
- } else {
- uiNew = mNode.insertNewUiChild(index, vd);
- }
- }
-
- // Set default attributes -- but only for new widgets (not when moving or copying)
- RulesEngine engine = null;
- LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(editor);
- if (delegate != null) {
- engine = delegate.getRulesEngine();
- }
- if (engine == null || engine.getInsertType().isCreate()) {
- // TODO: This should probably use IViewRule#getDefaultAttributes() at some point
- DescriptorsUtils.setDefaultLayoutAttributes(uiNew, false /*updateLayout*/);
- }
-
- Node xmlNode = uiNew.createXmlNode();
-
- if (!(uiNew instanceof UiViewElementNode) || xmlNode == null) {
- // Both things are not supposed to happen. When they do, we're in big trouble.
- // We don't really know how to revert the state at this point and the UI model is
- // now out of sync with the XML model.
- // Panic ensues.
- // The best bet is to abort now. The edit wrapper will release the edit and the
- // XML/UI should get reloaded properly (with a likely invalid XML.)
- warnPrintf("Failed to create a new %s element", viewFqcn);
- throw new RuntimeException("XML node creation failed."); //$NON-NLS-1$
- }
-
- UiViewElementNode uiNewView = (UiViewElementNode) uiNew;
- NodeProxy newNode = mFactory.create(uiNewView);
-
- if (engine != null) {
- engine.callCreateHooks(editor, this, newNode, null);
- }
-
- return newNode;
- }
-
- @Override
- public boolean setAttribute(
- @Nullable String uri,
- @NonNull String name,
- @Nullable String value) {
- checkEditOK();
- UiAttributeNode attr = mNode.setAttributeValue(name, uri, value, true /* override */);
-
- if (uri == null) {
- uri = ""; //$NON-NLS-1$
- }
-
- Map<String, String> map = null;
- if (mPendingAttributes == null) {
- // Small initial size: we don't expect many different namespaces
- mPendingAttributes = new HashMap<String, Map<String, String>>(3);
- } else {
- map = mPendingAttributes.get(uri);
- }
- if (map == null) {
- map = new HashMap<String, String>();
- mPendingAttributes.put(uri, map);
- }
- map.put(name, value);
-
- return attr != null;
- }
-
- @Override
- public String getStringAttr(@Nullable String uri, @NonNull String attrName) {
- UiElementNode uiNode = mNode;
-
- if (attrName == null) {
- return null;
- }
-
- if (mPendingAttributes != null) {
- Map<String, String> map = mPendingAttributes.get(uri == null ? "" : uri); //$NON-NLS-1$
- if (map != null) {
- String value = map.get(attrName);
- if (value != null) {
- return value;
- }
- }
- }
-
- if (uiNode.getXmlNode() != null) {
- Node xmlNode = uiNode.getXmlNode();
- if (xmlNode != null) {
- NamedNodeMap nodeAttributes = xmlNode.getAttributes();
- if (nodeAttributes != null) {
- Node attr = nodeAttributes.getNamedItemNS(uri, attrName);
- if (attr != null) {
- return attr.getNodeValue();
- }
- }
- }
- }
- return null;
- }
-
- @Override
- public IAttributeInfo getAttributeInfo(@Nullable String uri, @NonNull String attrName) {
- UiElementNode uiNode = mNode;
-
- if (attrName == null) {
- return null;
- }
-
- for (AttributeDescriptor desc : uiNode.getAttributeDescriptors()) {
- String dUri = desc.getNamespaceUri();
- String dName = desc.getXmlLocalName();
- if ((uri == null && dUri == null) || (uri != null && uri.equals(dUri))) {
- if (attrName.equals(dName)) {
- return desc.getAttributeInfo();
- }
- }
- }
-
- return null;
- }
-
- @Override
- public @NonNull IAttributeInfo[] getDeclaredAttributes() {
-
- AttributeDescriptor[] descs = mNode.getAttributeDescriptors();
- int n = descs.length;
- IAttributeInfo[] infos = new AttributeInfo[n];
-
- for (int i = 0; i < n; i++) {
- infos[i] = descs[i].getAttributeInfo();
- }
-
- return infos;
- }
-
- @Override
- public @NonNull List<String> getAttributeSources() {
- ElementDescriptor descriptor = mNode.getDescriptor();
- if (descriptor instanceof ViewElementDescriptor) {
- return ((ViewElementDescriptor) descriptor).getAttributeSources();
- } else {
- return Collections.emptyList();
- }
- }
-
- @Override
- public @NonNull IAttribute[] getLiveAttributes() {
- UiElementNode uiNode = mNode;
-
- if (uiNode.getXmlNode() != null) {
- Node xmlNode = uiNode.getXmlNode();
- if (xmlNode != null) {
- NamedNodeMap nodeAttributes = xmlNode.getAttributes();
- if (nodeAttributes != null) {
-
- int n = nodeAttributes.getLength();
- IAttribute[] result = new IAttribute[n];
- for (int i = 0; i < n; i++) {
- Node attr = nodeAttributes.item(i);
- String uri = attr.getNamespaceURI();
- String name = attr.getLocalName();
- String value = attr.getNodeValue();
-
- result[i] = new SimpleAttribute(uri, name, value);
- }
- return result;
- }
- }
- }
-
- return new IAttribute[0];
-
- }
-
- @Override
- public String toString() {
- return "NodeProxy [node=" + mNode + ", bounds=" + mBounds + "]";
- }
-
- // --- internal helpers ---
-
- /**
- * Helper methods that returns a {@link ViewElementDescriptor} for the requested FQCN.
- * Will return null if we can't find that FQCN or we lack the editor/data/descriptors info
- * (which shouldn't really happen since at this point the SDK should be fully loaded and
- * isn't reloading, or we wouldn't be here editing XML for a layout rule.)
- */
- private ViewElementDescriptor getFqcnViewDescriptor(String fqcn) {
- LayoutEditorDelegate delegate = LayoutEditorDelegate.fromEditor(mNode.getEditor());
- if (delegate != null) {
- return delegate.getFqcnViewDescriptor(fqcn);
- }
-
- return null;
- }
-
- private void warnPrintf(String msg, Object...params) {
- AdtPlugin.printToConsole(
- mNode == null ? "" : mNode.getDescriptor().getXmlLocalName(),
- String.format(msg, params)
- );
- }
-
- /**
- * If there are any pending changes in these nodes, apply them now
- *
- * @return true if any modifications were made
- */
- public boolean applyPendingChanges() {
- boolean modified = false;
-
- // Flush all pending attributes
- if (mPendingAttributes != null) {
- mNode.commitDirtyAttributesToXml();
- modified = true;
- mPendingAttributes = null;
-
- }
- for (INode child : getChildren()) {
- modified |= ((NodeProxy) child).applyPendingChanges();
- }
-
- return modified;
- }
-}