blob: 58fddc0ee7ea8834c5fb90f7cda0130bff5096fe [file] [log] [blame]
/*
* 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);
}
}