blob: 9ab6cd25f8d5b57006e6cb18a50be589a85a7532 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2015 Tasktop Technologies and others.
* 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:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.commons.workbench;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.mylyn.internal.commons.workbench.CommonsWorkbenchPlugin;
import org.eclipse.mylyn.internal.commons.workbench.Messages;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.progress.WorkbenchJob;
/**
* A filtered tree with additional controls below the filter text field.
*
* @author Mik Kersten
* @since 3.7
*/
@SuppressWarnings("deprecation")
public abstract class AbstractFilteredTree extends EnhancedFilteredTree {
private static final int FILTER_WIDTH_MIN = 60;
private static final int FILTER_WIDTH_MAX = 300;
private static final float FILTER_WIDTH_RATIO = 0.35f;
public static final String LABEL_FIND = Messages.AbstractFilteredTree_Find;
private WorkbenchJob refreshJob;
private AdaptiveRefreshPolicy refreshPolicy;
private Composite progressComposite;
private Composite searchComposite;
private boolean showProgress = false;
private String previousFilterText;
/**
* XXX: using reflection to gain access
*
* @param parent
* @param treeStyle
* @param filter
*/
public AbstractFilteredTree(Composite parent, int treeStyle, PatternFilter filter) {
super(parent, treeStyle, filter, true);
try {
// the super constructor calls doCreateRefreshJob() which assigns refreshJob
refreshPolicy = new AdaptiveRefreshPolicy(refreshJob);
} catch (Exception e) {
CommonsWorkbenchPlugin.getDefault().getLog().log(
new Status(IStatus.ERROR, CommonsWorkbenchPlugin.ID_PLUGIN, "Could not get refresh job", e)); //$NON-NLS-1$
}
setInitialText(LABEL_FIND);
}
@Override
protected WorkbenchJob doCreateRefreshJob() {
this.refreshJob = super.doCreateRefreshJob();
return this.refreshJob;
}
@Override
protected void createControl(Composite parent, int treeStyle) {
super.createControl(parent, treeStyle);
// Override superclass layout settings...
GridLayout layout = (GridLayout) getLayout();
layout.verticalSpacing = 0;
layout.horizontalSpacing = 0;
}
@Override
protected Control createTreeControl(Composite parent, int style) {
progressComposite = createProgressComposite(parent);
// progressComposite.setVisible(false);
// ((GridData) progressComposite.getLayoutData()).exclude = true;
searchComposite = createSearchComposite(parent);
if (searchComposite != null) {
searchComposite.setVisible(false);
((GridData) searchComposite.getLayoutData()).exclude = true;
}
return super.createTreeControl(parent, style);
}
@Override
protected Composite createFilterControls(final Composite parent) {
// replace filterComposite by a new composite
filterComposite = new Composite(parent.getParent(), SWT.NONE);
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.marginLeft = 3;
gridLayout.marginTop = 5;
gridLayout.marginBottom = 3;
gridLayout.verticalSpacing = 0;
filterComposite.setLayout(gridLayout);
// let FilteredTree create the find and clear control
super.createFilterControls(parent);
GridDataFactory.fillDefaults()
.align(SWT.BEGINNING, SWT.CENTER)
.grab(false, false)
.hint(FILTER_WIDTH_MIN, SWT.DEFAULT)
.minSize(FILTER_WIDTH_MIN, SWT.DEFAULT)
.applyTo(parent);
filterComposite.addControlListener(new ControlAdapter() {
boolean handlingEvents;
@Override
public void controlResized(ControlEvent e) {
if (handlingEvents) {
return;
}
try {
handlingEvents = true;
Point size = parent.getParent().getSize();
int width = Math.max(FILTER_WIDTH_MIN, (int) (size.x * FILTER_WIDTH_RATIO));
int offset = 1;
if (parent.getParent().getLayoutData() instanceof GridData) {
offset = ((GridLayout) parent.getParent().getLayout()).marginWidth
+ ((GridLayout) parent.getParent().getLayout()).marginLeft
+ ((GridLayout) parent.getParent().getLayout()).horizontalSpacing;
}
((GridData) parent.getLayoutData()).widthHint = Math.min(width, FILTER_WIDTH_MAX) + offset;
((GridData) filterText.getParent().getLayoutData()).widthHint = Math.min(width, FILTER_WIDTH_MAX);
parent.getParent().layout();
} finally {
handlingEvents = false;
}
}
});
filterText.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.character == SWT.ESC && e.doit) {
setFilterText(""); //$NON-NLS-1$
}
}
});
((GridData) filterText.getLayoutData()).verticalAlignment = SWT.CENTER;
// move original filterComposite on new filterComposite
parent.setParent(filterComposite);
Composite workingSetComposite = createActiveWorkingSetComposite(filterComposite);
if (workingSetComposite != null) {
GridDataFactory.fillDefaults()
.align(SWT.BEGINNING, SWT.CENTER)
.grab(false, false)
.applyTo(workingSetComposite);
}
Composite activeTaskComposite = createActiveTaskComposite(filterComposite);
if (activeTaskComposite != null) {
GridDataFactory.fillDefaults()
.align(SWT.BEGINNING, SWT.CENTER)
.grab(true, false)
.applyTo(activeTaskComposite);
}
Composite additionalComposite = createAdditionalControls(filterComposite);
if (additionalComposite != null) {
GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).grab(true, false).applyTo(additionalComposite);
}
gridLayout.numColumns = filterComposite.getChildren().length;
return parent;
}
protected abstract Composite createProgressComposite(Composite container);
protected abstract Composite createActiveWorkingSetComposite(Composite container);
protected abstract Composite createActiveTaskComposite(Composite container);
protected Composite createSearchComposite(Composite container) {
return null;
}
/**
* @since 3.18
*/
protected Composite createAdditionalControls(Composite container) {
return null;
}
@Override
protected void textChanged() {
// this call allows the filtered tree to preserve the selection when the clear button is used.
// It is necessary to correctly set the private narrowingDown flag in the super class.
// Note that the scheduling of the refresh job that is done in the super class will be overridden
// by the call to refreshPolicy.textChanged().
String text = getFilterString();
if (text == null || text.equals(previousFilterText)) {
return;
}
super.textChanged();
previousFilterText = text;
if (refreshPolicy != null) {
if (LABEL_FIND.equals(text) && !useNewLook) {
clearText();
refreshPolicy.textChanged(""); //$NON-NLS-1$
} else {
refreshPolicy.textChanged(text);
}
}
// bug 165353 work-around for premature return at FilteredTree.java:374
updateToolbar(true);
}
@Deprecated
protected Job getRefreshJob() {
return refreshJob;
}
public AdaptiveRefreshPolicy getRefreshPolicy() {
return refreshPolicy;
}
public boolean isShowProgress() {
return showProgress;
}
public void setShowProgress(boolean showProgress) {
this.showProgress = showProgress;
if (progressComposite != null) {
progressComposite.setVisible(showProgress);
((GridData) progressComposite.getLayoutData()).exclude = !showProgress;
}
getParent().getParent().layout(true, true);
}
public void setShowSearch(boolean showSearch) {
if (searchComposite != null) {
searchComposite.setVisible(showSearch);
((GridData) searchComposite.getLayoutData()).exclude = !showSearch;
getParent().getParent().layout(true, true);
}
}
}