diff options
author | Raphael Moll <> | 2009-04-21 15:49:49 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-04-21 15:49:49 -0700 |
commit | 770ad198b7afb903162ce26823245d21ae81c884 (patch) | |
tree | f6c18a6af3d31a435b8bcec183814aee8b413ac0 /eclipse | |
parent | 8d23475b6a30797db56e0fe70cfcf32f77d8ab27 (diff) | |
download | sdk-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.java | 183 |
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(); } } } |