blob: 6cb3c4e752a5649ef241d3bd684d199cdc100458 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2012, 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.internal.r.ui.datafilterview;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullLateInit;
import org.eclipse.jface.dialogs.MessageLine;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.services.IServiceLocator;
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.databinding.jface.DataBindingSupport;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.internal.r.ui.datafilter.VariableFilter;
@NonNullByDefault
public abstract class FilterClient<TFilter extends VariableFilter> extends Composite {
protected static final String SELECT_ALL_COMMAND_ID= IWorkbenchCommandConstants.EDIT_SELECT_ALL;
protected static final String REMOVE_COMMAND_ID= IWorkbenchCommandConstants.EDIT_DELETE;
protected static final String REMOVE_ALL_HANDLER_COMMAND_ID= "RemoveAll"; //$NON-NLS-1$
protected static final String REMOVE_UNCHECKED_HANDLER_ID= "RemoveUnchecked"; //$NON-NLS-1$
protected final TFilter filter;
private DataBindingSupport dataBinding= nonNullLateInit();
private @Nullable Listener resizeListener;
private @Nullable MessageLine statusInfo;
private boolean layoutChanged;
public FilterClient(final VariableComposite parent, final TFilter filter) {
super(parent, SWT.NONE);
this.filter= filter;
filter.setListener(this::onFilterDataChanged);
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(final DisposeEvent e) {
onDispose();
}
});
}
@Override
@SuppressWarnings("null")
public VariableComposite getParent() {
return (VariableComposite)super.getParent();
}
public abstract VariableFilter getFilter();
protected void init(final int numColumns) {
getParent().setClient(this);
setLayout(LayoutUtils.newCompositeGrid(numColumns));
addWidgets();
LayoutUtils.addSmallFiller(this, false);
initActions(getParent().getContainer().getServiceLocator());
initBindings();
onFilterDataChanged();
}
@SuppressWarnings("null")
protected int getNumColumns() {
return ((GridLayout)getLayout()).numColumns;
}
protected void addStatusInfoLine() {
final var statusInfo= new MessageLine(this, SWT.NONE);
statusInfo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
getNumColumns(), 1) );
this.statusInfo= statusInfo;
updateStatusInfo();
}
protected abstract void addWidgets();
protected abstract void initActions(IServiceLocator serviceLocator);
protected void onFilterDataChanged() {
if (isDisposed()) {
return;
}
updateStatusInfo();
updateInput();
this.dataBinding.getContext().updateTargets();
}
protected void updateStatusInfo() {
final var statusInfo= this.statusInfo;
if (statusInfo != null) {
final var status= getFilter().getStatus();
statusInfo.setErrorStatus(status);
final var layoutData= nonNullAssert((GridData)statusInfo.getLayoutData());
final boolean show= (status != null);
if (show != statusInfo.isVisible()) {
statusInfo.setVisible(show);
layoutData.exclude= !show;
this.layoutChanged= true;
}
}
}
protected abstract void updateInput();
protected void initBindings() {
this.dataBinding= new DataBindingSupport(this);
addBindings(this.dataBinding);
}
protected void addBindings(final DataBindingSupport db) {
}
protected DataBindingSupport getDataBinding() {
return this.dataBinding;
}
protected void installResizeListener() {
var listener= this.resizeListener;
if (listener == null) {
listener= new Listener() {
@Override
public void handleEvent(final Event event) {
checkLayout();
}
};
getParent().getContainer().getComposite().addListener(SWT.Resize, listener);
this.resizeListener= listener;
}
}
protected void checkLayout() {
if (updateLayout() || this.layoutChanged) {
getParent().layout(new @NonNull Control[] { this });
}
}
protected boolean updateLayout() {
return false;
}
protected boolean updateLayout(final TableViewer viewer, final int count) {
final GridData data= new GridData(SWT.FILL, SWT.CENTER, true, false,
getNumColumns(), 1 );
if (count == 0) {
data.exclude= true;
}
else {
data.heightHint= LayoutUtils.hintHeight(viewer.getTable(), count, false);
final int max= Math.max(5 * viewer.getTable().getItemHeight(),
getParent().getContainer().getComposite().getClientArea().height
- getMinHeightPadding() );
if (data.heightHint > max) {
data.heightHint= max;
}
installResizeListener();
}
{ final Control control= viewer.getControl();
final GridData oldData= ((GridData)control.getLayoutData());
if (oldData == null || oldData.exclude != data.exclude || oldData.heightHint != data.heightHint) {
control.setVisible(!data.exclude);
control.setLayoutData(data);
return true;
}
return false;
}
}
protected int getMinHeightPadding() {
return 20 + 8 * LayoutUtils.defaultVSpacing();
}
@Override
public void layout(boolean changed, final boolean all) {
changed |= updateLayout();
super.layout(changed, all);
}
@Override
public void layout(final @NonNull Control @Nullable [] changed, int flags) {
if (updateLayout() || this.layoutChanged) {
this.layoutChanged= false;
flags |= SWT.CHANGED;
}
super.layout(changed, flags);
}
protected void onDispose() {
{ final var listener= this.resizeListener;
if (listener != null) {
this.resizeListener= null;
getParent().getContainer().getComposite().removeListener(SWT.Resize, listener);
}
}
}
}