com.android.ide.eclipse.adt.internal.editors.layout.properties.PropertySheetPage.java Source code

Java tutorial

Introduction

Here is the source code for com.android.ide.eclipse.adt.internal.editors.layout.properties.PropertySheetPage.java

Source

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.ide.eclipse.adt.internal.editors.layout.properties;

import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.IconFactory;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.CanvasViewInfo;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
import com.android.ide.eclipse.adt.internal.editors.layout.properties.PropertyFactory.SortingMode;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.IUiUpdateListener;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.Page;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.wb.internal.core.editor.structure.IPage;
import org.eclipse.wb.internal.core.model.property.Property;
import org.eclipse.wb.internal.core.model.property.table.IPropertyExceptionHandler;
import org.eclipse.wb.internal.core.model.property.table.PropertyTable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * Property sheet page used when the graphical layout editor is chosen
 */
public class PropertySheetPage extends Page implements IPropertySheetPage, IUiUpdateListener, IPage {
    private PropertyTable mPropertyTable;
    private final GraphicalEditorPart mEditor;
    private Property mActiveProperty;
    private Action mDefaultValueAction;
    private Action mShowAdvancedPropertiesAction;
    private Action mSortAlphaAction;
    private Action mCollapseAll;
    private Action mExpandAll;
    private List<CanvasViewInfo> mSelection;

    private static final String EXPAND_DISABLED_ICON = "expandall-disabled"; //$NON-NLS-1$
    private static final String EXPAND_ICON = "expandall"; //$NON-NLS-1$
    private static final String DEFAULT_ICON = "properties_default"; //$NON-NLS-1$
    private static final String ADVANCED_ICON = "filter_advanced_properties"; //$NON-NLS-1$
    private static final String ALPHA_ICON = "sort_alpha"; //$NON-NLS-1$
    // TODO: goto-definition.png

    /**
     * Constructs a new {@link PropertySheetPage} associated with the given
     * editor
     *
     * @param editor the editor associated with this property sheet page
     */
    public PropertySheetPage(GraphicalEditorPart editor) {
        mEditor = editor;
    }

    private PropertyFactory getPropertyFactory() {
        return mEditor.getPropertyFactory();
    }

    @Override
    public void createControl(Composite parent) {
        assert parent != null;
        mPropertyTable = new PropertyTable(parent, SWT.NONE);
        mPropertyTable.setExceptionHandler(new IPropertyExceptionHandler() {
            @Override
            public void handle(Throwable e) {
                AdtPlugin.log(e, null);
            }
        });
        mPropertyTable.setDefaultCollapsedNames(
                Arrays.asList("Deprecated", "Layout Parameters", "Layout Parameters|Margins"));

        createActions();
        setPropertyTableContextMenu();
    }

