aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui
diff options
context:
space:
mode:
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/EditableDialogCellEditor.java490
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ErrorImageComposite.java72
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/FlagValueCellEditor.java58
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ListValueCellEditor.java76
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ResourceValueCellEditor.java59
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/SectionHelper.java364
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/TextValueCellEditor.java43
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/UiElementPart.java284
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/CopyCutAction.java221
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/ICommitXml.java28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/NewItemSelectionDialog.java415
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java129
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiActions.java598
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java494
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeContentProvider.java120
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java106
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java946
17 files changed, 0 insertions, 4503 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/EditableDialogCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/EditableDialogCellEditor.java
deleted file mode 100644
index baf8a1039..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/EditableDialogCellEditor.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright (C) 2008 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.ui;
-
-import com.android.SdkConstants;
-
-import org.eclipse.core.runtime.Assert;
-import org.eclipse.jface.viewers.DialogCellEditor;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.FocusAdapter;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.KeyAdapter;
-import org.eclipse.swt.events.KeyEvent;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.TraverseEvent;
-import org.eclipse.swt.events.TraverseListener;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Text;
-
-import java.text.MessageFormat;
-
-/**
- * Custom DialogCellEditor, replacing the Label with an editable {@link Text} widget.
- * <p/>Also set the button to {@link SWT#FLAT} to make sure it looks good on MacOS X.
- * <p/>Most of the code comes from TextCellEditor.
- */
-public abstract class EditableDialogCellEditor extends DialogCellEditor {
-
- private Text text;
-
- private ModifyListener modifyListener;
-
- /**
- * State information for updating action enablement
- */
- private boolean isSelection = false;
-
- private boolean isDeleteable = false;
-
- private boolean isSelectable = false;
-
- EditableDialogCellEditor(Composite parent) {
- super(parent);
- }
-
- /*
- * Re-implement this method only to properly set the style in the button, or it won't look
- * good in MacOS X
- */
- @Override
- protected Button createButton(Composite parent) {
- Button result = new Button(parent, SWT.DOWN | SWT.FLAT);
- result.setText("..."); //$NON-NLS-1$
- return result;
- }
-
-
- @Override
- protected Control createContents(Composite cell) {
- text = new Text(cell, SWT.SINGLE);
- text.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetDefaultSelected(SelectionEvent e) {
- handleDefaultSelection(e);
- }
- });
- text.addKeyListener(new KeyAdapter() {
- // hook key pressed - see PR 14201
- @Override
- public void keyPressed(KeyEvent e) {
- keyReleaseOccured(e);
-
- // as a result of processing the above call, clients may have
- // disposed this cell editor
- if ((getControl() == null) || getControl().isDisposed()) {
- return;
- }
- checkSelection(); // see explanation below
- checkDeleteable();
- checkSelectable();
- }
- });
- text.addTraverseListener(new TraverseListener() {
- @Override
- public void keyTraversed(TraverseEvent e) {
- if (e.detail == SWT.TRAVERSE_ESCAPE
- || e.detail == SWT.TRAVERSE_RETURN) {
- e.doit = false;
- }
- }
- });
- // We really want a selection listener but it is not supported so we
- // use a key listener and a mouse listener to know when selection changes
- // may have occurred
- text.addMouseListener(new MouseAdapter() {
- @Override
- public void mouseUp(MouseEvent e) {
- checkSelection();
- checkDeleteable();
- checkSelectable();
- }
- });
- text.addFocusListener(new FocusAdapter() {
- @Override
- public void focusLost(FocusEvent e) {
- EditableDialogCellEditor.this.focusLost();
- }
- });
- text.setFont(cell.getFont());
- text.setBackground(cell.getBackground());
- text.setText("");//$NON-NLS-1$
- text.addModifyListener(getModifyListener());
- return text;
- }
-
- /**
- * Checks to see if the "deletable" state (can delete/
- * nothing to delete) has changed and if so fire an
- * enablement changed notification.
- */
- private void checkDeleteable() {
- boolean oldIsDeleteable = isDeleteable;
- isDeleteable = isDeleteEnabled();
- if (oldIsDeleteable != isDeleteable) {
- fireEnablementChanged(DELETE);
- }
- }
-
- /**
- * Checks to see if the "selectable" state (can select)
- * has changed and if so fire an enablement changed notification.
- */
- private void checkSelectable() {
- boolean oldIsSelectable = isSelectable;
- isSelectable = isSelectAllEnabled();
- if (oldIsSelectable != isSelectable) {
- fireEnablementChanged(SELECT_ALL);
- }
- }
-
- /**
- * Checks to see if the selection state (selection /
- * no selection) has changed and if so fire an
- * enablement changed notification.
- */
- private void checkSelection() {
- boolean oldIsSelection = isSelection;
- isSelection = text.getSelectionCount() > 0;
- if (oldIsSelection != isSelection) {
- fireEnablementChanged(COPY);
- fireEnablementChanged(CUT);
- }
- }
-
- /* (non-Javadoc)
- * Method declared on CellEditor.
- */
- @Override
- protected void doSetFocus() {
- if (text != null) {
- text.selectAll();
- text.setFocus();
- checkSelection();
- checkDeleteable();
- checkSelectable();
- }
- }
-
- /*
- * (non-Javadoc)
- * @see org.eclipse.jface.viewers.DialogCellEditor#updateContents(java.lang.Object)
- */
- @Override
- protected void updateContents(Object value) {
- Assert.isTrue(text != null && (value == null || (value instanceof String)));
- if (value != null) {
- text.removeModifyListener(getModifyListener());
- text.setText((String) value);
- text.addModifyListener(getModifyListener());
- }
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of
- * this <code>CellEditor</code> framework method returns
- * the text string.
- *
- * @return the text string
- */
- @Override
- protected Object doGetValue() {
- return text.getText();
- }
-
-
- /**
- * Processes a modify event that occurred in this text cell editor.
- * This framework method performs validation and sets the error message
- * accordingly, and then reports a change via <code>fireEditorValueChanged</code>.
- * Subclasses should call this method at appropriate times. Subclasses
- * may extend or reimplement.
- *
- * @param e the SWT modify event
- */
- protected void editOccured(ModifyEvent e) {
- String value = text.getText();
- if (value == null) {
- value = "";//$NON-NLS-1$
- }
- Object typedValue = value;
- boolean oldValidState = isValueValid();
- boolean newValidState = isCorrect(typedValue);
-
- if (!newValidState) {
- // try to insert the current value into the error message.
- setErrorMessage(MessageFormat.format(getErrorMessage(),
- new Object[] { value }));
- }
- valueChanged(oldValidState, newValidState);
- }
-
- /**
- * Return the modify listener.
- */
- private ModifyListener getModifyListener() {
- if (modifyListener == null) {
- modifyListener = new ModifyListener() {
- @Override
- public void modifyText(ModifyEvent e) {
- editOccured(e);
- }
- };
- }
- return modifyListener;
- }
-
- /**
- * Handles a default selection event from the text control by applying the editor
- * value and deactivating this cell editor.
- *
- * @param event the selection event
- *
- * @since 3.0
- */
- protected void handleDefaultSelection(SelectionEvent event) {
- // same with enter-key handling code in keyReleaseOccured(e);
- fireApplyEditorValue();
- deactivate();
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method returns <code>true</code> if
- * the current selection is not empty.
- */
- @Override
- public boolean isCopyEnabled() {
- if (text == null || text.isDisposed()) {
- return false;
- }
- return text.getSelectionCount() > 0;
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method returns <code>true</code> if
- * the current selection is not empty.
- */
- @Override
- public boolean isCutEnabled() {
- if (text == null || text.isDisposed()) {
- return false;
- }
- return text.getSelectionCount() > 0;
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method returns <code>true</code>
- * if there is a selection or if the caret is not positioned
- * at the end of the text.
- */
- @Override
- public boolean isDeleteEnabled() {
- if (text == null || text.isDisposed()) {
- return false;
- }
- return text.getSelectionCount() > 0
- || text.getCaretPosition() < text.getCharCount();
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method always returns <code>true</code>.
- */
- @Override
- public boolean isPasteEnabled() {
- if (text == null || text.isDisposed()) {
- return false;
- }
- return true;
- }
-
- /**
- * Check if save all is enabled
- * @return true if it is
- */
- public boolean isSaveAllEnabled() {
- if (text == null || text.isDisposed()) {
- return false;
- }
- return true;
- }
-
- /**
- * Returns <code>true</code> if this cell editor is
- * able to perform the select all action.
- * <p>
- * This default implementation always returns
- * <code>false</code>.
- * </p>
- * <p>
- * Subclasses may override
- * </p>
- * @return <code>true</code> if select all is possible,
- * <code>false</code> otherwise
- */
- @Override
- public boolean isSelectAllEnabled() {
- if (text == null || text.isDisposed()) {
- return false;
- }
- return text.getCharCount() > 0;
- }
-
- /**
- * Processes a key release event that occurred in this cell editor.
- * <p>
- * The <code>TextCellEditor</code> implementation of this framework method
- * ignores when the RETURN key is pressed since this is handled in
- * <code>handleDefaultSelection</code>.
- * An exception is made for Ctrl+Enter for multi-line texts, since
- * a default selection event is not sent in this case.
- * </p>
- *
- * @param keyEvent the key event
- */
- @Override
- protected void keyReleaseOccured(KeyEvent keyEvent) {
- if (keyEvent.character == '\r') { // Return key
- // Enter is handled in handleDefaultSelection.
- // Do not apply the editor value in response to an Enter key event
- // since this can be received from the IME when the intent is -not-
- // to apply the value.
- // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control
- //
- // An exception is made for Ctrl+Enter for multi-line texts, since
- // a default selection event is not sent in this case.
- if (text != null && !text.isDisposed()
- && (text.getStyle() & SWT.MULTI) != 0) {
- if ((keyEvent.stateMask & SWT.CTRL) != 0) {
- super.keyReleaseOccured(keyEvent);
- }
- }
- return;
- }
- super.keyReleaseOccured(keyEvent);
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method copies the
- * current selection to the clipboard.
- */
- @Override
- public void performCopy() {
- text.copy();
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method cuts the
- * current selection to the clipboard.
- */
- @Override
- public void performCut() {
- text.cut();
- checkSelection();
- checkDeleteable();
- checkSelectable();
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method deletes the
- * current selection or, if there is no selection,
- * the character next character from the current position.
- */
- @Override
- public void performDelete() {
- if (text.getSelectionCount() > 0) {
- // remove the contents of the current selection
- text.insert(""); //$NON-NLS-1$
- } else {
- // remove the next character
- int pos = text.getCaretPosition();
- if (pos < text.getCharCount()) {
- text.setSelection(pos, pos + 1);
- text.insert(""); //$NON-NLS-1$
- }
- }
- checkSelection();
- checkDeleteable();
- checkSelectable();
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method pastes the
- * the clipboard contents over the current selection.
- */
- @Override
- public void performPaste() {
- text.paste();
- checkSelection();
- checkDeleteable();
- checkSelectable();
- }
-
- /**
- * The <code>TextCellEditor</code> implementation of this
- * <code>CellEditor</code> method selects all of the
- * current text.
- */
- @Override
- public void performSelectAll() {
- text.selectAll();
- checkSelection();
- checkDeleteable();
- }
-
- @Override
- protected void focusLost() {
- if (SdkConstants.currentPlatform() == SdkConstants.PLATFORM_LINUX) {
- // On Linux, something about the order of focus event delivery prevents the
- // callback on the "..." button to be invoked, which means the
- // customizer dialog never shows up (see issue #18348).
- // (Note that simply trying to Display.asyncRun() the super.focusLost()
- // method does not work.)
- //
- // We can work around this by not deactivating on a focus loss.
- // This means that in some cases the cell editor will still be
- // shown in the property sheet, but I've tested that the values
- // are all committed as before. This is better than having a non-operational
- // customizer, but since this issue only happens on Linux the workaround
- // is only done on Linux such that on other platforms we deactivate
- // immediately on focus loss.
- //
- if (isActivated()) {
- fireApplyEditorValue();
- // super.focusLost calls the following which we're deliberately
- // suppressing here:
- // deactivate();
- }
- } else {
- super.focusLost();
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ErrorImageComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ErrorImageComposite.java
deleted file mode 100644
index 7085e5d50..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ErrorImageComposite.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.android.ide.eclipse.adt.internal.editors.ui;
-
-import static org.eclipse.ui.ISharedImages.IMG_DEC_FIELD_ERROR;
-import static org.eclipse.ui.ISharedImages.IMG_DEC_FIELD_WARNING;
-import static org.eclipse.ui.ISharedImages.IMG_OBJS_ERROR_TSK;
-import static org.eclipse.ui.ISharedImages.IMG_OBJS_WARN_TSK;
-
-import org.eclipse.jface.resource.CompositeImageDescriptor;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.jface.viewers.DecorationOverlayIcon;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-
-/**
- * ImageDescriptor that adds a error marker.
- * Based on {@link DecorationOverlayIcon} only available in Eclipse 3.3
- */
-public class ErrorImageComposite extends CompositeImageDescriptor {
-
- private Image mBaseImage;
- private ImageDescriptor mErrorImageDescriptor;
- private Point mSize;
-
- /**
- * Creates a new {@link ErrorImageComposite}
- *
- * @param baseImage the base image to overlay an icon on top of
- */
- public ErrorImageComposite(Image baseImage) {
- this(baseImage, false);
- }
-
- /**
- * Creates a new {@link ErrorImageComposite}
- *
- * @param baseImage the base image to overlay an icon on top of
- * @param warning if true, add a warning icon, otherwise an error icon
- */
- public ErrorImageComposite(Image baseImage, boolean warning) {
- mBaseImage = baseImage;
- ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
- mErrorImageDescriptor = sharedImages.getImageDescriptor(
- warning ? IMG_DEC_FIELD_WARNING : IMG_DEC_FIELD_ERROR);
- if (mErrorImageDescriptor == null) {
- mErrorImageDescriptor = sharedImages.getImageDescriptor(
- warning ? IMG_OBJS_WARN_TSK : IMG_OBJS_ERROR_TSK);
- }
- mSize = new Point(baseImage.getBounds().width, baseImage.getBounds().height);
- }
-
- @Override
- protected void drawCompositeImage(int width, int height) {
- ImageData baseData = mBaseImage.getImageData();
- drawImage(baseData, 0, 0);
-
- ImageData overlayData = mErrorImageDescriptor.getImageData();
- if (overlayData.width == baseData.width && overlayData.height == baseData.height) {
- overlayData = overlayData.scaledTo(14, 14);
- drawImage(overlayData, -3, mSize.y - overlayData.height + 3);
- } else {
- drawImage(overlayData, 0, mSize.y - overlayData.height);
- }
- }
-
- @Override
- protected Point getSize() {
- return mSize;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/FlagValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/FlagValueCellEditor.java
deleted file mode 100644
index 2a1bc36b5..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/FlagValueCellEditor.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2008 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.ui;
-
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiFlagAttributeNode;
-
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-
-/**
- * DialogCellEditor able to receive a {@link UiFlagAttributeNode} in the {@link #setValue(Object)}
- * method.
- * <p/>The dialog box opened is the same as the one in the ui created by
- * {@link UiFlagAttributeNode#createUiControl(Composite, org.eclipse.ui.forms.IManagedForm)}
- */
-public class FlagValueCellEditor extends EditableDialogCellEditor {
-
- private UiFlagAttributeNode mUiFlagAttribute;
-
- public FlagValueCellEditor(Composite parent) {
- super(parent);
- }
-
- @Override
- protected Object openDialogBox(Control cellEditorWindow) {
- if (mUiFlagAttribute != null) {
- String currentValue = (String)getValue();
- return mUiFlagAttribute.showDialog(cellEditorWindow.getShell(), currentValue);
- }
-
- return null;
- }
-
- @Override
- protected void doSetValue(Object value) {
- if (value instanceof UiFlagAttributeNode) {
- mUiFlagAttribute = (UiFlagAttributeNode)value;
- super.doSetValue(mUiFlagAttribute.getCurrentValue());
- return;
- }
-
- super.doSetValue(value);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ListValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ListValueCellEditor.java
deleted file mode 100644
index 0c780a8c7..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ListValueCellEditor.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2008 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.ui;
-
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiListAttributeNode;
-
-import org.eclipse.jface.viewers.ComboBoxCellEditor;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.custom.CCombo;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-
-/**
- * ComboBoxCellEditor able to receive a {@link UiListAttributeNode} in the {@link #setValue(Object)}
- * method, and returning a {@link String} in {@link #getValue()} instead of an {@link Integer}.
- */
-public class ListValueCellEditor extends ComboBoxCellEditor {
- private String[] mItems;
- private CCombo mCombo;
-
- public ListValueCellEditor(Composite parent) {
- super(parent, new String[0], SWT.DROP_DOWN);
- }
-
- @Override
- protected Control createControl(Composite parent) {
- mCombo = (CCombo) super.createControl(parent);
- return mCombo;
- }
-
- @Override
- protected void doSetValue(Object value) {
- if (value instanceof UiListAttributeNode) {
- UiListAttributeNode uiListAttribute = (UiListAttributeNode)value;
-
- // set the possible values in the combo
- String[] items = uiListAttribute.getPossibleValues(null);
- mItems = new String[items.length];
- System.arraycopy(items, 0, mItems, 0, items.length);
- setItems(mItems);
-
- // now edit the current value of the attribute
- String attrValue = uiListAttribute.getCurrentValue();
- mCombo.setText(attrValue);
-
- return;
- }
-
- // default behavior
- super.doSetValue(value);
- }
-
- @Override
- protected Object doGetValue() {
- String comboText = mCombo.getText();
- if (comboText == null) {
- return ""; //$NON-NLS-1$
- }
- return comboText;
- }
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ResourceValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ResourceValueCellEditor.java
deleted file mode 100644
index 8efe294b1..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/ResourceValueCellEditor.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2008 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.ui;
-
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiFlagAttributeNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiResourceAttributeNode;
-
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-
-/**
- * DialogCellEditor able to receive a {@link UiFlagAttributeNode} in the {@link #setValue(Object)}
- * method.
- * <p/>The dialog box opened is the same as the one in the ui created by
- * {@link UiFlagAttributeNode#createUiControl(Composite, org.eclipse.ui.forms.IManagedForm)}
- */
-public class ResourceValueCellEditor extends EditableDialogCellEditor {
-
- private UiResourceAttributeNode mUiResourceAttribute;
-
- public ResourceValueCellEditor(Composite parent) {
- super(parent);
- }
-
- @Override
- protected Object openDialogBox(Control cellEditorWindow) {
- if (mUiResourceAttribute != null) {
- String currentValue = (String)getValue();
- return mUiResourceAttribute.showDialog(cellEditorWindow.getShell(), currentValue);
- }
-
- return null;
- }
-
- @Override
- protected void doSetValue(Object value) {
- if (value instanceof UiResourceAttributeNode) {
- mUiResourceAttribute = (UiResourceAttributeNode)value;
- super.doSetValue(mUiResourceAttribute.getCurrentValue());
- return;
- }
-
- super.doSetValue(value);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/SectionHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/SectionHelper.java
deleted file mode 100644
index fdb5d8292..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/SectionHelper.java
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (C) 2007 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.ui;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-
-import org.eclipse.jface.text.DefaultInformationControl;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.MouseEvent;
-import org.eclipse.swt.events.MouseTrackListener;
-import org.eclipse.swt.graphics.Point;
-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.Label;
-import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.forms.SectionPart;
-import org.eclipse.ui.forms.widgets.FormText;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.Section;
-import org.eclipse.ui.forms.widgets.TableWrapData;
-import org.eclipse.ui.forms.widgets.TableWrapLayout;
-
-import java.lang.reflect.Method;
-
-/**
- * Helper for the AndroidManifest form editor.
- *
- * Helps create a new SectionPart with sensible default parameters,
- * create default layout or add typical widgets.
- *
- * IMPORTANT: This is NOT a generic class. It makes a lot of assumptions on the
- * UI as used by the form editor for the AndroidManifest.
- *
- * TODO: Consider moving to a common package.
- */
-public final class SectionHelper {
-
- /**
- * Utility class that derives from SectionPart, constructs the Section with
- * sensible defaults (with a title and a description) and provide some shorthand
- * methods for creating typically UI (label and text, form text.)
- */
- static public class ManifestSectionPart extends SectionPart {
-
- /**
- * Construct a SectionPart that uses a title bar and a description.
- * It's up to the caller to call setText() and setDescription().
- * <p/>
- * The section style includes a description and a title bar by default.
- *
- * @param body The parent (e.g. FormPage body)
- * @param toolkit Form Toolkit
- */
- public ManifestSectionPart(Composite body, FormToolkit toolkit) {
- this(body, toolkit, 0, false);
- }
-
- /**
- * Construct a SectionPart that uses a title bar and a description.
- * It's up to the caller to call setText() and setDescription().
- * <p/>
- * The section style includes a description and a title bar by default.
- * You can add extra styles, like Section.TWISTIE.
- *
- * @param body The parent (e.g. FormPage body).
- * @param toolkit Form Toolkit.
- * @param extra_style Extra styles (on top of description and title bar).
- * @param use_description True if the Section.DESCRIPTION style should be added.
- */
- public ManifestSectionPart(Composite body, FormToolkit toolkit,
- int extra_style, boolean use_description) {
- super(body, toolkit, extra_style |
- Section.TITLE_BAR |
- (use_description ? Section.DESCRIPTION : 0));
- }
-
- // Create non-static methods of helpers just for convenience
-
- /**
- * Creates a new composite with a TableWrapLayout set with a given number of columns.
- *
- * If the parent composite is a Section, the new composite is set as a client.
- *
- * @param toolkit Form Toolkit
- * @param numColumns Desired number of columns.
- * @return The new composite.
- */
- public Composite createTableLayout(FormToolkit toolkit, int numColumns) {
- return SectionHelper.createTableLayout(getSection(), toolkit, numColumns);
- }
-
- /**
- * Creates a label widget.
- * If the parent layout if a TableWrapLayout, maximize it to span over all columns.
- *
- * @param parent The parent (e.g. composite from CreateTableLayout())
- * @param toolkit Form Toolkit
- * @param label The string for the label.
- * @param tooltip An optional tooltip for the label and text. Can be null.
- * @return The new created label
- */
- public Label createLabel(Composite parent, FormToolkit toolkit, String label,
- String tooltip) {
- return SectionHelper.createLabel(parent, toolkit, label, tooltip);
- }
-
- /**
- * Creates two widgets: a label and a text field.
- *
- * This expects the parent composite to have a TableWrapLayout with 2 columns.
- *
- * @param parent The parent (e.g. composite from CreateTableLayout())
- * @param toolkit Form Toolkit
- * @param label The string for the label.
- * @param value The initial value of the text field. Can be null.
- * @param tooltip An optional tooltip for the label and text. Can be null.
- * @return The new created Text field (the label is not returned)
- */
- public Text createLabelAndText(Composite parent, FormToolkit toolkit, String label,
- String value, String tooltip) {
- return SectionHelper.createLabelAndText(parent, toolkit, label, value, tooltip);
- }
-
- /**
- * Creates a FormText widget.
- *
- * This expects the parent composite to have a TableWrapLayout with 2 columns.
- *
- * @param parent The parent (e.g. composite from CreateTableLayout())
- * @param toolkit Form Toolkit
- * @param isHtml True if the form text will contain HTML that must be interpreted as
- * rich text (i.e. parse tags & expand URLs).
- * @param label The string for the label.
- * @param setupLayoutData indicates whether the created form text receives a TableWrapData
- * through the setLayoutData method. In some case, creating it will make the table parent
- * huge, which we don't want.
- * @return The new created FormText.
- */
- public FormText createFormText(Composite parent, FormToolkit toolkit, boolean isHtml,
- String label, boolean setupLayoutData) {
- return SectionHelper.createFormText(parent, toolkit, isHtml, label, setupLayoutData);
- }
-
- /**
- * Forces the section to recompute its layout and redraw.
- * This is needed after the content of the section has been changed at runtime.
- */
- public void layoutChanged() {
- Section section = getSection();
-
- // Calls getSection().reflow(), which is the same that Section calls
- // when the expandable state is changed and the height changes.
- // Since this is protected, some reflection is needed to invoke it.
- try {
- Method reflow;
- reflow = section.getClass().getDeclaredMethod("reflow", (Class<?>[])null);
- reflow.setAccessible(true);
- reflow.invoke(section);
- } catch (Exception e) {
- AdtPlugin.log(e, "Error when invoking Section.reflow");
- }
-
- section.layout(true /* changed */, true /* all */);
- }
- }
-
- /**
- * Creates a new composite with a TableWrapLayout set with a given number of columns.
- *
- * If the parent composite is a Section, the new composite is set as a client.
- *
- * @param composite The parent (e.g. a Section or SectionPart)
- * @param toolkit Form Toolkit
- * @param numColumns Desired number of columns.
- * @return The new composite.
- */
- static public Composite createTableLayout(Composite composite, FormToolkit toolkit,
- int numColumns) {
- Composite table = toolkit.createComposite(composite);
- TableWrapLayout layout = new TableWrapLayout();
- layout.numColumns = numColumns;
- table.setLayout(layout);
- toolkit.paintBordersFor(table);
- if (composite instanceof Section) {
- ((Section) composite).setClient(table);
- }
- return table;
- }
-
- /**
- * Creates a new composite with a GridLayout set with a given number of columns.
- *
- * If the parent composite is a Section, the new composite is set as a client.
- *
- * @param composite The parent (e.g. a Section or SectionPart)
- * @param toolkit Form Toolkit
- * @param numColumns Desired number of columns.
- * @return The new composite.
- */
- static public Composite createGridLayout(Composite composite, FormToolkit toolkit,
- int numColumns) {
- Composite grid = toolkit.createComposite(composite);
- GridLayout layout = new GridLayout();
- layout.numColumns = numColumns;
- grid.setLayout(layout);
- toolkit.paintBordersFor(grid);
- if (composite instanceof Section) {
- ((Section) composite).setClient(grid);
- }
- return grid;
- }
-
- /**
- * Creates two widgets: a label and a text field.
- *
- * This expects the parent composite to have a TableWrapLayout with 2 columns.
- *
- * @param parent The parent (e.g. composite from CreateTableLayout())
- * @param toolkit Form Toolkit
- * @param label_text The string for the label.
- * @param value The initial value of the text field. Can be null.
- * @param tooltip An optional tooltip for the label and text. Can be null.
- * @return The new created Text field (the label is not returned)
- */
- static public Text createLabelAndText(Composite parent, FormToolkit toolkit, String label_text,
- String value, String tooltip) {
- Label label = toolkit.createLabel(parent, label_text);
- label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE));
- Text text = toolkit.createText(parent, value);
- text.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE));
-
- addControlTooltip(label, tooltip);
- return text;
- }
-
- /**
- * Creates a label widget.
- * If the parent layout if a TableWrapLayout, maximize it to span over all columns.
- *
- * @param parent The parent (e.g. composite from CreateTableLayout())
- * @param toolkit Form Toolkit
- * @param label_text The string for the label.
- * @param tooltip An optional tooltip for the label and text. Can be null.
- * @return The new created label
- */
- static public Label createLabel(Composite parent, FormToolkit toolkit, String label_text,
- String tooltip) {
- Label label = toolkit.createLabel(parent, label_text);
-
- TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB);
- if (parent.getLayout() instanceof TableWrapLayout) {
- twd.colspan = ((TableWrapLayout) parent.getLayout()).numColumns;
- }
- label.setLayoutData(twd);
-
- addControlTooltip(label, tooltip);
- return label;
- }
-
- /**
- * Associates a tooltip with a control.
- *
- * This mirrors the behavior from org.eclipse.pde.internal.ui.editor.text.PDETextHover
- *
- * @param control The control to which associate the tooltip.
- * @param tooltip The tooltip string. Can use \n for multi-lines. Will not display if null.
- */
- static public void addControlTooltip(final Control control, String tooltip) {
- if (control == null || tooltip == null || tooltip.length() == 0) {
- return;
- }
-
- // Some kinds of controls already properly implement tooltip display.
- if (control instanceof Button) {
- control.setToolTipText(tooltip);
- return;
- }
-
- control.setToolTipText(null);
-
- final DefaultInformationControl ic = new DefaultInformationControl(control.getShell());
- ic.setInformation(tooltip);
- Point sz = ic.computeSizeHint();
- ic.setSize(sz.x, sz.y);
- ic.setVisible(false); // initially hidden
-
- control.addMouseTrackListener(new MouseTrackListener() {
- @Override
- public void mouseEnter(MouseEvent e) {
- }
-
- @Override
- public void mouseExit(MouseEvent e) {
- ic.setVisible(false);
- }
-
- @Override
- public void mouseHover(MouseEvent e) {
- ic.setLocation(control.toDisplay(10, 25)); // same offset as in PDETextHover
- ic.setVisible(true);
- }
- });
- control.addDisposeListener(new DisposeListener() {
- @Override
- public void widgetDisposed(DisposeEvent e) {
- ic.dispose();
- }
- });
- }
-
- /**
- * Creates a FormText widget.
- *
- * This expects the parent composite to have a TableWrapLayout with 2 columns.
- *
- * @param parent The parent (e.g. composite from CreateTableLayout())
- * @param toolkit Form Toolkit
- * @param isHtml True if the form text will contain HTML that must be interpreted as
- * rich text (i.e. parse tags & expand URLs).
- * @param label The string for the label.
- * @param setupLayoutData indicates whether the created form text receives a TableWrapData
- * through the setLayoutData method. In some case, creating it will make the table parent
- * huge, which we don't want.
- * @return The new created FormText.
- */
- static public FormText createFormText(Composite parent, FormToolkit toolkit,
- boolean isHtml, String label, boolean setupLayoutData) {
- FormText text = toolkit.createFormText(parent, true /* track focus */);
- if (setupLayoutData) {
- TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB);
- twd.maxWidth = AndroidXmlEditor.TEXT_WIDTH_HINT;
- if (parent.getLayout() instanceof TableWrapLayout) {
- twd.colspan = ((TableWrapLayout) parent.getLayout()).numColumns;
- }
- text.setLayoutData(twd);
- }
- text.setWhitespaceNormalized(true);
- if (isHtml && !label.startsWith("<form>")) { //$NON-NLS-1$
- // This assertion is violated, for example by the Class attribute for an activity
- //assert label.startsWith("<form>") : "HTML for FormText must be wrapped in <form>...</form>"; //$NON-NLS-1$
- label = "<form>" + label + "</form>"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- text.setText(label, isHtml /* parseTags */, isHtml /* expandURLs */);
- return text;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/TextValueCellEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/TextValueCellEditor.java
deleted file mode 100644
index 3750c3472..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/TextValueCellEditor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 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.ui;
-
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
-
-import org.eclipse.jface.viewers.TextCellEditor;
-import org.eclipse.swt.widgets.Composite;
-
-/**
- * TextCellEditor able to receive a {@link UiAttributeNode} in the {@link #setValue(Object)}
- * method.
- */
-public class TextValueCellEditor extends TextCellEditor {
-
- public TextValueCellEditor(Composite parent) {
- super(parent);
- }
-
- @Override
- protected void doSetValue(Object value) {
- if (value instanceof UiAttributeNode) {
- super.doSetValue(((UiAttributeNode)value).getCurrentValue());
- return;
- }
-
- super.doSetValue(value);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/UiElementPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/UiElementPart.java
deleted file mode 100644
index db9fa069f..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/UiElementPart.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2007 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.ui;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestEditor;
-import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper.ManifestSectionPart;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.Section;
-
-/**
- * Generic page's section part that displays all attributes of a given {@link UiElementNode}.
- * <p/>
- * This part is designed to be displayed in a page that has a table column layout.
- * It is linked to a specific {@link UiElementNode} and automatically displays all of its
- * attributes, manages its dirty state and commits the attributes when necessary.
- * <p/>
- * No derivation is needed unless the UI or workflow needs to be extended.
- */
-public class UiElementPart extends ManifestSectionPart {
-
- /** A reference to the container editor */
- private ManifestEditor mEditor;
- /** The {@link UiElementNode} manipulated by this SectionPart. It can be null. */
- private UiElementNode mUiElementNode;
- /** Table that contains all the attributes */
- private Composite mTable;
-
- public UiElementPart(Composite body, FormToolkit toolkit, ManifestEditor editor,
- UiElementNode uiElementNode, String sectionTitle, String sectionDescription,
- int extra_style) {
- super(body, toolkit, extra_style, sectionDescription != null);
- mEditor = editor;
- mUiElementNode = uiElementNode;
- setupSection(sectionTitle, sectionDescription);
-
- if (uiElementNode == null) {
- // This is serious and should never happen. Instead of crashing, simply abort.
- // There will be no UI, which will prevent further damage.
- AdtPlugin.log(IStatus.ERROR, "Missing node to edit!"); //$NON-NLS-1$
- return;
- }
- }
-
- /**
- * Returns the Editor associated with this part.
- */
- public ManifestEditor getEditor() {
- return mEditor;
- }
-
- /**
- * Returns the {@link UiElementNode} associated with this part.
- */
- public UiElementNode getUiElementNode() {
- return mUiElementNode;
- }
-
- /**
- * Changes the element node handled by this part.
- *
- * @param uiElementNode The new element node for the part.
- */
- public void setUiElementNode(UiElementNode uiElementNode) {
- mUiElementNode = uiElementNode;
- }
-
- /**
- * Initializes the form part.
- * <p/>
- * This is called by the owning managed form as soon as the part is added to the form,
- * which happens right after the part is actually created.
- */
- @Override
- public void initialize(IManagedForm form) {
- super.initialize(form);
- createFormControls(form);
- }
-
- /**
- * Setup the section that contains this part.
- * <p/>
- * This is called by the constructor to set the section's title and description
- * with parameters given in the constructor.
- * <br/>
- * Derived class override this if needed, however in most cases the default
- * implementation should be enough.
- *
- * @param sectionTitle The section part's title
- * @param sectionDescription The section part's description
- */
- protected void setupSection(String sectionTitle, String sectionDescription) {
- Section section = getSection();
- section.setText(sectionTitle);
- section.setDescription(sectionDescription);
- }
-
- /**
- * Create the controls to edit the attributes for the given ElementDescriptor.
- * <p/>
- * This MUST not be called by the constructor. Instead it must be called from
- * <code>initialize</code> (i.e. right after the form part is added to the managed form.)
- * <p/>
- * Derived classes can override this if necessary.
- *
- * @param managedForm The owner managed form
- */
- protected void createFormControls(IManagedForm managedForm) {
- setTable(createTableLayout(managedForm.getToolkit(), 2 /* numColumns */));
-
- createUiAttributes(managedForm);
- }
-
- /**
- * Sets the table where the attribute UI needs to be created.
- */
- protected void setTable(Composite table) {
- mTable = table;
- }
-
- /**
- * Returns the table where the attribute UI needs to be created.
- */
- protected Composite getTable() {
- return mTable;
- }
-
- /**
- * Add all the attribute UI widgets into the underlying table layout.
- *
- * @param managedForm The owner managed form
- */
- protected void createUiAttributes(IManagedForm managedForm) {
- Composite table = getTable();
- if (table == null || managedForm == null) {
- return;
- }
-
- // Remove any old UI controls
- for (Control c : table.getChildren()) {
- c.dispose();
- }
-
- fillTable(table, managedForm);
-
- // Tell the section that the layout has changed.
- layoutChanged();
- }
-
- /**
- * Actually fills the table.
- * This is called by {@link #createUiAttributes(IManagedForm)} to populate the new
- * table. The default implementation is to use
- * {@link #insertUiAttributes(UiElementNode, Composite, IManagedForm)} to actually
- * place the attributes of the default {@link UiElementNode} in the table.
- * <p/>
- * Derived classes can override this to add controls in the table before or after.
- *
- * @param table The table to fill. It must have 2 columns.
- * @param managedForm The managed form for new controls.
- */
- protected void fillTable(Composite table, IManagedForm managedForm) {
- int inserted = insertUiAttributes(mUiElementNode, table, managedForm);
-
- if (inserted == 0) {
- createLabel(table, managedForm.getToolkit(),
- "No attributes to display, waiting for SDK to finish loading...",
- null /* tooltip */ );
- }
- }
-
- /**
- * Insert the UI attributes of the given {@link UiElementNode} in the given table.
- *
- * @param uiNode The {@link UiElementNode} that contains the attributes to display.
- * Must not be null.
- * @param table The table to fill. It must have 2 columns.
- * @param managedForm The managed form for new controls.
- * @return The number of UI attributes inserted. It is >= 0.
- */
- protected int insertUiAttributes(UiElementNode uiNode, Composite table, IManagedForm managedForm) {
- if (uiNode == null || table == null || managedForm == null) {
- return 0;
- }
-
- // To iterate over all attributes, we use the {@link ElementDescriptor} instead
- // of the {@link UiElementNode} because the attributes' order is guaranteed in the
- // descriptor but not in the node itself.
- AttributeDescriptor[] attr_desc_list = uiNode.getAttributeDescriptors();
- for (AttributeDescriptor attr_desc : attr_desc_list) {
- if (attr_desc instanceof XmlnsAttributeDescriptor) {
- // Do not show hidden attributes
- continue;
- }
-
- UiAttributeNode ui_attr = uiNode.findUiAttribute(attr_desc);
- if (ui_attr != null) {
- ui_attr.createUiControl(table, managedForm);
- } else {
- // The XML has an extra attribute which wasn't declared in
- // AndroidManifestDescriptors. This is not a problem, we just ignore it.
- AdtPlugin.log(IStatus.WARNING,
- "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
- attr_desc.getXmlLocalName(),
- uiNode.getDescriptor().getXmlName());
- }
- }
- return attr_desc_list.length;
- }
-
- /**
- * Tests whether the part is dirty i.e. its widgets have state that is
- * newer than the data in the model.
- * <p/>
- * This is done by iterating over all attributes and updating the super's
- * internal dirty flag. Stop once at least one attribute is dirty.
- *
- * @return <code>true</code> if the part is dirty, <code>false</code>
- * otherwise.
- */
- @Override
- public boolean isDirty() {
- if (mUiElementNode != null && !super.isDirty()) {
- for (UiAttributeNode ui_attr : mUiElementNode.getAllUiAttributes()) {
- if (ui_attr.isDirty()) {
- markDirty();
- break;
- }
- }
- }
- return super.isDirty();
- }
-
- /**
- * If part is displaying information loaded from a model, this method
- * instructs it to commit the new (modified) data back into the model.
- *
- * @param onSave
- * indicates if commit is called during 'save' operation or for
- * some other reason (for example, if form is contained in a
- * wizard or a multi-page editor and the user is about to leave
- * the page).
- */
- @Override
- public void commit(boolean onSave) {
- if (mUiElementNode != null) {
- mEditor.wrapEditXmlModel(new Runnable() {
- @Override
- public void run() {
- for (UiAttributeNode ui_attr : mUiElementNode.getAllUiAttributes()) {
- ui_attr.commit();
- }
- }
- });
- }
-
- // We need to call super's commit after we synchronized the nodes to make sure we
- // reset the dirty flag after all the side effects from committing have occurred.
- super.commit(onSave);
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/CopyCutAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/CopyCutAction.java
deleted file mode 100644
index 3fe98bb23..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/CopyCutAction.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2008 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.ui.tree;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-
-import org.apache.xml.serialize.Method;
-import org.apache.xml.serialize.OutputFormat;
-import org.apache.xml.serialize.XMLSerializer;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.swt.dnd.Transfer;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
-import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.xml.core.internal.document.NodeContainer;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-
-/**
- * Provides Cut and Copy actions for the tree nodes.
- */
-@SuppressWarnings({"restriction", "deprecation"})
-public class CopyCutAction extends Action {
- private List<UiElementNode> mUiNodes;
- private boolean mPerformCut;
- private final AndroidXmlEditor mEditor;
- private final Clipboard mClipboard;
- private final ICommitXml mXmlCommit;
-
- /**
- * Creates a new Copy or Cut action.
- *
- * @param selected The UI node to cut or copy. It *must* have a non-null XML node.
- * @param performCut True if the operation is cut, false if it is copy.
- */
- public CopyCutAction(AndroidXmlEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
- UiElementNode selected, boolean performCut) {
- this(editor, clipboard, xmlCommit, toList(selected), performCut);
- }
-
- /**
- * Creates a new Copy or Cut action.
- *
- * @param selected The UI nodes to cut or copy. They *must* have a non-null XML node.
- * The list becomes owned by the {@link CopyCutAction}.
- * @param performCut True if the operation is cut, false if it is copy.
- */
- public CopyCutAction(AndroidXmlEditor editor, Clipboard clipboard, ICommitXml xmlCommit,
- List<UiElementNode> selected, boolean performCut) {
- super(performCut ? "Cut" : "Copy");
- mEditor = editor;
- mClipboard = clipboard;
- mXmlCommit = xmlCommit;
-
- ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
- if (performCut) {
- setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT));
- setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_HOVER));
- setDisabledImageDescriptor(
- images.getImageDescriptor(ISharedImages.IMG_TOOL_CUT_DISABLED));
- } else {
- setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
- setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_HOVER));
- setDisabledImageDescriptor(
- images.getImageDescriptor(ISharedImages.IMG_TOOL_COPY_DISABLED));
- }
-
- mUiNodes = selected;
- mPerformCut = performCut;
- }
-
- /**
- * Performs the cut or copy action.
- * First an XML serializer is used to turn the existing XML node into a valid
- * XML fragment, which is added as text to the clipboard.
- */
- @Override
- public void run() {
- super.run();
- if (mUiNodes == null || mUiNodes.size() < 1) {
- return;
- }
-
- // Commit the current pages first, to make sure the XML is in sync.
- // Committing may change the XML structure.
- if (mXmlCommit != null) {
- mXmlCommit.commitPendingXmlChanges();
- }
-
- StringBuilder allText = new StringBuilder();
- ArrayList<UiElementNode> nodesToCut = mPerformCut ? new ArrayList<UiElementNode>() : null;
-
- for (UiElementNode uiNode : mUiNodes) {
- try {
- Node xml_node = uiNode.getXmlNode();
- if (xml_node == null) {
- return;
- }
-
- String data = getXmlTextFromEditor(xml_node);
-
- // In the unlikely event that IStructuredDocument failed to extract the text
- // directly from the editor, try to fall back on a direct XML serialization
- // of the XML node. This uses the generic Node interface with no SSE tricks.
- if (data == null) {
- data = getXmlTextFromSerialization(xml_node);
- }
-
- if (data != null) {
- allText.append(data);
- if (mPerformCut) {
- // only remove notes to cut if we actually got some XML text from them
- nodesToCut.add(uiNode);
- }
- }
-
- } catch (Exception e) {
- AdtPlugin.log(e, "CopyCutAction failed for UI node %1$s", //$NON-NLS-1$
- uiNode.getBreadcrumbTrailDescription(true));
- }
- } // for uiNode
-
- if (allText != null && allText.length() > 0) {
- mClipboard.setContents(
- new Object[] { allText.toString() },
- new Transfer[] { TextTransfer.getInstance() });
- if (mPerformCut) {
- for (UiElementNode uiNode : nodesToCut) {
- uiNode.deleteXmlNode();
- }
- }
- }
- }
-
- /** Get the data directly from the editor. */
- private String getXmlTextFromEditor(Node xml_node) {
- String data = null;
- IStructuredModel model = mEditor.getModelForRead();
- try {
- IStructuredDocument sse_doc = mEditor.getStructuredDocument();
- if (xml_node instanceof NodeContainer) {
- // The easy way to get the source of an SSE XML node.
- data = ((NodeContainer) xml_node).getSource();
- } else if (xml_node instanceof IndexedRegion && sse_doc != null) {
- // Try harder.
- IndexedRegion region = (IndexedRegion) xml_node;
- int start = region.getStartOffset();
- int end = region.getEndOffset();
-
- if (end > start) {
- data = sse_doc.get(start, end - start);
- }
- }
- } catch (BadLocationException e) {
- // the region offset was invalid. ignore.
- } finally {
- model.releaseFromRead();
- }
- return data;
- }
-
- /**
- * Direct XML serialization of the XML node.
- * <p/>
- * This uses the generic Node interface with no SSE tricks. It's however slower
- * and doesn't respect formatting (since serialization is involved instead of reading
- * the actual text buffer.)
- */
- private String getXmlTextFromSerialization(Node xml_node) throws IOException {
- String data;
- StringWriter sw = new StringWriter();
- XMLSerializer serializer = new XMLSerializer(sw,
- new OutputFormat(Method.XML,
- OutputFormat.Defaults.Encoding /* utf-8 */,
- true /* indent */));
- // Serialize will throw an IOException if it fails.
- serializer.serialize((Element) xml_node);
- data = sw.toString();
- return data;
- }
-
- /**
- * Static helper class to wrap on node into a list for the constructors.
- */
- private static ArrayList<UiElementNode> toList(UiElementNode selected) {
- ArrayList<UiElementNode> list = null;
- if (selected != null) {
- list = new ArrayList<UiElementNode>(1);
- list.add(selected);
- }
- return list;
- }
-}
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/ICommitXml.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/ICommitXml.java
deleted file mode 100644
index 067d1459e..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/ICommitXml.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.ui.tree;
-
-/**
- * Interface for an object that can commit its changes to the underlying XML model
- */
-public interface ICommitXml {
-
- /** Commits pending data to the underlying XML model. */
- public void commitPendingXmlChanges();
-
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/NewItemSelectionDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/NewItemSelectionDialog.java
deleted file mode 100644
index 385a53a5f..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/NewItemSelectionDialog.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2007 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.ui.tree;
-
-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.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;
-import com.android.ide.eclipse.adt.internal.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;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-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.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
-
-/**
- * A selection dialog to select the type of the new element node to
- * create, either in the application node or the selected sub node.
- */
-public class NewItemSelectionDialog extends AbstractElementListSelectionDialog {
-
- /** 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 UiElementNode mSelectedUiNode;
- /** The root node chosen by the user, either root_node or the one passed
- * to the constructor if not null */
- 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. 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. 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.
- */
- public NewItemSelectionDialog(Shell shell, ILabelProvider labelProvider,
- ElementDescriptor[] descriptorFilters,
- UiElementNode ui_node,
- UiElementNode root_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() {
- @Override
- 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]).getFullClassName(), //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;
- }
-
- /**
- * 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) {
- AndroidXmlEditor 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) {
- AndroidXmlEditor 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;
- }
-
- /**
- * @return The root node selected by the user, either root node or the
- * one passed to the constructor if not null.
- */
- public UiElementNode getChosenRootNode() {
- return mChosenRootNode;
- }
-
- /**
- * Internal helper to compute the result. Returns the selection from
- * the list view, if any.
- */
- @Override
- protected void computeResult() {
- setResult(Arrays.asList(getSelectedElements()));
- setLastUsedXmlName(getSelectedElements());
- }
-
- /**
- * 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.
- */
- @Override
- protected Control createDialogArea(Composite parent) {
- Composite contents = (Composite) super.createDialogArea(parent);
-
- createRadioControl(contents);
- createFilterText(contents);
- createFilteredList(contents);
-
- // We don't want the builtin message area label (we use a radio control
- // instead), but if we don't create it, Bad Stuff happens on
- // Eclipse 3.8 and later (see issue 32527).
- Label label = createMessageArea(contents);
- if (label != null) {
- GridData data = (GridData) label.getLayoutData();
- data.exclude = true;
- }
-
- // 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;
- }
-
- /**
- * 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(Locale.US);
- }
-
- for (ElementDescriptor desc : getAllowedDescriptors(rootNode)) {
- if (!partial && desc.getXmlName().equals(name)) {
- initialElement = desc;
- break;
- } else if (partial) {
- String name2 = desc.getXmlLocalName().toLowerCase(Locale.US);
- 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.
- */
- private Composite createRadioControl(Composite content) {
-
- 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;
- }
-
- /**
- * 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.
- */
- 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) {
- return mDescriptorFilters;
- } else {
- return ui_node.getDescriptor().getChildren();
- }
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java
deleted file mode 100644
index 6674ba9ca..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/PasteAction.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2008 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.ui.tree;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.dnd.TextTransfer;
-import org.eclipse.ui.ISharedImages;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
-import org.eclipse.wst.xml.core.internal.document.NodeContainer;
-import org.w3c.dom.Node;
-
-
-/**
- * Provides Paste operation for the tree nodes
- */
-@SuppressWarnings("restriction")
-public class PasteAction extends Action {
- private UiElementNode mUiNode;
- private final AndroidXmlEditor mEditor;
- private final Clipboard mClipboard;
-
- public PasteAction(AndroidXmlEditor editor, Clipboard clipboard, UiElementNode ui_node) {
- super("Paste");
- mEditor = editor;
- mClipboard = clipboard;
-
- ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
- setImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));
- setHoverImageDescriptor(images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));
- setDisabledImageDescriptor(
- images.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE_DISABLED));
-
- mUiNode = ui_node;
- }
-
- /**
- * Performs the paste operation.
- */
- @Override
- public void run() {
- super.run();
-
- final String data = (String) mClipboard.getContents(TextTransfer.getInstance());
- if (data != null) {
- mEditor.wrapEditXmlModel(new Runnable() {
- @Override
- public void run() {
- try {
- IStructuredDocument sse_doc = mEditor.getStructuredDocument();
- if (sse_doc != null) {
- if (mUiNode.getDescriptor().hasChildren()) {
- // This UI Node can have children. The new XML is
- // inserted as the first child.
-
- if (mUiNode.getUiChildren().size() > 0) {
- // There's already at least one child,
- // so insert right before it.
- Node xml_node = mUiNode.getUiChildren().get(0).getXmlNode();
-
- if (xml_node instanceof IndexedRegion) {
- IndexedRegion region = (IndexedRegion) xml_node;
- sse_doc.replace(region.getStartOffset(), 0, data);
- return; // we're done, no need to try the other cases
- }
- }
-
- // If there's no first XML node child. Create one by
- // inserting at the end of the *start* tag.
- Node xml_node = mUiNode.getXmlNode();
- if (xml_node instanceof NodeContainer) {
- NodeContainer container = (NodeContainer) xml_node;
- IStructuredDocumentRegion start_tag =
- container.getStartStructuredDocumentRegion();
- if (start_tag != null) {
- sse_doc.replace(start_tag.getEndOffset(), 0, data);
- return; // we're done, no need to try the other case
- }
- }
- }
-
- // This UI Node doesn't accept children. The new XML is inserted as the
- // next sibling. This also serves as a fallback if all the previous
- // attempts failed. However, this is not possible if the current node
- // has for parent a document -- an XML document can only have one root,
- // with no siblings.
- if (!(mUiNode.getUiParent() instanceof UiDocumentNode)) {
- Node xml_node = mUiNode.getXmlNode();
- if (xml_node instanceof IndexedRegion) {
- IndexedRegion region = (IndexedRegion) xml_node;
- sse_doc.replace(region.getEndOffset(), 0, data);
- }
- }
- }
-
- } catch (BadLocationException e) {
- AdtPlugin.log(e,
- "ParseAction failed for UI Node %2$s, content '%1$s'", //$NON-NLS-1$
- mUiNode.getBreadcrumbTrailDescription(true), data);
- }
- }
- });
- }
- }
-}
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiActions.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiActions.java
deleted file mode 100644
index 92ccf2e7d..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiActions.java
+++ /dev/null
@@ -1,598 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
- *
- * 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.ui.tree;
-
-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.descriptors.ElementDescriptor.Mandatory;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.swt.widgets.Shell;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-import java.util.List;
-
-/**
- * Performs basic actions on an XML tree: add node, remove node, move up/down.
- */
-public abstract class UiActions implements ICommitXml {
-
- public UiActions() {
- }
-
- //---------------------
- // Actual implementations must override these to provide specific hooks
-
- /** Returns the UiDocumentNode for the current model. */
- abstract protected UiElementNode getRootNode();
-
- /** Commits pending data before the XML model is modified. */
- @Override
- abstract public void commitPendingXmlChanges();
-
- /**
- * Utility method to select an outline item based on its model node
- *
- * @param uiNode The node to select. Can be null (in which case nothing should happen)
- */
- abstract protected void selectUiNode(UiElementNode uiNode);
-
- //---------------------
-
- /**
- * Called when the "Add..." button next to the tree view is selected.
- * <p/>
- * This simplified version of doAdd does not support descriptor filters and creates
- * a new {@link UiModelTreeLabelProvider} for each call.
- */
- public void doAdd(UiElementNode uiNode, Shell shell) {
- doAdd(uiNode, null /* descriptorFilters */, shell, new UiModelTreeLabelProvider());
- }
-
- /**
- * Called when the "Add..." button next to the tree view is selected.
- *
- * Displays a selection dialog that lets the user select which kind of node
- * to create, depending on the current selection.
- */
- public void doAdd(UiElementNode uiNode,
- ElementDescriptor[] descriptorFilters,
- Shell shell, ILabelProvider labelProvider) {
- // If the root node is a document with already a root, use it as the root node
- UiElementNode rootNode = getRootNode();
- if (rootNode instanceof UiDocumentNode && rootNode.getUiChildren().size() > 0) {
- rootNode = rootNode.getUiChildren().get(0);
- }
-
- NewItemSelectionDialog dlg = new NewItemSelectionDialog(
- shell,
- labelProvider,
- descriptorFilters,
- uiNode, rootNode);
- dlg.open();
- Object[] results = dlg.getResult();
- if (results != null && results.length > 0) {
- addElement(dlg.getChosenRootNode(), null, (ElementDescriptor) results[0],
- true /*updateLayout*/);
- }
- }
-
- /**
- * Adds a new XML element based on the {@link ElementDescriptor} to the given parent
- * {@link UiElementNode}, and then select it.
- * <p/>
- * If the parent is a document root which already contains a root element, the inner
- * root element is used as the actual parent. This ensure you can't create a broken
- * XML file with more than one root element.
- * <p/>
- * If a sibling is given and that sibling has the same parent, the new node is added
- * right after that sibling. Otherwise the new node is added at the end of the parent
- * child list.
- *
- * @param uiParent An existing UI node or null to add to the tree root
- * @param uiSibling An existing UI node before which to insert the new node. Can be null.
- * @param descriptor The descriptor of the element to add
- * @param updateLayout True if layout attributes should be set
- * @return The new {@link UiElementNode} or null.
- */
- public UiElementNode addElement(UiElementNode uiParent,
- UiElementNode uiSibling,
- ElementDescriptor descriptor,
- boolean updateLayout) {
- if (uiParent instanceof UiDocumentNode && uiParent.getUiChildren().size() > 0) {
- uiParent = uiParent.getUiChildren().get(0);
- }
- if (uiSibling != null && uiSibling.getUiParent() != uiParent) {
- uiSibling = null;
- }
-
- UiElementNode uiNew = addNewTreeElement(uiParent, uiSibling, descriptor, updateLayout);
- selectUiNode(uiNew);
-
- return uiNew;
- }
-
- /**
- * Called when the "Remove" button is selected.
- *
- * If the tree has a selection, remove it.
- * This simply deletes the XML node attached to the UI node: when the XML model fires the
- * update event, the tree will get refreshed.
- */
- public void doRemove(final List<UiElementNode> nodes, Shell shell) {
-
- if (nodes == null || nodes.size() == 0) {
- return;
- }
-
- final int len = nodes.size();
-
- StringBuilder sb = new StringBuilder();
- for (UiElementNode node : nodes) {
- sb.append("\n- "); //$NON-NLS-1$
- sb.append(node.getBreadcrumbTrailDescription(false /* include_root */));
- }
-
- if (MessageDialog.openQuestion(shell,
- len > 1 ? "Remove elements from Android XML" // title
- : "Remove element from Android XML",
- String.format("Do you really want to remove %1$s?", sb.toString()))) {
- commitPendingXmlChanges();
- getRootNode().getEditor().wrapEditXmlModel(new Runnable() {
- @Override
- public void run() {
- UiElementNode previous = null;
- UiElementNode parent = null;
-
- for (int i = len - 1; i >= 0; i--) {
- UiElementNode node = nodes.get(i);
- previous = node.getUiPreviousSibling();
- parent = node.getUiParent();
-
- // delete node
- node.deleteXmlNode();
- }
-
- // try to select the last previous sibling or the last parent
- if (previous != null) {
- selectUiNode(previous);
- } else if (parent != null) {
- selectUiNode(parent);
- }
- }
- });
- }
- }
-
- /**
- * Called when the "Up" button is selected.
- * <p/>
- * If the tree has a selection, move it up, either in the child list or as the last child
- * of the previous parent.
- */
- public void doUp(
- final List<UiElementNode> uiNodes,
- final ElementDescriptor[] descriptorFilters) {
- if (uiNodes == null || uiNodes.size() < 1) {
- return;
- }
-
- final Node[] selectXmlNode = { null };
- final UiElementNode[] uiLastNode = { null };
- final UiElementNode[] uiSearchRoot = { null };
-
- commitPendingXmlChanges();
- getRootNode().getEditor().wrapEditXmlModel(new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < uiNodes.size(); i++) {
- UiElementNode uiNode = uiLastNode[0] = uiNodes.get(i);
- doUpInternal(
- uiNode,
- descriptorFilters,
- selectXmlNode,
- uiSearchRoot,
- false /*testOnly*/);
- }
- }
- });
-
- assert uiLastNode[0] != null; // tell Eclipse this can't be null below
-
- if (selectXmlNode[0] == null) {
- // The XML node has not been moved, we can just select the same UI node
- selectUiNode(uiLastNode[0]);
- } else {
- // The XML node has moved. At this point the UI model has been reloaded
- // and the XML node has been affected to a new UI node. Find that new UI
- // node and select it.
- if (uiSearchRoot[0] == null) {
- uiSearchRoot[0] = uiLastNode[0].getUiRoot();
- }
- if (uiSearchRoot[0] != null) {
- selectUiNode(uiSearchRoot[0].findXmlNode(selectXmlNode[0]));
- }
- }
- }
-
- /**
- * Checks whether the "up" action can be performed on all items.
- *
- * @return True if the up action can be carried on *all* items.
- */
- public boolean canDoUp(
- List<UiElementNode> uiNodes,
- ElementDescriptor[] descriptorFilters) {
- if (uiNodes == null || uiNodes.size() < 1) {
- return false;
- }
-
- final Node[] selectXmlNode = { null };
- final UiElementNode[] uiSearchRoot = { null };
-
- commitPendingXmlChanges();
-
- for (int i = 0; i < uiNodes.size(); i++) {
- if (!doUpInternal(
- uiNodes.get(i),
- descriptorFilters,
- selectXmlNode,
- uiSearchRoot,
- true /*testOnly*/)) {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean doUpInternal(
- UiElementNode uiNode,
- ElementDescriptor[] descriptorFilters,
- Node[] outSelectXmlNode,
- UiElementNode[] outUiSearchRoot,
- boolean testOnly) {
- // the node will move either up to its parent or grand-parent
- outUiSearchRoot[0] = uiNode.getUiParent();
- if (outUiSearchRoot[0] != null && outUiSearchRoot[0].getUiParent() != null) {
- outUiSearchRoot[0] = outUiSearchRoot[0].getUiParent();
- }
- Node xmlNode = uiNode.getXmlNode();
- ElementDescriptor nodeDesc = uiNode.getDescriptor();
- if (xmlNode == null || nodeDesc == null) {
- return false;
- }
- UiElementNode uiParentNode = uiNode.getUiParent();
- Node xmlParent = uiParentNode == null ? null : uiParentNode.getXmlNode();
- if (xmlParent == null) {
- return false;
- }
-
- UiElementNode uiPrev = uiNode.getUiPreviousSibling();
-
- // Only accept a sibling that has an XML attached and
- // is part of the allowed descriptor filters.
- while (uiPrev != null &&
- (uiPrev.getXmlNode() == null || !matchDescFilter(descriptorFilters, uiPrev))) {
- uiPrev = uiPrev.getUiPreviousSibling();
- }
-
- if (uiPrev != null && uiPrev.getXmlNode() != null) {
- // This node is not the first one of the parent.
- Node xmlPrev = uiPrev.getXmlNode();
- if (uiPrev.getDescriptor().acceptChild(nodeDesc)) {
- // If the previous sibling can accept this child, then it
- // is inserted at the end of the children list.
- if (testOnly) {
- return true;
- }
- xmlPrev.appendChild(xmlParent.removeChild(xmlNode));
- outSelectXmlNode[0] = xmlNode;
- } else {
- // This node is not the first one of the parent, so it can be
- // removed and then inserted before its previous sibling.
- if (testOnly) {
- return true;
- }
- xmlParent.insertBefore(
- xmlParent.removeChild(xmlNode),
- xmlPrev);
- outSelectXmlNode[0] = xmlNode;
- }
- } else if (uiParentNode != null && !(xmlParent instanceof Document)) {
- UiElementNode uiGrandParent = uiParentNode.getUiParent();
- Node xmlGrandParent = uiGrandParent == null ? null : uiGrandParent.getXmlNode();
- ElementDescriptor grandDesc =
- uiGrandParent == null ? null : uiGrandParent.getDescriptor();
-
- if (xmlGrandParent != null &&
- !(xmlGrandParent instanceof Document) &&
- grandDesc != null &&
- grandDesc.acceptChild(nodeDesc)) {
- // If the node is the first one of the child list of its
- // parent, move it up in the hierarchy as previous sibling
- // to the parent. This is only possible if the parent of the
- // parent is not a document.
- // The parent node must actually accept this kind of child.
-
- if (testOnly) {
- return true;
- }
- xmlGrandParent.insertBefore(
- xmlParent.removeChild(xmlNode),
- xmlParent);
- outSelectXmlNode[0] = xmlNode;
- }
- }
-
- return false;
- }
-
- private boolean matchDescFilter(
- ElementDescriptor[] descriptorFilters,
- UiElementNode uiNode) {
- if (descriptorFilters == null || descriptorFilters.length < 1) {
- return true;
- }
-
- ElementDescriptor desc = uiNode.getDescriptor();
-
- for (ElementDescriptor filter : descriptorFilters) {
- if (filter.equals(desc)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Called when the "Down" button is selected.
- *
- * If the tree has a selection, move it down, either in the same child list or as the
- * first child of the next parent.
- */
- public void doDown(
- final List<UiElementNode> nodes,
- final ElementDescriptor[] descriptorFilters) {
- if (nodes == null || nodes.size() < 1) {
- return;
- }
-
- final Node[] selectXmlNode = { null };
- final UiElementNode[] uiLastNode = { null };
- final UiElementNode[] uiSearchRoot = { null };
-
- commitPendingXmlChanges();
- getRootNode().getEditor().wrapEditXmlModel(new Runnable() {
- @Override
- public void run() {
- for (int i = nodes.size() - 1; i >= 0; i--) {
- final UiElementNode node = uiLastNode[0] = nodes.get(i);
- doDownInternal(
- node,
- descriptorFilters,
- selectXmlNode,
- uiSearchRoot,
- false /*testOnly*/);
- }
- }
- });
-
- assert uiLastNode[0] != null; // tell Eclipse this can't be null below
-
- if (selectXmlNode[0] == null) {
- // The XML node has not been moved, we can just select the same UI node
- selectUiNode(uiLastNode[0]);
- } else {
- // The XML node has moved. At this point the UI model has been reloaded
- // and the XML node has been affected to a new UI node. Find that new UI
- // node and select it.
- if (uiSearchRoot[0] == null) {
- uiSearchRoot[0] = uiLastNode[0].getUiRoot();
- }
- if (uiSearchRoot[0] != null) {
- selectUiNode(uiSearchRoot[0].findXmlNode(selectXmlNode[0]));
- }
- }
- }
-
- /**
- * Checks whether the "down" action can be performed on all items.
- *
- * @return True if the down action can be carried on *all* items.
- */
- public boolean canDoDown(
- List<UiElementNode> uiNodes,
- ElementDescriptor[] descriptorFilters) {
- if (uiNodes == null || uiNodes.size() < 1) {
- return false;
- }
-
- final Node[] selectXmlNode = { null };
- final UiElementNode[] uiSearchRoot = { null };
-
- commitPendingXmlChanges();
-
- for (int i = 0; i < uiNodes.size(); i++) {
- if (!doDownInternal(
- uiNodes.get(i),
- descriptorFilters,
- selectXmlNode,
- uiSearchRoot,
- true /*testOnly*/)) {
- return false;
- }
- }
-
- return true;
- }
-
- private boolean doDownInternal(
- UiElementNode uiNode,
- ElementDescriptor[] descriptorFilters,
- Node[] outSelectXmlNode,
- UiElementNode[] outUiSearchRoot,
- boolean testOnly) {
- // the node will move either down to its parent or grand-parent
- outUiSearchRoot[0] = uiNode.getUiParent();
- if (outUiSearchRoot[0] != null && outUiSearchRoot[0].getUiParent() != null) {
- outUiSearchRoot[0] = outUiSearchRoot[0].getUiParent();
- }
-
- Node xmlNode = uiNode.getXmlNode();
- ElementDescriptor nodeDesc = uiNode.getDescriptor();
- if (xmlNode == null || nodeDesc == null) {
- return false;
- }
- UiElementNode uiParentNode = uiNode.getUiParent();
- Node xmlParent = uiParentNode == null ? null : uiParentNode.getXmlNode();
- if (xmlParent == null) {
- return false;
- }
-
- UiElementNode uiNext = uiNode.getUiNextSibling();
-
- // Only accept a sibling that has an XML attached and
- // is part of the allowed descriptor filters.
- while (uiNext != null &&
- (uiNext.getXmlNode() == null || !matchDescFilter(descriptorFilters, uiNext))) {
- uiNext = uiNext.getUiNextSibling();
- }
-
- if (uiNext != null && uiNext.getXmlNode() != null) {
- // This node is not the last one of the parent.
- Node xmlNext = uiNext.getXmlNode();
- // If the next sibling is a node that can have children, though,
- // then the node is inserted as the first child.
- if (uiNext.getDescriptor().acceptChild(nodeDesc)) {
- if (testOnly) {
- return true;
- }
- // Note: insertBefore works as append if the ref node is
- // null, i.e. when the node doesn't have children yet.
- xmlNext.insertBefore(
- xmlParent.removeChild(xmlNode),
- xmlNext.getFirstChild());
- outSelectXmlNode[0] = xmlNode;
- } else {
- // This node is not the last one of the parent, so it can be
- // removed and then inserted after its next sibling.
-
- if (testOnly) {
- return true;
- }
- // Insert "before after next" ;-)
- xmlParent.insertBefore(
- xmlParent.removeChild(xmlNode),
- xmlNext.getNextSibling());
- outSelectXmlNode[0] = xmlNode;
- }
- } else if (uiParentNode != null && !(xmlParent instanceof Document)) {
- UiElementNode uiGrandParent = uiParentNode.getUiParent();
- Node xmlGrandParent = uiGrandParent == null ? null : uiGrandParent.getXmlNode();
- ElementDescriptor grandDesc =
- uiGrandParent == null ? null : uiGrandParent.getDescriptor();
-
- if (xmlGrandParent != null &&
- !(xmlGrandParent instanceof Document) &&
- grandDesc != null &&
- grandDesc.acceptChild(nodeDesc)) {
- // This node is the last node of its parent.
- // If neither the parent nor the grandparent is a document,
- // then the node can be inserted right after the parent.
- // The parent node must actually accept this kind of child.
- if (testOnly) {
- return true;
- }
- xmlGrandParent.insertBefore(
- xmlParent.removeChild(xmlNode),
- xmlParent.getNextSibling());
- outSelectXmlNode[0] = xmlNode;
- }
- }
-
- return false;
- }
-
- //---------------------
-
- /**
- * Adds a new element of the given descriptor's type to the given UI parent node.
- *
- * This actually creates the corresponding XML node in the XML model, which in turn
- * will refresh the current tree view.
- *
- * @param uiParent An existing UI node or null to add to the tree root
- * @param uiSibling An existing UI node to insert right before. Can be null.
- * @param descriptor The descriptor of the element to add
- * @param updateLayout True if layout attributes should be set
- * @return The {@link UiElementNode} that has been added to the UI tree.
- */
- private UiElementNode addNewTreeElement(UiElementNode uiParent,
- UiElementNode uiSibling,
- ElementDescriptor descriptor,
- final boolean updateLayout) {
- commitPendingXmlChanges();
-
- List<UiElementNode> uiChildren = uiParent.getUiChildren();
- int n = uiChildren.size();
-
- // The default is to append at the end of the list.
- int index = n;
-
- if (uiSibling != null) {
- // Try to find the requested sibling.
- index = uiChildren.indexOf(uiSibling);
- if (index < 0) {
- // This sibling didn't exist. Should not happen but compensate
- // by simply adding to the end of the list.
- uiSibling = null;
- index = n;
- }
- }
-
- if (uiSibling == null) {
- // If we don't require any specific position, make sure to insert before the
- // first mandatory_last descriptor's position, if any.
-
- for (int i = 0; i < n; i++) {
- UiElementNode uiChild = uiChildren.get(i);
- if (uiChild.getDescriptor().getMandatory() == Mandatory.MANDATORY_LAST) {
- index = i;
- break;
- }
- }
- }
-
- final UiElementNode uiNew = uiParent.insertNewUiChild(index, descriptor);
- UiElementNode rootNode = getRootNode();
-
- rootNode.getEditor().wrapEditXmlModel(new Runnable() {
- @Override
- public void run() {
- DescriptorsUtils.setDefaultLayoutAttributes(uiNew, updateLayout);
- uiNew.createXmlNode();
- }
- });
- return uiNew;
- }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java
deleted file mode 100644
index 2aa56a826..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiElementDetail.java
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright (C) 2007 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.ui.tree;
-
-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.descriptors.SeparatorAttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper;
-import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper.ManifestSectionPart;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.ITreeSelection;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.ui.forms.IDetailsPage;
-import org.eclipse.ui.forms.IFormPart;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.events.ExpansionEvent;
-import org.eclipse.ui.forms.events.IExpansionListener;
-import org.eclipse.ui.forms.widgets.FormText;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.Section;
-import org.eclipse.ui.forms.widgets.SharedScrolledComposite;
-import org.eclipse.ui.forms.widgets.TableWrapData;
-import org.eclipse.ui.forms.widgets.TableWrapLayout;
-
-import java.util.Collection;
-import java.util.HashSet;
-
-/**
- * Details page for the {@link UiElementNode} nodes in the tree view.
- * <p/>
- * See IDetailsBase for more details.
- */
-class UiElementDetail implements IDetailsPage {
-
- /** The master-detail part, composed of a main tree and an auxiliary detail part */
- private ManifestSectionPart mMasterPart;
-
- private Section mMasterSection;
- private UiElementNode mCurrentUiElementNode;
- private Composite mCurrentTable;
- private boolean mIsDirty;
-
- private IManagedForm mManagedForm;
-
- private final UiTreeBlock mTree;
-
- public UiElementDetail(UiTreeBlock tree) {
- mTree = tree;
- mMasterPart = mTree.getMasterPart();
- mManagedForm = mMasterPart.getManagedForm();
- }
-
- /* (non-java doc)
- * Initializes the part.
- */
- @Override
- public void initialize(IManagedForm form) {
- mManagedForm = form;
- }
-
- /* (non-java doc)
- * Creates the contents of the page in the provided parent.
- */
- @Override
- public void createContents(Composite parent) {
- mMasterSection = createMasterSection(parent);
- }
-
- /* (non-java doc)
- * Called when the provided part has changed selection state.
- * <p/>
- * Only reply when our master part originates the selection.
- */
- @Override
- public void selectionChanged(IFormPart part, ISelection selection) {
- if (part == mMasterPart &&
- !selection.isEmpty() &&
- selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
-
- Object first = tree_selection.getFirstElement();
- if (first instanceof UiElementNode) {
- UiElementNode ui_node = (UiElementNode) first;
- createUiAttributeControls(mManagedForm, ui_node);
- }
- }
- }
-
- /* (non-java doc)
- * Instructs it to commit the new (modified) data back into the model.
- */
- @Override
- public void commit(boolean onSave) {
-
- mTree.getEditor().wrapEditXmlModel(new Runnable() {
- @Override
- public void run() {
- try {
- if (mCurrentUiElementNode != null) {
- mCurrentUiElementNode.commit();
- }
-
- // Finally reset the dirty flag if everything was saved properly
- mIsDirty = false;
- } catch (Exception e) {
- AdtPlugin.log(e, "Detail node failed to commit XML attribute!"); //$NON-NLS-1$
- }
- }
- });
- }
-
- @Override
- public void dispose() {
- // pass
- }
-
-
- /* (non-java doc)
- * Returns true if the part has been modified with respect to the data
- * loaded from the model.
- */
- @Override
- public boolean isDirty() {
- if (mCurrentUiElementNode != null && mCurrentUiElementNode.isDirty()) {
- markDirty();
- }
- return mIsDirty;
- }
-
- @Override
- public boolean isStale() {
- // pass
- return false;
- }
-
- /**
- * Called by the master part when the tree is refreshed after the framework resources
- * have been reloaded.
- */
- @Override
- public void refresh() {
- if (mCurrentTable != null) {
- mCurrentTable.dispose();
- mCurrentTable = null;
- }
- mCurrentUiElementNode = null;
- mMasterSection.getParent().pack(true /* changed */);
- }
-
- @Override
- public void setFocus() {
- // pass
- }
-
- @Override
- public boolean setFormInput(Object input) {
- // pass
- return false;
- }
-
- /**
- * Creates a TableWrapLayout in the DetailsPage, which in turns contains a Section.
- *
- * All the UI should be created in a layout which parent is the mSection itself.
- * The hierarchy is:
- * <pre>
- * DetailPage
- * + TableWrapLayout
- * + Section (with title/description && fill_grab horizontal)
- * + TableWrapLayout [*]
- * + Labels/Forms/etc... [*]
- * </pre>
- * Both items marked with [*] are created by the derived classes to fit their needs.
- *
- * @param parent Parent of the mSection (from createContents)
- * @return The new Section
- */
- private Section createMasterSection(Composite parent) {
- TableWrapLayout layout = new TableWrapLayout();
- layout.topMargin = 0;
- parent.setLayout(layout);
-
- FormToolkit toolkit = mManagedForm.getToolkit();
- Section section = toolkit.createSection(parent, Section.TITLE_BAR);
- section.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP));
- return section;
- }
-
- /**
- * Create the ui attribute controls to edit the attributes for the given
- * ElementDescriptor.
- * <p/>
- * This is called by the constructor.
- * Derived classes can override this if necessary.
- *
- * @param managedForm The managed form
- */
- private void createUiAttributeControls(
- final IManagedForm managedForm,
- final UiElementNode ui_node) {
-
- final ElementDescriptor elem_desc = ui_node.getDescriptor();
- mMasterSection.setText(String.format("Attributes for %1$s", ui_node.getShortDescription()));
-
- if (mCurrentUiElementNode != ui_node) {
- // Before changing the table, commit all dirty state.
- if (mIsDirty) {
- commit(false);
- }
- if (mCurrentTable != null) {
- mCurrentTable.dispose();
- mCurrentTable = null;
- }
-
- // To iterate over all attributes, we use the {@link ElementDescriptor} instead
- // of the {@link UiElementNode} because the attributes order is guaranteed in the
- // descriptor but not in the node itself.
- AttributeDescriptor[] attr_desc_list = ui_node.getAttributeDescriptors();
-
- // If the attribute list contains at least one SeparatorAttributeDescriptor,
- // sub-sections will be used. This needs to be known early as it influences the
- // creation of the master table.
- boolean useSubsections = false;
- for (AttributeDescriptor attr_desc : attr_desc_list) {
- if (attr_desc instanceof SeparatorAttributeDescriptor) {
- // Sub-sections will be used. The default sections should no longer be
- useSubsections = true;
- break;
- }
- }
-
- FormToolkit toolkit = managedForm.getToolkit();
- Composite masterTable = SectionHelper.createTableLayout(mMasterSection,
- toolkit, useSubsections ? 1 : 2 /* numColumns */);
- mCurrentTable = masterTable;
-
- mCurrentUiElementNode = ui_node;
-
- if (elem_desc.getTooltip() != null) {
- String tooltip;
- if (Sdk.getCurrent() != null &&
- Sdk.getCurrent().getDocumentationBaseUrl() != null) {
- tooltip = DescriptorsUtils.formatFormText(elem_desc.getTooltip(),
- elem_desc,
- Sdk.getCurrent().getDocumentationBaseUrl());
- } else {
- tooltip = elem_desc.getTooltip();
- }
-
- try {
- FormText text = SectionHelper.createFormText(masterTable, toolkit,
- true /* isHtml */, tooltip, true /* setupLayoutData */);
- text.addHyperlinkListener(mTree.getEditor().createHyperlinkListener());
- Image icon = elem_desc.getCustomizedIcon();
- if (icon != null) {
- text.setImage(DescriptorsUtils.IMAGE_KEY, icon);
- }
- } catch(Exception e) {
- // The FormText parser is really really basic and will fail as soon as the
- // HTML javadoc is ever so slightly malformatted.
- AdtPlugin.log(e,
- "Malformed javadoc, rejected by FormText for node %1$s: '%2$s'", //$NON-NLS-1$
- ui_node.getDescriptor().getXmlName(),
- tooltip);
-
- // Fallback to a pure text tooltip, no fancy HTML
- tooltip = DescriptorsUtils.formatTooltip(elem_desc.getTooltip());
- SectionHelper.createLabel(masterTable, toolkit, tooltip, tooltip);
- }
- }
-
- Composite table = useSubsections ? null : masterTable;
-
- for (AttributeDescriptor attr_desc : attr_desc_list) {
- if (attr_desc instanceof XmlnsAttributeDescriptor) {
- // Do not show hidden attributes
- continue;
- } else if (table == null || attr_desc instanceof SeparatorAttributeDescriptor) {
- String title = null;
- if (attr_desc instanceof SeparatorAttributeDescriptor) {
- // xmlName is actually the label of the separator
- title = attr_desc.getXmlLocalName();
- } else {
- title = String.format("Attributes from %1$s", elem_desc.getUiName());
- }
-
- table = createSubSectionTable(toolkit, masterTable, title);
- if (attr_desc instanceof SeparatorAttributeDescriptor) {
- continue;
- }
- }
-
- UiAttributeNode ui_attr = ui_node.findUiAttribute(attr_desc);
-
- if (ui_attr != null) {
- ui_attr.createUiControl(table, managedForm);
-
- if (ui_attr.getCurrentValue() != null &&
- ui_attr.getCurrentValue().length() > 0) {
- ((Section) table.getParent()).setExpanded(true);
- }
- } else {
- // The XML has an extra unknown attribute.
- // This is not expected to happen so it is ignored.
- AdtPlugin.log(IStatus.INFO,
- "Attribute %1$s not declared in node %2$s, ignored.", //$NON-NLS-1$
- attr_desc.getXmlLocalName(),
- ui_node.getDescriptor().getXmlName());
- }
- }
-
- // Create a sub-section for the unknown attributes.
- // It is initially hidden till there are some attributes to show here.
- final Composite unknownTable = createSubSectionTable(toolkit, masterTable,
- "Unknown XML Attributes");
- unknownTable.getParent().setVisible(false); // set section to not visible
- final HashSet<UiAttributeNode> reference = new HashSet<UiAttributeNode>();
-
- final IUiUpdateListener updateListener = new IUiUpdateListener() {
- @Override
- public void uiElementNodeUpdated(UiElementNode uiNode, UiUpdateState state) {
- if (state == UiUpdateState.ATTR_UPDATED) {
- updateUnknownAttributesSection(uiNode, unknownTable, managedForm,
- reference);
- }
- }
- };
- ui_node.addUpdateListener(updateListener);
-
- // remove the listener when the UI is disposed
- unknownTable.addDisposeListener(new DisposeListener() {
- @Override
- public void widgetDisposed(DisposeEvent e) {
- ui_node.removeUpdateListener(updateListener);
- }
- });
-
- updateUnknownAttributesSection(ui_node, unknownTable, managedForm, reference);
-
- mMasterSection.getParent().pack(true /* changed */);
- }
- }
-
- /**
- * Create a sub Section and its embedding wrapper table with 2 columns.
- * @return The table, child of a new section.
- */
- private Composite createSubSectionTable(FormToolkit toolkit,
- Composite masterTable, String title) {
-
- // The Section composite seems to ignore colspan when assigned a TableWrapData so
- // if the parent is a table with more than one column an extra table with one column
- // is inserted to respect colspan.
- int parentNumCol = ((TableWrapLayout) masterTable.getLayout()).numColumns;
- if (parentNumCol > 1) {
- masterTable = SectionHelper.createTableLayout(masterTable, toolkit, 1);
- TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB);
- twd.maxWidth = AndroidXmlEditor.TEXT_WIDTH_HINT;
- twd.colspan = parentNumCol;
- masterTable.setLayoutData(twd);
- }
-
- Composite table;
- Section section = toolkit.createSection(masterTable,
- Section.TITLE_BAR | Section.TWISTIE);
-
- // Add an expansion listener that will trigger a reflow on the parent
- // ScrolledPageBook (which is actually a SharedScrolledComposite). This will
- // recompute the correct size and adjust the scrollbar as needed.
- section.addExpansionListener(new IExpansionListener() {
- @Override
- public void expansionStateChanged(ExpansionEvent e) {
- reflowMasterSection();
- }
-
- @Override
- public void expansionStateChanging(ExpansionEvent e) {
- // pass
- }
- });
-
- section.setText(title);
- section.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB,
- TableWrapData.TOP));
- table = SectionHelper.createTableLayout(section, toolkit, 2 /* numColumns */);
- return table;
- }
-
- /**
- * Reflow the parent ScrolledPageBook (which is actually a SharedScrolledComposite).
- * This will recompute the correct size and adjust the scrollbar as needed.
- */
- private void reflowMasterSection() {
- for(Composite c = mMasterSection; c != null; c = c.getParent()) {
- if (c instanceof SharedScrolledComposite) {
- ((SharedScrolledComposite) c).reflow(true /* flushCache */);
- break;
- }
- }
- }
-
- /**
- * Updates the unknown attributes section for the UI Node.
- */
- private void updateUnknownAttributesSection(UiElementNode ui_node,
- final Composite unknownTable, final IManagedForm managedForm,
- HashSet<UiAttributeNode> reference) {
- Collection<UiAttributeNode> ui_attrs = ui_node.getUnknownUiAttributes();
- Section section = ((Section) unknownTable.getParent());
- boolean needs_reflow = false;
-
- // The table was created hidden, show it if there are unknown attributes now
- if (ui_attrs.size() > 0 && !section.isVisible()) {
- section.setVisible(true);
- needs_reflow = true;
- }
-
- // Compare the new attribute set with the old "reference" one
- boolean has_differences = ui_attrs.size() != reference.size();
- if (!has_differences) {
- for (UiAttributeNode ui_attr : ui_attrs) {
- if (!reference.contains(ui_attr)) {
- has_differences = true;
- break;
- }
- }
- }
-
- if (has_differences) {
- needs_reflow = true;
- reference.clear();
-
- // Remove all children of the table
- for (Control c : unknownTable.getChildren()) {
- c.dispose();
- }
-
- // Recreate all attributes UI
- for (UiAttributeNode ui_attr : ui_attrs) {
- reference.add(ui_attr);
- ui_attr.createUiControl(unknownTable, managedForm);
-
- if (ui_attr.getCurrentValue() != null && ui_attr.getCurrentValue().length() > 0) {
- section.setExpanded(true);
- }
- }
- }
-
- if (needs_reflow) {
- reflowMasterSection();
- }
- }
-
- /**
- * Marks the part dirty. Called as a result of user interaction with the widgets in the
- * section.
- */
- private void markDirty() {
- if (!mIsDirty) {
- mIsDirty = true;
- mManagedForm.dirtyStateChanged();
- }
- }
-}
-
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeContentProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeContentProvider.java
deleted file mode 100644
index 14049cf86..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeContentProvider.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2007 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.ui.tree;
-
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.Viewer;
-
-import java.util.ArrayList;
-
-/**
- * UiModelTreeContentProvider is a trivial implementation of {@link ITreeContentProvider}
- * where elements are expected to be instances of {@link UiElementNode}.
- */
-class UiModelTreeContentProvider implements ITreeContentProvider {
-
- /** 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. */
- private ElementDescriptor[] mDescriptorFilters;
- /** The uiRootNode of the model. */
- private final UiElementNode mUiRootNode;
-
- public UiModelTreeContentProvider(UiElementNode uiRootNode,
- ElementDescriptor[] descriptorFilters) {
- mUiRootNode = uiRootNode;
- mDescriptorFilters = descriptorFilters;
- }
-
- /* (non-java doc)
- * Returns all the UI node children of the given element or null if not the right kind
- * of object. */
- @Override
- public Object[] getChildren(Object parentElement) {
- if (parentElement instanceof UiElementNode) {
- UiElementNode node = (UiElementNode) parentElement;
- return node.getUiChildren().toArray();
- }
- return null;
- }
-
- /* (non-java doc)
- * Returns the parent of a given UI node or null if it's a root node or it's not the
- * right kind of node. */
- @Override
- public Object getParent(Object element) {
- if (element instanceof UiElementNode) {
- UiElementNode node = (UiElementNode) element;
- return node.getUiParent();
- }
- return null;
- }
-
- /* (non-java doc)
- * Returns true if the UI node has any UI children nodes. */
- @Override
- public boolean hasChildren(Object element) {
- if (element instanceof UiElementNode) {
- UiElementNode node = (UiElementNode) element;
- return node.getUiChildren().size() > 0;
- }
- return false;
- }
-
- /* (non-java doc)
- * Get root elements for the tree. These are all the UI nodes that
- * match the filter descriptor in the current root node.
- * <p/>
- * Although not documented, it seems this method should not return null.
- * At worse, it should return new Object[0].
- * <p/>
- * inputElement is not currently used. The root node and the filter are given
- * by the enclosing class.
- */
- @Override
- public Object[] getElements(Object inputElement) {
- ArrayList<UiElementNode> roots = new ArrayList<UiElementNode>();
- if (mUiRootNode != null) {
- for (UiElementNode ui_node : mUiRootNode.getUiChildren()) {
- if (mDescriptorFilters == null || mDescriptorFilters.length == 0) {
- roots.add(ui_node);
- } else {
- for (ElementDescriptor filter : mDescriptorFilters) {
- if (ui_node.getDescriptor() == filter) {
- roots.add(ui_node);
- }
- }
- }
- }
- }
-
- return roots.toArray();
- }
-
- @Override
- public void dispose() {
- // pass
- }
-
- @Override
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- // pass
- }
-}
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java
deleted file mode 100644
index 337319761..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiModelTreeLabelProvider.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2007 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.ui.tree;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
-
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.jface.viewers.ILabelProviderListener;
-import org.eclipse.swt.graphics.Image;
-
-/**
- * UiModelTreeLabelProvider is a trivial implementation of {@link ILabelProvider}
- * where elements are expected to derive from {@link UiElementNode} or
- * from {@link ElementDescriptor}.
- *
- * It is used by both the master tree viewer and by the list in the Add... selection dialog.
- */
-public class UiModelTreeLabelProvider implements ILabelProvider {
-
- public UiModelTreeLabelProvider() {
- }
-
- /**
- * Returns the element's logo with a fallback on the android logo.
- */
- @Override
- public Image getImage(Object element) {
- ElementDescriptor desc = null;
- UiElementNode node = null;
-
- if (element instanceof ElementDescriptor) {
- desc = (ElementDescriptor) element;
- } else if (element instanceof UiElementNode) {
- node = (UiElementNode) element;
- desc = node.getDescriptor();
- }
-
- if (desc != null) {
- Image img = desc.getCustomizedIcon();
- if (img != null) {
- if (node != null && node.hasError()) {
- return IconFactory.getInstance().addErrorIcon(img);
- } else {
- return img;
- }
- }
- }
-
- return AdtPlugin.getAndroidLogo();
- }
-
- /**
- * Uses UiElementNode.shortDescription for the label for this tree item.
- */
- @Override
- public String getText(Object element) {
- if (element instanceof ElementDescriptor) {
- ElementDescriptor desc = (ElementDescriptor) element;
- return desc.getUiName();
- } else if (element instanceof UiElementNode) {
- UiElementNode node = (UiElementNode) element;
- return node.getShortDescription();
- }
- return element.toString();
- }
-
- @Override
- public void addListener(ILabelProviderListener listener) {
- // pass
- }
-
- @Override
- public void dispose() {
- // pass
- }
-
- @Override
- public boolean isLabelProperty(Object element, String property) {
- // pass
- return false;
- }
-
- @Override
- public void removeListener(ILabelProviderListener listener) {
- // pass
- }
-}
-
-
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java
deleted file mode 100644
index d11b8a4c6..000000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/ui/tree/UiTreeBlock.java
+++ /dev/null
@@ -1,946 +0,0 @@
-/*
- * Copyright (C) 2007 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.ui.tree;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
-import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper;
-import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper.ManifestSectionPart;
-import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener;
-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.sdk.Sdk.ITargetChangeListener;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk.TargetChangeListener;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.jface.action.Action;
-import org.eclipse.jface.action.IMenuListener;
-import org.eclipse.jface.action.IMenuManager;
-import org.eclipse.jface.action.MenuManager;
-import org.eclipse.jface.action.Separator;
-import org.eclipse.jface.action.ToolBarManager;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.ITreeSelection;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TreePath;
-import org.eclipse.jface.viewers.TreeSelection;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.viewers.ViewerComparator;
-import org.eclipse.jface.viewers.ViewerFilter;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.dnd.Clipboard;
-import org.eclipse.swt.events.DisposeEvent;
-import org.eclipse.swt.events.DisposeListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-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.Menu;
-import org.eclipse.swt.widgets.ToolBar;
-import org.eclipse.swt.widgets.Tree;
-import org.eclipse.ui.forms.DetailsPart;
-import org.eclipse.ui.forms.IDetailsPage;
-import org.eclipse.ui.forms.IDetailsPageProvider;
-import org.eclipse.ui.forms.IManagedForm;
-import org.eclipse.ui.forms.MasterDetailsBlock;
-import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.ui.forms.widgets.Section;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-
-/**
- * {@link UiTreeBlock} is a {@link MasterDetailsBlock} which displays a tree view for
- * a specific set of {@link UiElementNode}.
- * <p/>
- * For a given UI element node, the tree view displays all first-level children that
- * match a given type (given by an {@link ElementDescriptor}. All children from these
- * nodes are also displayed.
- * <p/>
- * In the middle next to the tree are some controls to add or delete tree nodes.
- * On the left is a details part that displays all the visible UI attributes for a given
- * selected UI element node.
- */
-public final class UiTreeBlock extends MasterDetailsBlock implements ICommitXml {
-
- /** Height hint for the tree view. Helps the grid layout resize properly on smaller screens. */
- private static final int TREE_HEIGHT_HINT = 50;
-
- /** Container editor */
- AndroidXmlEditor mEditor;
- /** The root {@link UiElementNode} which contains all the elements that are to be
- * manipulated by this tree view. In general this is the manifest UI node. */
- private UiElementNode mUiRootNode;
- /** 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 or empty to mean everything
- * can be displayed. */
- private ElementDescriptor[] mDescriptorFilters;
- /** The title for the master-detail part (displayed on the top "tab" on top of the tree) */
- private String mTitle;
- /** The description for the master-detail part (displayed on top of the tree view) */
- private String mDescription;
- /** The master-detail part, composed of a main tree and an auxiliary detail part */
- private ManifestSectionPart mMasterPart;
- /** The tree viewer in the master-detail part */
- private TreeViewer mTreeViewer;
- /** The "add" button for the tree view */
- private Button mAddButton;
- /** The "remove" button for the tree view */
- private Button mRemoveButton;
- /** The "up" button for the tree view */
- private Button mUpButton;
- /** The "down" button for the tree view */
- private Button mDownButton;
- /** The Managed Form used to create the master part */
- private IManagedForm mManagedForm;
- /** Reference to the details part of the tree master block. */
- private DetailsPart mDetailsPart;
- /** Reference to the clipboard for copy-paste */
- private Clipboard mClipboard;
- /** Listener to refresh the tree viewer when the parent's node has been updated */
- private IUiUpdateListener mUiRefreshListener;
- /** Listener to enable/disable the UI based on the application node's presence */
- private IUiUpdateListener mUiEnableListener;
- /** An adapter/wrapper to use the add/remove/up/down tree edit actions. */
- private UiTreeActions mUiTreeActions;
- /**
- * True if the root node can be created on-demand (i.e. as needed as
- * soon as children exist). False if an external entity controls the existence of the
- * root node. In practise, this is false for the manifest application page (the actual
- * "application" node is managed by the ApplicationToggle part) whereas it is true
- * for all other tree pages.
- */
- private final boolean mAutoCreateRoot;
-
-
- /**
- * Creates a new {@link MasterDetailsBlock} that will display all UI nodes matching the
- * given filter in the given root node.
- *
- * @param editor The parent manifest editor.
- * @param uiRootNode The root {@link UiElementNode} which contains all the elements that are
- * to be manipulated by this tree view. In general this is the manifest UI node or the
- * application UI node. This cannot be null.
- * @param autoCreateRoot True if the root node can be created on-demand (i.e. as needed as
- * soon as children exist). False if an external entity controls the existence of the
- * root node. In practise, this is false for the manifest application page (the actual
- * "application" node is managed by the ApplicationToggle part) whereas it is true
- * for all other tree pages.
- * @param descriptorFilters A list of descriptors of the elements to be displayed as root in
- * this tree view. Use null or an empty list to accept any kind of node.
- * @param title Title for the section
- * @param description Description for the section
- */
- public UiTreeBlock(AndroidXmlEditor editor,
- UiElementNode uiRootNode,
- boolean autoCreateRoot,
- ElementDescriptor[] descriptorFilters,
- String title,
- String description) {
- mEditor = editor;
- mUiRootNode = uiRootNode;
- mAutoCreateRoot = autoCreateRoot;
- mDescriptorFilters = descriptorFilters;
- mTitle = title;
- mDescription = description;
- }
-
- /** @returns The container editor */
- AndroidXmlEditor getEditor() {
- return mEditor;
- }
-
- /** @returns The reference to the clipboard for copy-paste */
- Clipboard getClipboard() {
- return mClipboard;
- }
-
- /** @returns The master-detail part, composed of a main tree and an auxiliary detail part */
- ManifestSectionPart getMasterPart() {
- return mMasterPart;
- }
-
- /**
- * Returns the {@link UiElementNode} for the current model.
- * <p/>
- * This is used by the content provider attached to {@link #mTreeViewer} since
- * the uiRootNode changes after each call to
- * {@link #changeRootAndDescriptors(UiElementNode, ElementDescriptor[], boolean)}.
- */
- public UiElementNode getRootNode() {
- return mUiRootNode;
- }
-
- @Override
- protected void createMasterPart(final IManagedForm managedForm, Composite parent) {
- FormToolkit toolkit = managedForm.getToolkit();
-
- mManagedForm = managedForm;
- mMasterPart = new ManifestSectionPart(parent, toolkit);
- Section section = mMasterPart.getSection();
- section.setText(mTitle);
- section.setDescription(mDescription);
- section.setLayout(new GridLayout());
- section.setLayoutData(new GridData(GridData.FILL_BOTH));
-
- Composite grid = SectionHelper.createGridLayout(section, toolkit, 2);
-
- Tree tree = createTreeViewer(toolkit, grid, managedForm);
- createButtons(toolkit, grid);
- createTreeContextMenu(tree);
- createSectionActions(section, toolkit);
- }
-
- private void createSectionActions(Section section, FormToolkit toolkit) {
- ToolBarManager manager = new ToolBarManager(SWT.FLAT);
- manager.removeAll();
-
- ToolBar toolbar = manager.createControl(section);
- section.setTextClient(toolbar);
-
- ElementDescriptor[] descs = mDescriptorFilters;
- if (descs == null && mUiRootNode != null) {
- descs = mUiRootNode.getDescriptor().getChildren();
- }
-
- if (descs != null && descs.length > 1) {
- for (ElementDescriptor desc : descs) {
- manager.add(new DescriptorFilterAction(desc));
- }
- }
-
- manager.add(new TreeSortAction());
-
- manager.update(true /*force*/);
- }
-
- /**
- * Creates the tree and its viewer
- * @return The tree control
- */
- private Tree createTreeViewer(FormToolkit toolkit, Composite grid,
- final IManagedForm managedForm) {
- // Note: we *could* use a FilteredTree instead of the Tree+TreeViewer here.
- // However the class must be adapted to create an adapted toolkit tree.
- final Tree tree = toolkit.createTree(grid, SWT.MULTI);
- GridData gd = new GridData(GridData.FILL_BOTH);
- gd.widthHint = AndroidXmlEditor.TEXT_WIDTH_HINT;
- gd.heightHint = TREE_HEIGHT_HINT;
- tree.setLayoutData(gd);
-
- mTreeViewer = new TreeViewer(tree);
- mTreeViewer.setContentProvider(new UiModelTreeContentProvider(mUiRootNode, mDescriptorFilters));
- mTreeViewer.setLabelProvider(new UiModelTreeLabelProvider());
- mTreeViewer.setInput("unused"); //$NON-NLS-1$
-
- // Create a listener that reacts to selections on the tree viewer.
- // When a selection is made, ask the managed form to propagate an event to
- // all parts in the managed form.
- // This is picked up by UiElementDetail.selectionChanged().
- mTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
- @Override
- public void selectionChanged(SelectionChangedEvent event) {
- managedForm.fireSelectionChanged(mMasterPart, event.getSelection());
- adjustTreeButtons(event.getSelection());
- }
- });
-
- // Create three listeners:
- // - One to refresh the tree viewer when the parent's node has been updated
- // - One to refresh the tree viewer when the framework resources have changed
- // - One to enable/disable the UI based on the application node's presence.
- mUiRefreshListener = new IUiUpdateListener() {
- @Override
- public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
- mTreeViewer.refresh();
- }
- };
-
- mUiEnableListener = new IUiUpdateListener() {
- @Override
- public void uiElementNodeUpdated(UiElementNode ui_node, UiUpdateState state) {
- // The UiElementNode for the application XML node always exists, even
- // if there is no corresponding XML node in the XML file.
- //
- // Normally, we enable the UI here if the XML node is not null.
- //
- // However if mAutoCreateRoot is true, the root node will be created on-demand
- // so the tree/block is always enabled.
- boolean exists = mAutoCreateRoot || (ui_node.getXmlNode() != null);
- if (mMasterPart != null) {
- Section section = mMasterPart.getSection();
- if (section.getEnabled() != exists) {
- section.setEnabled(exists);
- for (Control c : section.getChildren()) {
- c.setEnabled(exists);
- }
- }
- }
- }
- };
-
- /** Listener to update the root node if the target of the file is changed because of a
- * SDK location change or a project target change */
- final ITargetChangeListener targetListener = new TargetChangeListener() {
- @Override
- public IProject getProject() {
- if (mEditor != null) {
- return mEditor.getProject();
- }
-
- return null;
- }
-
- @Override
- public void reload() {
- // If a details part has been created, we need to "refresh" it too.
- if (mDetailsPart != null) {
- // The details part does not directly expose access to its internal
- // page book. Instead it is possible to resize the page book to 0 and then
- // back to its original value, which has the side effect of removing all
- // existing cached pages.
- int limit = mDetailsPart.getPageLimit();
- mDetailsPart.setPageLimit(0);
- mDetailsPart.setPageLimit(limit);
- }
- // Refresh the tree, preserving the selection if possible.
- mTreeViewer.refresh();
- }
- };
-
- // Setup the listeners
- changeRootAndDescriptors(mUiRootNode, mDescriptorFilters, false /* refresh */);
-
- // Listen on resource framework changes to refresh the tree
- AdtPlugin.getDefault().addTargetListener(targetListener);
-
- // Remove listeners when the tree widget gets disposed.
- tree.addDisposeListener(new DisposeListener() {
- @Override
- public void widgetDisposed(DisposeEvent e) {
- if (mUiRootNode != null) {
- UiElementNode node = mUiRootNode.getUiParent() != null ?
- mUiRootNode.getUiParent() :
- mUiRootNode;
-
- if (node != null) {
- node.removeUpdateListener(mUiRefreshListener);
- }
- mUiRootNode.removeUpdateListener(mUiEnableListener);
- }
-
- AdtPlugin.getDefault().removeTargetListener(targetListener);
- if (mClipboard != null) {
- mClipboard.dispose();
- mClipboard = null;
- }
- }
- });
-
- // Get a new clipboard reference. It is disposed when the tree is disposed.
- mClipboard = new Clipboard(tree.getDisplay());
-
- return tree;
- }
-
- /**
- * Changes the UI root node and the descriptor filters of the tree.
- * <p/>
- * This removes the listeners attached to the old root node and reattaches them to the
- * new one.
- *
- * @param uiRootNode The root {@link UiElementNode} which contains all the elements that are
- * to be manipulated by this tree view. In general this is the manifest UI node or the
- * application UI node. This cannot be null.
- * @param descriptorFilters A list of descriptors of the elements to be displayed as root in
- * this tree view. Use null or an empty list to accept any kind of node.
- * @param forceRefresh If tree, forces the tree to refresh
- */
- public void changeRootAndDescriptors(UiElementNode uiRootNode,
- ElementDescriptor[] descriptorFilters, boolean forceRefresh) {
- UiElementNode node;
-
- // Remove previous listeners if any
- if (mUiRootNode != null) {
- node = mUiRootNode.getUiParent() != null ? mUiRootNode.getUiParent() : mUiRootNode;
- node.removeUpdateListener(mUiRefreshListener);
- mUiRootNode.removeUpdateListener(mUiEnableListener);
- }
-
- mUiRootNode = uiRootNode;
- mDescriptorFilters = descriptorFilters;
-
- mTreeViewer.setContentProvider(
- new UiModelTreeContentProvider(mUiRootNode, mDescriptorFilters));
-
- // Listen on structural changes on the root node of the tree
- // If the node has a parent, listen on the parent instead.
- if (mUiRootNode != null) {
- node = mUiRootNode.getUiParent() != null ? mUiRootNode.getUiParent() : mUiRootNode;
-
- if (node != null) {
- node.addUpdateListener(mUiRefreshListener);
- }
-
- // Use the root node to listen to its presence.
- mUiRootNode.addUpdateListener(mUiEnableListener);
-
- // Initialize the enabled/disabled state
- mUiEnableListener.uiElementNodeUpdated(mUiRootNode, null /* state, not used */);
- }
-
- if (forceRefresh) {
- mTreeViewer.refresh();
- }
-
- createSectionActions(mMasterPart.getSection(), mManagedForm.getToolkit());
- }
-
- /**
- * Creates the buttons next to the tree.
- */
- private void createButtons(FormToolkit toolkit, Composite grid) {
-
- mUiTreeActions = new UiTreeActions();
-
- Composite button_grid = SectionHelper.createGridLayout(grid, toolkit, 1);
- button_grid.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
- mAddButton = toolkit.createButton(button_grid, "Add...", SWT.PUSH);
- SectionHelper.addControlTooltip(mAddButton, "Adds a new element.");
- mAddButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL |
- GridData.VERTICAL_ALIGN_BEGINNING));
-
- mAddButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- doTreeAdd();
- }
- });
-
- mRemoveButton = toolkit.createButton(button_grid, "Remove...", SWT.PUSH);
- SectionHelper.addControlTooltip(mRemoveButton, "Removes an existing selected element.");
- mRemoveButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
- mRemoveButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- doTreeRemove();
- }
- });
-
- mUpButton = toolkit.createButton(button_grid, "Up", SWT.PUSH);
- SectionHelper.addControlTooltip(mRemoveButton, "Moves the selected element up.");
- mUpButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
- mUpButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- doTreeUp();
- }
- });
-
- mDownButton = toolkit.createButton(button_grid, "Down", SWT.PUSH);
- SectionHelper.addControlTooltip(mRemoveButton, "Moves the selected element down.");
- mDownButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
- mDownButton.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- super.widgetSelected(e);
- doTreeDown();
- }
- });
-
- adjustTreeButtons(TreeSelection.EMPTY);
- }
-
- private void createTreeContextMenu(Tree tree) {
- MenuManager menuManager = new MenuManager();
- menuManager.setRemoveAllWhenShown(true);
- menuManager.addMenuListener(new IMenuListener() {
- /**
- * The menu is about to be shown. The menu manager has already been
- * requested to remove any existing menu item. This method gets the
- * tree selection and if it is of the appropriate type it re-creates
- * the necessary actions.
- */
- @Override
- public void menuAboutToShow(IMenuManager manager) {
- ISelection selection = mTreeViewer.getSelection();
- if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
- doCreateMenuAction(manager, selected);
- return;
- }
- doCreateMenuAction(manager, null /* ui_node */);
- }
- });
- Menu contextMenu = menuManager.createContextMenu(tree);
- tree.setMenu(contextMenu);
- }
-
- /**
- * Adds the menu actions to the context menu when the given UI node is selected in
- * the tree view.
- *
- * @param manager The context menu manager
- * @param selected The UI nodes selected in the tree. Can be null, in which case the root
- * is to be modified.
- */
- private void doCreateMenuAction(IMenuManager manager, ArrayList<UiElementNode> selected) {
- if (selected != null) {
- boolean hasXml = false;
- for (UiElementNode uiNode : selected) {
- if (uiNode.getXmlNode() != null) {
- hasXml = true;
- break;
- }
- }
-
- if (hasXml) {
- manager.add(new CopyCutAction(getEditor(), getClipboard(),
- null, selected, true /* cut */));
- manager.add(new CopyCutAction(getEditor(), getClipboard(),
- null, selected, false /* cut */));
-
- // Can't paste with more than one element selected (the selection is the target)
- if (selected.size() <= 1) {
- // Paste is not valid if it would add a second element on a terminal element
- // which parent is a document -- an XML document can only have one child. This
- // means paste is valid if the current UI node can have children or if the
- // parent is not a document.
- UiElementNode ui_root = selected.get(0).getUiRoot();
- if (ui_root.getDescriptor().hasChildren() ||
- !(ui_root.getUiParent() instanceof UiDocumentNode)) {
- manager.add(new PasteAction(getEditor(), getClipboard(), selected.get(0)));
- }
- }
- manager.add(new Separator());
- }
- }
-
- // Append "add" and "remove" actions. They do the same thing as the add/remove
- // buttons on the side.
- IconFactory factory = IconFactory.getInstance();
-
- // "Add" makes sense only if there's 0 or 1 item selected since the
- // one selected item becomes the target.
- if (selected == null || selected.size() <= 1) {
- manager.add(new Action("Add...", factory.getImageDescriptor("add")) { //$NON-NLS-1$
- @Override
- public void run() {
- super.run();
- doTreeAdd();
- }
- });
- }
-
- if (selected != null) {
- if (selected != null) {
- manager.add(new Action("Remove", factory.getImageDescriptor("delete")) { //$NON-NLS-1$
- @Override
- public void run() {
- super.run();
- doTreeRemove();
- }
- });
- }
- manager.add(new Separator());
-
- manager.add(new Action("Up", factory.getImageDescriptor("up")) { //$NON-NLS-1$
- @Override
- public void run() {
- super.run();
- doTreeUp();
- }
- });
- manager.add(new Action("Down", factory.getImageDescriptor("down")) { //$NON-NLS-1$
- @Override
- public void run() {
- super.run();
- doTreeDown();
- }
- });
- }
- }
-
-
- /**
- * This is called by the tree when a selection is made.
- * It enables/disables the buttons associated with the tree depending on the current
- * selection.
- *
- * @param selection The current tree selection (same as mTreeViewer.getSelection())
- */
- private void adjustTreeButtons(ISelection selection) {
- mRemoveButton.setEnabled(!selection.isEmpty() && selection instanceof ITreeSelection);
- mUpButton.setEnabled(canDoTreeUp(selection));
- mDownButton.setEnabled(canDoTreeDown(selection));
- }
-
- /**
- * An adapter/wrapper to use the add/remove/up/down tree edit actions.
- */
- private class UiTreeActions extends UiActions {
- @Override
- protected UiElementNode getRootNode() {
- return mUiRootNode;
- }
-
- @Override
- protected void selectUiNode(UiElementNode uiNodeToSelect) {
- // Select the new item
- if (uiNodeToSelect != null) {
- LinkedList<UiElementNode> segments = new LinkedList<UiElementNode>();
- for (UiElementNode ui_node = uiNodeToSelect; ui_node != mUiRootNode;
- ui_node = ui_node.getUiParent()) {
- segments.add(0, ui_node);
- }
- if (segments.size() > 0) {
- mTreeViewer.setSelection(new TreeSelection(new TreePath(segments.toArray())));
- } else {
- mTreeViewer.setSelection(null);
- }
- }
- }
-
- @Override
- public void commitPendingXmlChanges() {
- commitManagedForm();
- }
- }
-
- /**
- * Filters an ITreeSelection to only keep the {@link UiElementNode}s (in case there's
- * something else in there).
- *
- * @return A new list of {@link UiElementNode} with at least one item or null.
- */
- private ArrayList<UiElementNode> filterSelection(ITreeSelection selection) {
- ArrayList<UiElementNode> selected = new ArrayList<UiElementNode>();
-
- for (Iterator<Object> it = selection.iterator(); it.hasNext(); ) {
- Object selectedObj = it.next();
-
- if (selectedObj instanceof UiElementNode) {
- selected.add((UiElementNode) selectedObj);
- }
- }
-
- return selected.size() > 0 ? selected : null;
- }
-
- /**
- * Called when the "Add..." button next to the tree view is selected.
- *
- * Displays a selection dialog that lets the user select which kind of node
- * to create, depending on the current selection.
- */
- private void doTreeAdd() {
- UiElementNode ui_node = mUiRootNode;
- ISelection selection = mTreeViewer.getSelection();
- if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ITreeSelection tree_selection = (ITreeSelection) selection;
- Object first = tree_selection.getFirstElement();
- if (first != null && first instanceof UiElementNode) {
- ui_node = (UiElementNode) first;
- }
- }
-
- mUiTreeActions.doAdd(
- ui_node,
- mDescriptorFilters,
- mTreeViewer.getControl().getShell(),
- (ILabelProvider) mTreeViewer.getLabelProvider());
- }
-
- /**
- * Called when the "Remove" button is selected.
- *
- * If the tree has a selection, remove it.
- * This simply deletes the XML node attached to the UI node: when the XML model fires the
- * update event, the tree will get refreshed.
- */
- protected void doTreeRemove() {
- ISelection selection = mTreeViewer.getSelection();
- if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
- mUiTreeActions.doRemove(selected, mTreeViewer.getControl().getShell());
- }
- }
-
- /**
- * Called when the "Up" button is selected.
- * <p/>
- * If the tree has a selection, move it up, either in the child list or as the last child
- * of the previous parent.
- */
- protected void doTreeUp() {
- ISelection selection = mTreeViewer.getSelection();
- if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
- mUiTreeActions.doUp(selected, mDescriptorFilters);
- }
- }
-
- /**
- * Checks whether the "up" action can be done on the current selection.
- *
- * @param selection The current tree selection.
- * @return True if all the selected nodes can be moved up.
- */
- protected boolean canDoTreeUp(ISelection selection) {
- if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
- return mUiTreeActions.canDoUp(selected, mDescriptorFilters);
- }
-
- return false;
- }
-
- /**
- * Called when the "Down" button is selected.
- *
- * If the tree has a selection, move it down, either in the same child list or as the
- * first child of the next parent.
- */
- protected void doTreeDown() {
- ISelection selection = mTreeViewer.getSelection();
- if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
- mUiTreeActions.doDown(selected, mDescriptorFilters);
- }
- }
-
- /**
- * Checks whether the "down" action can be done on the current selection.
- *
- * @param selection The current tree selection.
- * @return True if all the selected nodes can be moved down.
- */
- protected boolean canDoTreeDown(ISelection selection) {
- if (!selection.isEmpty() && selection instanceof ITreeSelection) {
- ArrayList<UiElementNode> selected = filterSelection((ITreeSelection) selection);
- return mUiTreeActions.canDoDown(selected, mDescriptorFilters);
- }
-
- return false;
- }
-
- /**
- * Commits the current managed form (the one associated with our master part).
- * As a side effect, this will commit the current UiElementDetails page.
- */
- void commitManagedForm() {
- if (mManagedForm != null) {
- mManagedForm.commit(false /* onSave */);
- }
- }
-
- /* Implements ICommitXml for CopyCutAction */
- @Override
- public void commitPendingXmlChanges() {
- commitManagedForm();
- }
-
- @Override
- protected void createToolBarActions(IManagedForm managedForm) {
- // Pass. Not used, toolbar actions are defined by createSectionActions().
- }
-
- @Override
- protected void registerPages(DetailsPart inDetailsPart) {
- // Keep a reference on the details part (the super class doesn't provide a getter
- // for it.)
- mDetailsPart = inDetailsPart;
-
- // The page selection mechanism does not use pages registered by association with
- // a node class. Instead it uses a custom details page provider that provides a
- // new UiElementDetail instance for each node instance. A limit of 5 pages is
- // then set (the value is arbitrary but should be reasonable) for the internal
- // page book.
- inDetailsPart.setPageLimit(5);
-
- final UiTreeBlock tree = this;
-
- inDetailsPart.setPageProvider(new IDetailsPageProvider() {
- @Override
- public IDetailsPage getPage(Object key) {
- if (key instanceof UiElementNode) {
- return new UiElementDetail(tree);
- }
- return null;
- }
-
- @Override
- public Object getPageKey(Object object) {
- return object; // use node object as key
- }
- });
- }
-
- /**
- * An alphabetic sort action for the tree viewer.
- */
- private class TreeSortAction extends Action {
-
- private ViewerComparator mComparator;
-
- public TreeSortAction() {
- super("Sorts elements alphabetically.", AS_CHECK_BOX);
- setImageDescriptor(IconFactory.getInstance().getImageDescriptor("az_sort")); //$NON-NLS-1$
-
- if (mTreeViewer != null) {
- boolean is_sorted = mTreeViewer.getComparator() != null;
- setChecked(is_sorted);
- }
- }
-
- /**
- * Called when the button is selected. Toggles the tree viewer comparator.
- */
- @Override
- public void run() {
- if (mTreeViewer == null) {
- notifyResult(false /*success*/);
- return;
- }
-
- ViewerComparator comp = mTreeViewer.getComparator();
- if (comp != null) {
- // Tree is currently sorted.
- // Save currently comparator and remove it
- mComparator = comp;
- mTreeViewer.setComparator(null);
- } else {
- // Tree is not currently sorted.
- // Reuse or add a new comparator.
- if (mComparator == null) {
- mComparator = new ViewerComparator();
- }
- mTreeViewer.setComparator(mComparator);
- }
-
- notifyResult(true /*success*/);
- }
- }
-
- /**
- * A filter on descriptor for the tree viewer.
- * <p/>
- * The tree viewer will contain many of these actions and only one can be enabled at a
- * given time. When no action is selected, everything is displayed.
- * <p/>
- * Since "radio"-like actions do not allow for unselecting all of them, we manually
- * handle the exclusive radio button-like property: when an action is selected, it manually
- * removes all other actions as needed.
- */
- private class DescriptorFilterAction extends Action {
-
- private final ElementDescriptor mDescriptor;
- private ViewerFilter mFilter;
-
- public DescriptorFilterAction(ElementDescriptor descriptor) {
- super(String.format("Displays only %1$s elements.", descriptor.getUiName()),
- AS_CHECK_BOX);
-
- mDescriptor = descriptor;
- setImageDescriptor(descriptor.getImageDescriptor());
- }
-
- /**
- * Called when the button is selected.
- * <p/>
- * Find any existing {@link DescriptorFilter}s and remove them. Install ours.
- */
- @Override
- public void run() {
- super.run();
-
- if (isChecked()) {
- if (mFilter == null) {
- // create filter when required
- mFilter = new DescriptorFilter(this);
- }
-
- // we add our filter first, otherwise the UI might show the full list
- mTreeViewer.addFilter(mFilter);
-
- // Then remove the any other filters except ours. There should be at most
- // one other filter, since that's how the actions are made to look like
- // exclusive radio buttons.
- for (ViewerFilter filter : mTreeViewer.getFilters()) {
- if (filter instanceof DescriptorFilter && filter != mFilter) {
- DescriptorFilterAction action = ((DescriptorFilter) filter).getAction();
- action.setChecked(false);
- mTreeViewer.removeFilter(filter);
- }
- }
- } else if (mFilter != null){
- mTreeViewer.removeFilter(mFilter);
- }
- }
-
- /**
- * Filters the tree viewer for the given descriptor.
- * <p/>
- * The filter is linked to the action so that an action can iterate through the list
- * of filters and un-select the actions.
- */
- private class DescriptorFilter extends ViewerFilter {
-
- private final DescriptorFilterAction mAction;
-
- public DescriptorFilter(DescriptorFilterAction action) {
- mAction = action;
- }
-
- public DescriptorFilterAction getAction() {
- return mAction;
- }
-
- /**
- * Returns true if an element should be displayed, that if the element or
- * any of its parent matches the requested descriptor.
- */
- @Override
- public boolean select(Viewer viewer, Object parentElement, Object element) {
- while (element instanceof UiElementNode) {
- UiElementNode uiNode = (UiElementNode)element;
- if (uiNode.getDescriptor() == mDescriptor) {
- return true;
- }
- element = uiNode.getUiParent();
- }
- return false;
- }
- }
- }
-
-}