| /*=============================================================================# |
| # Copyright (c) 2009, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.ecommons.ui.actions; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullLateInit; |
| |
| import org.eclipse.jface.action.ContributionItem; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.layout.RowLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Layout; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.ToolBar; |
| import org.eclipse.swt.widgets.ToolItem; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.swt.widgets.TreeItem; |
| |
| import org.eclipse.statet.jcommons.lang.NonNull; |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| import org.eclipse.statet.ecommons.ui.components.SearchText; |
| import org.eclipse.statet.ecommons.ui.util.LayoutUtils; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| |
| @NonNullByDefault |
| public class SearchContributionItem extends ContributionItem { |
| |
| |
| public static final int VIEW_TOOLBAR= 0x10000000; |
| |
| |
| private class SWTListener implements Listener { |
| |
| @Override |
| public void handleEvent(final Event event) { |
| switch (event.type) { |
| case SWT.Resize: |
| scheduleSizeCheck(); |
| return; |
| } |
| } |
| |
| } |
| |
| |
| private final int options; |
| |
| private SearchText control= nonNullLateInit(); |
| private ToolItem textItem= nonNullLateInit(); |
| |
| private @Nullable String toolTipText; |
| |
| private @Nullable Composite sizeControl; |
| private @Nullable Control resultControl; |
| |
| private final boolean updateWhenTyping; |
| |
| private final Runnable sizeCheckRunnable= new Runnable() { |
| @Override |
| public void run() { |
| SearchContributionItem.this.sizeCheckScheduled= false; |
| resize(); |
| } |
| }; |
| private boolean sizeCheckScheduled; |
| |
| |
| public SearchContributionItem(final String id, final int options, |
| final boolean updateWhenTyping) { |
| super(id); |
| this.options= options; |
| this.updateWhenTyping= updateWhenTyping; |
| } |
| |
| public SearchContributionItem(final String id, final int options) { |
| this(id, options, false); |
| } |
| |
| |
| public SearchText getSearchText() { |
| return this.control; |
| } |
| |
| /** |
| * Table or tree to select |
| */ |
| public void setResultControl(final @Nullable Control control) { |
| this.resultControl= control; |
| } |
| |
| public void setToolTip(final @Nullable String text) { |
| this.toolTipText= text; |
| } |
| |
| /** |
| * For views the control of the view |
| */ |
| public void setSizeControl(final Composite control) { |
| this.sizeControl= control; |
| control.addListener(SWT.Resize, new Listener() { |
| @Override |
| public void handleEvent(final Event event) { |
| resize(); |
| } |
| }); |
| } |
| |
| public void resize() { |
| final var sizeControl= this.sizeControl; |
| if (this.textItem != null && !this.textItem.isDisposed() |
| && sizeControl != null ) { |
| final int viewWidth= sizeControl.getClientArea().width; |
| if (viewWidth <= 0) { |
| return; |
| } |
| final ToolBar toolBar= this.textItem.getParent(); |
| final Composite toolBarParent= nonNullAssert(toolBar.getParent()); |
| final int toolBarWidth= toolBar.computeSize(SWT.DEFAULT, SWT.DEFAULT).x; |
| final int currentWidth= this.textItem.getWidth(); |
| final int minWidth= LayoutUtils.hintWidth(this.control.getTextControl(), 8); |
| |
| int corr= toolBarWidth - currentWidth; |
| if ((this.options & VIEW_TOOLBAR) != 0) { |
| // E-4.2 View Toolbar (=> space for view menu) |
| final Layout layout= toolBarParent.getLayout(); |
| if (layout instanceof RowLayout && ((RowLayout)layout).type == SWT.HORIZONTAL) { |
| final Control[] children= toolBarParent.getChildren(); |
| for (int i= 0; i < children.length; i++) { |
| if (children[i] != toolBar) { |
| corr += children[i].getSize().x; |
| } |
| } |
| corr += (children.length - 1) * ((RowLayout)layout).spacing; |
| } |
| } |
| corr += 16; // 2 required |
| |
| final int width= Math.min(310, Math.max(minWidth, viewWidth - corr)); |
| if (width == currentWidth) { |
| return; |
| } |
| |
| // scheduleSizeCheck(); |
| |
| this.textItem.setWidth(width); |
| toolBarParent.layout(new @NonNull Control[] { this.control }); |
| toolBarParent.pack(true); |
| } |
| } |
| |
| private void scheduleSizeCheck() { |
| if (!this.sizeCheckScheduled |
| && this.textItem != null && !this.textItem.isDisposed() ) { |
| this.sizeCheckScheduled= true; |
| this.textItem.getDisplay().asyncExec(this.sizeCheckRunnable); |
| } |
| } |
| |
| @Override |
| public void fill(final ToolBar parent, final int index) { |
| this.control= new SearchText(parent); |
| this.control.addListener(createSearchTextListener()); |
| final Listener swtListener= new SWTListener(); |
| this.control.addListener(SWT.Resize, swtListener); |
| this.control.setToolTipText(this.toolTipText); |
| |
| this.textItem= new ToolItem(parent, SWT.SEPARATOR, index); |
| this.textItem.setControl(this.control); |
| this.textItem.setToolTipText(this.toolTipText); |
| this.textItem.setWidth(310); // high value prevents that the toolbar is moved to tabs |
| } |
| |
| public Control create(final Composite parent) { |
| this.control= new SearchText(parent); |
| this.control.addListener(createSearchTextListener()); |
| final Listener swtListener= new SWTListener(); |
| this.control.addListener(SWT.Resize, swtListener); |
| this.control.setToolTipText(this.toolTipText); |
| return this.control; |
| } |
| |
| protected SearchText.Listener createSearchTextListener() { |
| return new SearchText.Listener() { |
| @Override |
| public void textChanged(final boolean user) { |
| if (SearchContributionItem.this.updateWhenTyping || !user) { |
| SearchContributionItem.this.search(); |
| } |
| } |
| @Override |
| public void okPressed() { |
| SearchContributionItem.this.search(); |
| } |
| @Override |
| public void downPressed() { |
| SearchContributionItem.this.selectFirst(); |
| } |
| }; |
| } |
| |
| protected void search() { |
| } |
| |
| protected void selectFirst() { |
| final var resultControl= this.resultControl; |
| if (resultControl instanceof Table) { |
| final Table table= (Table)resultControl; |
| table.setFocus(); |
| if (table.getSelectionCount() == 0) { |
| final int idx= table.getTopIndex(); |
| if (idx >= 0) { |
| table.setSelection(idx); |
| } |
| } |
| } |
| else if (resultControl instanceof Tree) { |
| final Tree table= (Tree)resultControl; |
| table.setFocus(); |
| if (table.getSelectionCount() == 0) { |
| final TreeItem item= table.getTopItem(); |
| if (item != null) { |
| table.setSelection(item); |
| } |
| } |
| } |
| } |
| |
| public String getText() { |
| return this.control.getText(); |
| } |
| |
| public void show() { |
| if (!UIAccess.isOkToUse(this.control)) { |
| return; |
| } |
| this.control.setFocus(); |
| } |
| |
| } |