    @Override
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        if (selection instanceof TreeSelection && mPropertyTable != null && !mPropertyTable.isDisposed()) {
            TreeSelection treeSelection = (TreeSelection) selection;

            // We get a lot of repeated selection requests for the same selection
            // as before, so try to eliminate these
            if (mSelection != null) {
                if (mSelection.isEmpty()) {
                    if (treeSelection.isEmpty()) {
                        return;
                    }
                } else {
                    int selectionCount = treeSelection.size();
                    if (selectionCount == mSelection.size()) {
                        boolean same = true;
                        Iterator<?> iterator = treeSelection.iterator();
                        for (int i = 0, n = selectionCount; i < n && iterator.hasNext(); i++) {
                            Object next = iterator.next();
                            if (next instanceof CanvasViewInfo) {
                                CanvasViewInfo info = (CanvasViewInfo) next;
                                if (info != mSelection.get(i)) {
                                    same = false;
                                    break;
                                }
                            } else {
                                same = false;
                                break;
                            }
                        }
                        if (same) {
                            return;
                        }
                    }
                }
            }

            stopTrackingSelection();

            if (treeSelection.isEmpty()) {
                mSelection = Collections.emptyList();
            } else {
                int selectionCount = treeSelection.size();
                List<CanvasViewInfo> newSelection = new ArrayList<CanvasViewInfo>(selectionCount);
                Iterator<?> iterator = treeSelection.iterator();
                while (iterator.hasNext()) {
                    Object next = iterator.next();
                    if (next instanceof CanvasViewInfo) {
                        CanvasViewInfo info = (CanvasViewInfo) next;
                        newSelection.add(info);
                    }
                }
                mSelection = newSelection;
            }

            startTrackingSelection();

            refreshProperties();
        }
    }

    @Override
    public void dispose() {
        stopTrackingSelection();
        super.dispose();
    }

    private void startTrackingSelection() {
        if (mSelection != null && !mSelection.isEmpty()) {
            for (CanvasViewInfo item : mSelection) {
                UiViewElementNode node = item.getUiViewNode();
                if (node != null) {
                    node.addUpdateListener(this);
                }
            }
        }
    }

    private void stopTrackingSelection() {
        if (mSelection != null && !mSelection.isEmpty()) {
            for (CanvasViewInfo item : mSelection) {
                UiViewElementNode node = item.getUiViewNode();
                if (node != null) {
                    node.removeUpdateListener(this);
                }
            }
        }
        mSelection = null;
    }

    // Implements IUiUpdateListener
    @Override
    public void uiElementNodeUpdated(UiElementNode node, UiUpdateState state) {
        refreshProperties();
    }

    @Override
    public Control getControl() {
        return mPropertyTable;
    }

    @Override
    public void setFocus() {
        mPropertyTable.setFocus();
    }

    @Override
    public void makeContributions(IMenuManager menuManager, IToolBarManager toolBarManager,
            IStatusLineManager statusLineManager) {
        toolBarManager.add(mShowAdvancedPropertiesAction);
        toolBarManager.add(new Separator());
        toolBarManager.add(mSortAlphaAction);
        toolBarManager.add(new Separator());
        toolBarManager.add(mDefaultValueAction);
        toolBarManager.add(new Separator());
        toolBarManager.add(mExpandAll);
        toolBarManager.add(mCollapseAll);
        toolBarManager.add(new Separator());
    }

    private void createActions() {
        ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
        IconFactory iconFactory = IconFactory.getInstance();

        mExpandAll = new PropertySheetAction(IAction.AS_PUSH_BUTTON, "Expand All", ACTION_EXPAND,
                iconFactory.getImageDescriptor(EXPAND_ICON), iconFactory.getImageDescriptor(EXPAND_DISABLED_ICON));

        mCollapseAll = new PropertySheetAction(IAction.AS_PUSH_BUTTON, "Collapse All", ACTION_COLLAPSE,
                sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL),
                sharedImages.getImageDescriptor(ISharedImages.IMG_ELCL_COLLAPSEALL_DISABLED));

        mShowAdvancedPropertiesAction = new PropertySheetAction(IAction.AS_CHECK_BOX, "Show Advanced Properties",
                ACTION_SHOW_ADVANCED, iconFactory.getImageDescriptor(ADVANCED_ICON), null);

        mSortAlphaAction = new PropertySheetAction(IAction.AS_CHECK_BOX, "Sort Alphabetically", ACTION_SORT_ALPHA,
                iconFactory.getImageDescriptor(ALPHA_ICON), null);

        mDefaultValueAction = new PropertySheetAction(IAction.AS_PUSH_BUTTON, "Restore Default Value",
                ACTION_DEFAULT_VALUE, iconFactory.getImageDescriptor(DEFAULT_ICON), null);

        // Listen on the selection in the property sheet so we can update the
        // Restore Default Value action
        ISelectionChangedListener listener = new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                StructuredSelection selection = (StructuredSelection) event.getSelection();
                mActiveProperty = (Property) selection.getFirstElement();
                updateDefaultValueAction();
            }
        };
        mPropertyTable.addSelectionChangedListener(listener);
    }

    /**
     * Updates the state of {@link #mDefaultValueAction}.
     */
    private void updateDefaultValueAction() {
        if (mActiveProperty != null) {
            try {
                mDefaultValueAction.setEnabled(mActiveProperty.isModified());
            } catch (Exception e) {
                AdtPlugin.log(e, null);
            }
        } else {
            mDefaultValueAction.setEnabled(false);
        }
    }

    /**
     * Sets the context menu for {@link #mPropertyTable}.
     */
    private void setPropertyTableContextMenu() {
        final MenuManager manager = new MenuManager();
        manager.setRemoveAllWhenShown(true);
        manager.addMenuListener(new IMenuListener() {
            @Override
            public void menuAboutToShow(IMenuManager m) {
                // dispose items to avoid caching
                for (MenuItem item : manager.getMenu().getItems()) {
                    item.dispose();
                }
                // apply new items
                fillContextMenu();
            }

            private void fillContextMenu() {
                manager.add(mDefaultValueAction);
                manager.add(mSortAlphaAction);
                manager.add(mShowAdvancedPropertiesAction);
            }
        });

        mPropertyTable.setMenu(manager.createContextMenu(mPropertyTable));
    }

    /**
     * Shows {@link Property}'s of current objects.
     */
    private void refreshProperties() {
        PropertyFactory factory = getPropertyFactory();
        mPropertyTable.setInput(factory.getProperties(mSelection));
        updateDefaultValueAction();
    }

    // ---- Actions ----

    private static final int ACTION_DEFAULT_VALUE = 1;
    private static final int ACTION_SHOW_ADVANCED = 2;
    private static final int ACTION_COLLAPSE = 3;
    private static final int ACTION_EXPAND = 4;
    private static final int ACTION_SORT_ALPHA = 5;

    private class PropertySheetAction extends Action {
        private final int mAction;

        private PropertySheetAction(int style, String label, int action, ImageDescriptor imageDesc,
                ImageDescriptor disabledImageDesc) {
            super(label, style);
            mAction = action;
            setImageDescriptor(imageDesc);
            if (disabledImageDesc != null) {
                setDisabledImageDescriptor(disabledImageDesc);
            }
            setToolTipText(label);
        }

        @Override
        public void run() {
            switch (mAction) {
            case ACTION_COLLAPSE: {
                mPropertyTable.collapseAll();
                break;
            }
            case ACTION_EXPAND: {
                mPropertyTable.expandAll();
                break;
            }
            case ACTION_SHOW_ADVANCED: {
                boolean show = mShowAdvancedPropertiesAction.isChecked();
                mPropertyTable.setShowAdvancedProperties(show);
                break;
            }
            case ACTION_SORT_ALPHA: {
                boolean isAlphabetical = mSortAlphaAction.isChecked();
                getPropertyFactory()
                        .setSortingMode(isAlphabetical ? SortingMode.ALPHABETICAL : PropertyFactory.DEFAULT_MODE);
                refreshProperties();
                break;
            }
            case ACTION_DEFAULT_VALUE:
                try {
                    mActiveProperty.setValue(Property.UNKNOWN_VALUE);
                } catch (Exception e) {
                    // Ignore warnings from setters
                }
                break;
            default:
                assert false : mAction;
            }
        }
    }

    @Override
    public void setToolBar(IToolBarManager toolBarManager) {
        makeContributions(null, toolBarManager, null);
        toolBarManager.update(false);
    }
}