FileDocCategorySizeDatePackage
NewItemSelectionDialog.javaAPI DocAndroid 1.5 API16668Wed May 06 22:41:10 BST 2009com.android.ide.eclipse.editors.ui.tree

NewItemSelectionDialog

public class NewItemSelectionDialog extends org.eclipse.ui.dialogs.AbstractElementListSelectionDialog
A selection dialog to select the type of the new element node to create, either in the application node or the selected sub node.

Fields Summary
private com.android.ide.eclipse.editors.uimodel.UiElementNode
mSelectedUiNode
The UI node selected in the tree view before creating the new item selection dialog. Can be null -- which means new items must be created in the root_node.
private com.android.ide.eclipse.editors.uimodel.UiElementNode
mChosenRootNode
The root node chosen by the user, either root_node or the one passed to the constructor if not null
private com.android.ide.eclipse.editors.uimodel.UiElementNode
mLocalRootNode
private com.android.ide.eclipse.editors.descriptors.ElementDescriptor[]
mDescriptorFilters
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. Can be null.
private String
mLastUsedKey
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 static final Map
sLastUsedXmlName
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 String
mInitialXmlName
The potential XML Name to initially select in the selection dialog. This is computed in the constructor and set by {@link #setInitialSelection(UiElementNode)}.
Constructors Summary
public NewItemSelectionDialog(org.eclipse.swt.widgets.Shell shell, org.eclipse.jface.viewers.ILabelProvider labelProvider, com.android.ide.eclipse.editors.descriptors.ElementDescriptor[] descriptorFilters, com.android.ide.eclipse.editors.uimodel.UiElementNode ui_node, com.android.ide.eclipse.editors.uimodel.UiElementNode root_node)
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. 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.


                                                                     
        
             
             
              
        super(shell, labelProvider);
        mDescriptorFilters = descriptorFilters;
        mLocalRootNode = root_node;

        // Only accept the UI node if it is not the UI root node and it can have children.
        // If the node cannot have children, select its parent as a potential target.
        if (ui_node != null && ui_node != mLocalRootNode) {
            if (ui_node.getDescriptor().hasChildren()) {
                mSelectedUiNode = ui_node;
            } else {
                UiElementNode parent = ui_node.getUiParent();
                if (parent != null && parent != mLocalRootNode) {
                    mSelectedUiNode = parent;
                }
            }
        }
        
        setHelpAvailable(false);
        setMultipleSelection(false);
        
        setValidator(new ISelectionStatusValidator() {
            public IStatus validate(Object[] selection) {
                if (selection.length == 1 && selection[0] instanceof ViewElementDescriptor) {
                    return new Status(IStatus.OK, // severity
                            AdtPlugin.PLUGIN_ID, //plugin id
                            IStatus.OK, // code
                            ((ViewElementDescriptor) selection[0]).getCanonicalClassName(), //msg 
                            null); // exception
                } else if (selection.length == 1 && selection[0] instanceof ElementDescriptor) {
                    return new Status(IStatus.OK, // severity
                            AdtPlugin.PLUGIN_ID, //plugin id
                            IStatus.OK, // code
                            "", //$NON-NLS-1$ // msg
                            null); // exception
                } else {
                    return new Status(IStatus.ERROR, // severity
                            AdtPlugin.PLUGIN_ID, //plugin id
                            IStatus.ERROR, // code
                            "Invalid selection", // msg, translatable 
                            null); // exception
                }
            }
        });
        
        // 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;
    
Methods Summary
private voidchooseNode(com.android.ide.eclipse.editors.uimodel.UiElementNode ui_node)
Internal helper to remember the root node choosen by the user. It also sets the list view to the adequate list of children that can be added to the chosen root node. If the chosen root node is mLocalRootNode and a descriptor filter was specified when creating the master-detail part, we use this as the set of nodes that can be created on the root node.

param
ui_node The chosen root node, either mLocalRootNode or mSelectedUiNode.

        mChosenRootNode = ui_node;
        setListElements(getAllowedDescriptors(ui_node));
    
protected voidcomputeResult()
Internal helper to compute the result. Returns the selection from the list view, if any.

        setResult(Arrays.asList(getSelectedElements()));
        setLastUsedXmlName(getSelectedElements());
    
protected org.eclipse.swt.widgets.ControlcreateDialogArea(org.eclipse.swt.widgets.Composite parent)
Creates the dialog area. First add a radio area, which may be either 2 radio controls or just a message area if there's only one choice (the app root node). Then uses the default from the AbstractElementListSelectionDialog which is to add both a filter text and a filtered list. Adding both is necessary (since the base class accesses both internal directly fields without checking for null pointers.) Finally sets the initial selection list.

        Composite contents = (Composite) super.createDialogArea(parent);

        createRadioControl(contents);
        createFilterText(contents);
        createFilteredList(contents);

        // Initialize the list state.
        // This must be done after the filtered list as been created.
        chooseNode(mChosenRootNode);
        
        // Set the initial selection
        setInitialSelection(mChosenRootNode);
        return contents;
    
private org.eclipse.swt.widgets.CompositecreateRadioControl(org.eclipse.swt.widgets.Composite content)
Creates the message text widget and sets layout data.

param
content the parent composite of the message area.

        
        if (mSelectedUiNode != null) {
            Button radio1 = new Button(content, SWT.RADIO);
            radio1.setText(String.format("Create a new element at the top level, in %1$s.",
                    mLocalRootNode.getShortDescription()));

            Button radio2 = new Button(content, SWT.RADIO);
            radio2.setText(String.format("Create a new element in the selected element, %1$s.",
                    mSelectedUiNode.getBreadcrumbTrailDescription(false /* include_root */)));

            // Set the initial selection before adding the listeners
            // (they can't be run till the filtered list has been created)
            radio1.setSelection(false);
            radio2.setSelection(true);
            mChosenRootNode = mSelectedUiNode;
            
            radio1.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    super.widgetSelected(e);
                    chooseNode(mLocalRootNode);
                }
            });
            
            radio2.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    super.widgetSelected(e);
                    chooseNode(mSelectedUiNode);
                }
            });
        } else {
            setMessage(String.format("Create a new element at the top level, in %1$s.",
                    mLocalRootNode.getShortDescription()));
            createMessageArea(content);

            mChosenRootNode = mLocalRootNode;
        }
         
        return content;
    
