aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse
diff options
context:
space:
mode:
authorRaphael Moll <>2009-04-21 15:49:49 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-04-21 15:49:49 -0700
commit770ad198b7afb903162ce26823245d21ae81c884 (patch)
treef6c18a6af3d31a435b8bcec183814aee8b413ac0 /eclipse
parent8d23475b6a30797db56e0fe70cfcf32f77d8ab27 (diff)
downloadsdk-770ad198b7afb903162ce26823245d21ae81c884.zip
sdk-770ad198b7afb903162ce26823245d21ae81c884.tar.gz
sdk-770ad198b7afb903162ce26823245d21ae81c884.tar.bz2
AI 147264: am: CL 147262 ADT #1761055: Pre-select node types when adding node in manifest & resource based on context
Original author: raphael Merged from: //branches/cupcake/... Automated import of CL 147264
Diffstat (limited to 'eclipse')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java183
1 files changed, 178 insertions, 5 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
index 72fe060..36bd148 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/editors/ui/tree/NewItemSelectionDialog.java
@@ -17,10 +17,12 @@
package com.android.ide.eclipse.editors.ui.tree;
import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.editors.AndroidEditor;
import com.android.ide.eclipse.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.editors.layout.descriptors.ViewElementDescriptor;
import com.android.ide.eclipse.editors.uimodel.UiElementNode;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.viewers.ILabelProvider;
@@ -31,10 +33,16 @@ import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+import org.eclipse.ui.part.FileEditorInput;
import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Map.Entry;
/**
* A selection dialog to select the type of the new element node to
@@ -50,15 +58,25 @@ public class NewItemSelectionDialog extends AbstractElementListSelectionDialog {
private UiElementNode mChosenRootNode;
private UiElementNode mLocalRootNode;
/** The descriptor of the elements to be displayed as root in this tree view. All elements
- * of the same type in the root will be displayed. */
+ * of the same type in the root will be displayed. Can be null. */
private ElementDescriptor[] mDescriptorFilters;
+ /** The key for the {@link #setLastUsedXmlName(Object[])}. It corresponds to the full
+ * workspace path of the currently edited file, if this can be computed. This is computed
+ * by {@link #getLastUsedXmlName(UiElementNode)}, called from the constructor. */
+ private String mLastUsedKey;
+ /** A static map of known XML Names used for a given file. The map has full workspace
+ * paths as key and XML names as values. */
+ private static final Map<String, String> sLastUsedXmlName = new HashMap<String, String>();
+ /** The potential XML Name to initially select in the selection dialog. This is computed
+ * in the constructor and set by {@link #setInitialSelection(UiElementNode)}. */
+ private String mInitialXmlName;
/**
* Creates the new item selection dialog.
*
* @param shell The parent shell for the list.
* @param labelProvider ILabelProvider for the list.
- * @param descriptorFilters The element allows at the root of the tree
+ * @param descriptorFilters The element allows at the root of the tree. Can be null.
* @param ui_node The selected node, or null if none is selected.
* @param root_node The root of the Ui Tree, either the UiDocumentNode or a sub-node.
*/
@@ -109,6 +127,114 @@ public class NewItemSelectionDialog extends AbstractElementListSelectionDialog {
}
}
});
+
+ // Determine the initial selection using a couple heuristics.
+
+ // First check if we can get the last used node type for this file.
+ // The heuristic is that generally one keeps adding the same kind of items to the
+ // same file, so reusing the last used item type makes most sense.
+ String xmlName = getLastUsedXmlName(root_node);
+ if (xmlName == null) {
+ // Another heuristic is to find the most used item and default to that.
+ xmlName = getMostUsedXmlName(root_node);
+ }
+ if (xmlName == null) {
+ // Finally the last heuristic is to see if there's an item with a name
+ // similar to the edited file name.
+ xmlName = getLeafFileName(root_node);
+ }
+ // Set the potential name. Selecting the right item is done later by setInitialSelection().
+ mInitialXmlName = xmlName;
+ }
+
+ /**
+ * Returns a potential XML name based on the file name.
+ * The item name is marked with an asterisk to identify it as a partial match.
+ */
+ private String getLeafFileName(UiElementNode ui_node) {
+ if (ui_node != null) {
+ AndroidEditor editor = ui_node.getEditor();
+ if (editor != null) {
+ IEditorInput editorInput = editor.getEditorInput();
+ if (editorInput instanceof FileEditorInput) {
+ IFile f = ((FileEditorInput) editorInput).getFile();
+ if (f != null) {
+ String leafName = f.getFullPath().removeFileExtension().lastSegment();
+ return "*" + leafName; //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Given a potential non-null root node, this method looks for the currently edited
+ * file path and uses it as a key to retrieve the last used item for this file by this
+ * selection dialog. Returns null if nothing can be found, otherwise returns the string
+ * name of the item.
+ */
+ private String getLastUsedXmlName(UiElementNode ui_node) {
+ if (ui_node != null) {
+ AndroidEditor editor = ui_node.getEditor();
+ if (editor != null) {
+ IEditorInput editorInput = editor.getEditorInput();
+ if (editorInput instanceof FileEditorInput) {
+ IFile f = ((FileEditorInput) editorInput).getFile();
+ if (f != null) {
+ mLastUsedKey = f.getFullPath().toPortableString();
+
+ return sLastUsedXmlName.get(mLastUsedKey);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the last used item for this selection dialog for this file.
+ * @param objects The currently selected items. Only the first one is used if it is an
+ * {@link ElementDescriptor}.
+ */
+ private void setLastUsedXmlName(Object[] objects) {
+ if (mLastUsedKey != null &&
+ objects != null &&
+ objects.length > 0 &&
+ objects[0] instanceof ElementDescriptor) {
+ ElementDescriptor desc = (ElementDescriptor) objects[0];
+ sLastUsedXmlName.put(mLastUsedKey, desc.getXmlName());
+ }
+ }
+
+ /**
+ * Returns the most used sub-element name, if any, or null.
+ */
+ private String getMostUsedXmlName(UiElementNode ui_node) {
+ if (ui_node != null) {
+ TreeMap<String, Integer> counts = new TreeMap<String, Integer>();
+ int max = -1;
+
+ for (UiElementNode child : ui_node.getUiChildren()) {
+ String name = child.getDescriptor().getXmlName();
+ Integer i = counts.get(name);
+ int count = i == null ? 1 : i.intValue() + 1;
+ counts.put(name, count);
+ max = Math.max(max, count);
+ }
+
+ if (max > 0) {
+ // Find first key with this max and return it
+ for (Entry<String, Integer> entry : counts.entrySet()) {
+ if (entry.getValue().intValue() == max) {
+ return entry.getKey();
+ }
+ }
+ }
+ }
+ return null;
}
/**
@@ -126,6 +252,7 @@ public class NewItemSelectionDialog extends AbstractElementListSelectionDialog {
@Override
protected void computeResult() {
setResult(Arrays.asList(getSelectedElements()));
+ setLastUsedXmlName(getSelectedElements());
}
/**
@@ -152,11 +279,47 @@ public class NewItemSelectionDialog extends AbstractElementListSelectionDialog {
// Initialize the list state.
// This must be done after the filtered list as been created.
chooseNode(mChosenRootNode);
- setSelection(getInitialElementSelections().toArray());
+
+ // Set the initial selection
+ setInitialSelection(mChosenRootNode);
return contents;
}
/**
+ * Tries to set the initial selection based on the {@link #mInitialXmlName} computed
+ * in the constructor. The selection is only set if there's an element descriptor
+ * that matches the same exact XML name. When {@link #mInitialXmlName} starts with an
+ * asterisk, it means to do a partial case-insensitive match on the start of the
+ * strings.
+ */
+ private void setInitialSelection(UiElementNode rootNode) {
+ ElementDescriptor initialElement = null;
+
+ if (mInitialXmlName != null && mInitialXmlName.length() > 0) {
+ String name = mInitialXmlName;
+ boolean partial = name.startsWith("*"); //$NON-NLS-1$
+ if (partial) {
+ name = name.substring(1).toLowerCase();
+ }
+
+ for (ElementDescriptor desc : getAllowedDescriptors(rootNode)) {
+ if (!partial && desc.getXmlName().equals(name)) {
+ initialElement = desc;
+ break;
+ } else if (partial) {
+ String name2 = desc.getXmlLocalName().toLowerCase();
+ if (name.startsWith(name2) || name2.startsWith(name)) {
+ initialElement = desc;
+ break;
+ }
+ }
+ }
+ }
+
+ setSelection(initialElement == null ? null : new ElementDescriptor[] { initialElement });
+ }
+
+ /**
* Creates the message text widget and sets layout data.
* @param content the parent composite of the message area.
*/
@@ -217,13 +380,23 @@ public class NewItemSelectionDialog extends AbstractElementListSelectionDialog {
*/
private void chooseNode(UiElementNode ui_node) {
mChosenRootNode = ui_node;
+ setListElements(getAllowedDescriptors(ui_node));
+ }
+ /**
+ * Returns the list of {@link ElementDescriptor}s that can be added to the given
+ * UI node.
+ *
+ * @param ui_node The UI node to which element should be added. Cannot be null.
+ * @return A non-null array of {@link ElementDescriptor}. The array might be empty.
+ */
+ private ElementDescriptor[] getAllowedDescriptors(UiElementNode ui_node) {
if (ui_node == mLocalRootNode &&
mDescriptorFilters != null &&
mDescriptorFilters.length != 0) {
- setListElements(mDescriptorFilters);
+ return mDescriptorFilters;
} else {
- setListElements(ui_node.getDescriptor().getChildren());
+ return ui_node.getDescriptor().getChildren();
}
}
}