X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.selectionview%2Fsrc%2Forg%2Fsimantics%2Fselectionview%2FStandardPropertyPage.java;fp=bundles%2Forg.simantics.selectionview%2Fsrc%2Forg%2Fsimantics%2Fselectionview%2FStandardPropertyPage.java;h=b534e647a18f45a718651ea0132d822d41f69c15;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.selectionview/src/org/simantics/selectionview/StandardPropertyPage.java b/bundles/org.simantics.selectionview/src/org/simantics/selectionview/StandardPropertyPage.java new file mode 100644 index 000000000..b534e647a --- /dev/null +++ b/bundles/org.simantics.selectionview/src/org/simantics/selectionview/StandardPropertyPage.java @@ -0,0 +1,292 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.selectionview; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; +import java.util.TreeSet; +import java.util.function.Consumer; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchPartSite; +import org.simantics.utils.ObjectUtils; + +/** + *

+ * See PropertyPage for more information on what can be extended or + * reimplemented from the superclasses. In addition to those, subclasses may + * extend or reimplement the following methods: + *

+ *

+ * + * @author Tuukka Lehtonen + * + * @see StandardProperties + */ +public class StandardPropertyPage extends PropertyPage { + + private final Set contexts; + private StandardProperties tabs; + + /** + * For updating the view title when the active tab changes. + */ + //private transient ISelection lastSelection; + private transient Consumer lastTitleCallback; + + /** + * Initializes a new standard property page for the specified workbench part + * without loading the page configuration from any extensible contexts. + * + * @param site the workbench part site that contains this page or + * null if there is no site, i.e. the page is within a + * dialog or a plain shell. + */ + public StandardPropertyPage(IWorkbenchPartSite site) { + this(site, new TreeSet()); + } + + /** + * Initializes a new standard property page for the specified workbench part + * and specifies which contexts should be searched for + * {@link SelectionProcessor} and {@link PropertyTabContributor} bindings to + * initialize the page. + * + * @param site the workbench part site that contains this page or + * null if there is no site, i.e. the page is within a + * dialog or a plain shell. + * @param contexts the contexts to search bindings for to initialize the + * property page + */ + public StandardPropertyPage(IWorkbenchPartSite site, Set contexts) { + super(site); + this.contexts = contexts; + } + + protected SelectionProcessor getSelectionProcessor() { + return new StandardSelectionProcessor(); + } + + protected Set getContexts() { + return contexts; + } + + @SuppressWarnings("unchecked") + @Override + protected void createPageControls(Composite parent) { + SelectionProcessor sp = getSelectionProcessor(); + @SuppressWarnings("rawtypes") + Collection sps = null; + if (sp != null) + sps = Collections.singleton(sp); + + tabs = new StandardProperties(sourceSite, getSite(), parent, SWT.NONE, getContexts(), sps) { + @Override + protected void activeTabChanged(TabChangeEvent event) { + StandardPropertyPage.this.activeTabChanged(event); + } + @Override + protected ComparableTabContributor selectInitialTab(Collection selectionContents, Collection contributions) { + return StandardPropertyPage.this.selectInitialTab(selectionContents, contributions); + } + @Override + protected int getTabFolderStyle() { + return StandardPropertyPage.this.getTabFolderStyle(); + } + }; + tab = tabs; + tab.createControl(tabs, getSessionContext()); + getSite().setSelectionProvider(tabs.getSelectionProvider()); + + fillToolBar(getSite().getActionBars().getToolBarManager()); + fillDropDownMenu(getSite().getActionBars().getMenuManager()); + } + + @Override + public void updatePartName(ISelection forSelection, Consumer updateCallback) { + + if(!visible) { + updateCallback.accept("Selection"); + return; + } + + //this.lastSelection = forSelection; + this.lastTitleCallback = updateCallback; + IPropertyTab tab = tabs.getActiveTab(); + //System.out.println("updatePartName(" + forSelection + ", " + updateCallback + "): " + tab); + if (tab instanceof IPropertyTab2) { + //System.out.println("invoking tab.updatePartName for tab " + tab); + // TabbedPropertyTable implementation reacts to events with several subsequent runnables. + // This causes the part name update to be run before the input is set. Hence we have to set the input here. + // TLe: this is broken since there is no guarantee that forSelection + // is the proper input for this property tab whose input may well be + // a transformed version of the original workbench selection. + //((IPropertyTab2) tab).setInput(getSessionContext(), forSelection, false); + ((IPropertyTab2) tab).updatePartName(updateCallback); + } else { + //System.out.println("using default updatePartName for tab " + tab); + super.updatePartName(forSelection, updateCallback); + } + } + + /** + * @return + */ + protected int getTabFolderStyle() { + return SWT.BOTTOM | SWT.FLAT; + } + + /** + * A simple tab label based implementation for restoring the last selected + * tab as the initial tab selection when the property page contents are + * reset. It statically stores the last selected tab names for + * {@value #MAX_SELECTED_TABS_REMEMBERED} last different ordered tab name + * combinations. + * + * @param selectionContents + * @param contributions + * @return the previously selected tab contribution for a matching list of tabs + */ + protected ComparableTabContributor selectInitialTab(Collection selectionContents, Collection contributions) { + tabSelection = TabSelection.make(contributions); + for (Iterator it = previouslySelectedTabs.iterator(); it.hasNext();) { + TabSelection t = it.next(); + if (t.equals(tabSelection)) { + tabSelection = t; + // Move selection to front of list. + it.remove(); + previouslySelectedTabs.addFirst(t); + for (ComparableTabContributor contrib : contributions) { + if (ObjectUtils.objectEquals(contrib.getLabel(), t.selected)) { + return contrib; + } + } + // selection must have been null, select first tab anyway. + return null; + } + } + tabSelection.setSelected(contributions.iterator().next().getLabel()); + previouslySelectedTabs.addFirst(tabSelection); + while (previouslySelectedTabs.size() > MAX_SELECTED_TABS_REMEMBERED) + previouslySelectedTabs.removeLast(); + return null; + } + + protected void activeTabChanged(TabChangeEvent event) { + //System.out.println("active tab changed: " + event); + if (tabSelection != null) + tabSelection.setSelected(event.getNewTabLabel()); + IPropertyTab tab = event.getNewTab(); + if (tab instanceof IPropertyTab2) { + //System.out.println("invoking tab.updatePartName for tab " + tab); + if(lastTitleCallback != null) + ((IPropertyTab2) tab).updatePartName(lastTitleCallback); + } + } + + /** + * The maximum number of previous initial tab selections to store. See + * {@link #previouslySelectedTabs} and {@link #tabSelection}. + */ + private static final int MAX_SELECTED_TABS_REMEMBERED = 20; + + /** + * An LRU managed list of previously existing tab selections. The list is + * static but only used from the SWT display thread so no synchronization is + * necessary. + */ + private static LinkedList previouslySelectedTabs = new LinkedList(); + + /** + * The selection of tabs this property page is currently showing. Also + * contains the currently selected tab name, which is updated by + * {@link #activeTabChanged(TabChangeEvent)} and + * {@link #selectInitialTab(Collection, Collection)}. + */ + private TabSelection tabSelection; + + /** + * A class for representing a set of tabs by their labels and a marking the previously selected one. + */ + static class TabSelection { + + private final String[] tabLabels; + private String selected; + + public static TabSelection make(Collection contribs) { + String[] labels = new String[contribs.size()]; + int i = 0; + for (ComparableTabContributor contrib : contribs) + labels[i++] = contrib.getLabel(); + return new TabSelection(labels); + } + + public TabSelection(String... tabLabels) { + this.tabLabels = tabLabels; + } + + public String getSelected() { + return selected; + } + + /** + * Ensures that the selected tab is among the set of different tab + * labels. Otherwise the set request is ignored. + * + * @param label + */ + public void setSelected(String label) { + for (String l : tabLabels) { + if (l.equals(label)) { + this.selected = label; + break; + } + } + } + + @Override + public int hashCode() { + return Arrays.hashCode(tabLabels); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TabSelection other = (TabSelection) obj; + return Arrays.equals(tabLabels, other.tabLabels); + } + + @Override + public String toString() { + return getClass().getName() + "[" + Arrays.toString(tabLabels) + " - " + selected + "]"; + } + + } + +}