private com.android.ide.eclipse.editors.descriptors.ElementDescriptor[]getAllowedDescriptors(com.android.ide.eclipse.editors.uimodel.UiElementNode 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.

        if (ui_node == mLocalRootNode && 
                mDescriptorFilters != null &&
                mDescriptorFilters.length != 0) {
            return mDescriptorFilters;
        } else {
            return ui_node.getDescriptor().getChildren();
        }
    
public com.android.ide.eclipse.editors.uimodel.UiElementNodegetChosenRootNode()

return
The root node selected by the user, either root node or the one passed to the constructor if not null.

        return mChosenRootNode;
    
private java.lang.StringgetLastUsedXmlName(com.android.ide.eclipse.editors.uimodel.UiElementNode ui_node)
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.

        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;
    
private java.lang.StringgetLeafFileName(com.android.ide.eclipse.editors.uimodel.UiElementNode ui_node)
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.

        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;
    
private java.lang.StringgetMostUsedXmlName(com.android.ide.eclipse.editors.uimodel.UiElementNode ui_node)
Returns the most used sub-element name, if any, or null.

        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;
    
private voidsetInitialSelection(com.android.ide.eclipse.editors.uimodel.UiElementNode rootNode)
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.

        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 });
    
private voidsetLastUsedXmlName(java.lang.Object[] objects)
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}.

        if (mLastUsedKey != null &&
                objects != null &&
                objects.length > 0 &&
                objects[0] instanceof ElementDescriptor) {
            ElementDescriptor desc = (ElementDescriptor) objects[0];
            sLastUsedXmlName.put(mLastUsedKey, desc.getXmlName());
        }