blob: af2a56fdd8cf4eeed910d9098240fab06bbf5737 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2012, 2019 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.datafilter;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.r.ui.dataeditor.RDataTableColumn;
import org.eclipse.statet.rj.data.RDataUtils;
import org.eclipse.statet.rj.data.RObject;
import org.eclipse.statet.rj.data.RStore;
import org.eclipse.statet.rj.data.UnexpectedRDataException;
import org.eclipse.statet.rj.services.FunctionCall;
import org.eclipse.statet.rj.ts.core.RToolService;
public class IntervalVariableFilter extends VariableFilter {
public static final int MIN_IDX= 0;
public static final int MAX_IDX= 1;
public static final int NA_IDX= 2;
private RStore<? extends Number> minMaxData;
private final IObservableValue<Number> selectedLowerValue;
private final IObservableValue<Number> selectedUpperValue;
private final IObservableValue<Boolean> selectedNA;
protected IntervalVariableFilter(final FilterSet set, final RDataTableColumn column) {
super(set, column);
this.selectedLowerValue= new WritableValue<>(set.getRealm());
this.selectedUpperValue= new WritableValue<>(set.getRealm());
this.selectedNA= new WritableValue<>(set.getRealm(), true, Boolean.TYPE);
registerObservable(this.selectedLowerValue);
registerObservable(this.selectedUpperValue);
registerObservable(this.selectedNA);
}
@Override
public FilterType getType() {
return FilterType.INTERVAL;
}
@Override
public void load(final VariableFilter filter) {
if (filter.getType() == FilterType.INTERVAL
&& filter.getColumn().getDataStore().getStoreType() == getColumn().getDataStore().getStoreType()) {
final IntervalVariableFilter intervalFilter= (IntervalVariableFilter) filter;
runInRealm(new Runnable() {
@Override
public void run() {
if (IntervalVariableFilter.this.minMaxData == null) {
IntervalVariableFilter.this.selectedLowerValue.setValue(intervalFilter.getSelectedLowerValue().getValue());
IntervalVariableFilter.this.selectedUpperValue.setValue(intervalFilter.getSelectedUpperValue().getValue());
IntervalVariableFilter.this.selectedNA.setValue(intervalFilter.getSelectedNA().getValue());
}
}
});
}
}
@Override
public void reset() {
runInRealm(new Runnable() {
@Override
public void run() {
if (IntervalVariableFilter.this.minMaxData == null) {
return;
}
IntervalVariableFilter.this.selectedLowerValue.setValue(IntervalVariableFilter.this.minMaxData.get(MIN_IDX));
IntervalVariableFilter.this.selectedUpperValue.setValue(IntervalVariableFilter.this.minMaxData.get(MAX_IDX));
IntervalVariableFilter.this.selectedNA.setValue(Boolean.TRUE);
}
});
}
@Override
protected void update(final RToolService r, final ProgressMonitor m) throws StatusException, UnexpectedRDataException {
final RDataTableColumn column= getColumn();
{ final FunctionCall fcall= r.createFunctionCall("rj:::.getDataIntervalValues"); //$NON-NLS-1$
fcall.add(column.getRExpression());
final RObject data= fcall.evalData(m);
RDataUtils.checkRVector(data);
setValues((RStore<Number>) RDataUtils.checkData(data.getData(), column.getDataStore().getStoreType()));
return;
}
}
@Override
protected void setError(final String message) {
runInRealm(new Runnable() {
@Override
public void run() {
IntervalVariableFilter.this.minMaxData= null;
IntervalVariableFilter.super.setError(message);
notifyListeners();
}
});
}
protected void setValues(final RStore<? extends Number> minMaxData) {
runInRealm(new Runnable() {
@Override
public void run() {
boolean wasMin;
{ final Object value= IntervalVariableFilter.this.selectedLowerValue.getValue();
wasMin= (value == null || value.equals(minMaxData.get(MIN_IDX)));
}
boolean wasMax;
{ final Object value= IntervalVariableFilter.this.selectedLowerValue.getValue();
wasMax= (value == null || value.equals(minMaxData.get(MAX_IDX)));
}
IntervalVariableFilter.this.minMaxData= minMaxData;
if (wasMin) {
IntervalVariableFilter.this.selectedLowerValue.setValue(IntervalVariableFilter.this.minMaxData.get(MIN_IDX));
}
if (wasMax) {
IntervalVariableFilter.this.selectedUpperValue.setValue(IntervalVariableFilter.this.minMaxData.get(MAX_IDX));
}
IntervalVariableFilter.super.setError(null);
notifyListeners();
}
});
}
private static boolean isSmaller(final Number e1, final Number e2) {
if (e1 instanceof Integer) {
return (((Integer) e1).intValue() < ((Integer) e2).intValue());
}
return (e1.doubleValue() < e2.doubleValue());
}
private static boolean isGreater(final Object e1, final Object e2) {
if (e1 instanceof Integer) {
return (((Integer) e1).intValue() > ((Integer) e2).intValue());
}
return (((Number) e1).doubleValue() > ((Number) e2).doubleValue());
}
@Override
protected String createFilter(final String varExpression) {
if (this.minMaxData == null
|| this.selectedLowerValue.getValue() == null
|| this.selectedUpperValue.getValue() == null) {
return null;
}
final StringBuilder sb= new StringBuilder();
sb.append('(');
{
final Number lower= this.selectedLowerValue.getValue();
if (isGreater(lower, this.minMaxData.get(MIN_IDX))) {
sb.append(varExpression);
sb.append(" >= "); //$NON-NLS-1$
sb.append(lower);
}
}
{ final Number upper= this.selectedUpperValue.getValue();
if (isSmaller(upper, this.minMaxData.get(MAX_IDX))) {
if (sb.length() > 1) {
sb.append(" & "); //$NON-NLS-1$
}
sb.append(varExpression);
sb.append(" <= "); //$NON-NLS-1$
sb.append(upper);
}
}
// if (this.minMaxData.getLogi(NA_IDX)) {
final Boolean na= (!this.minMaxData.getLogi(NA_IDX))
|| this.selectedNA.getValue();
if (na) {
if (sb.length() > 1) {
sb.insert(0, '(');
sb.append(") | "); //$NON-NLS-1$
sb.append("is.na(").append(varExpression).append(')'); //$NON-NLS-1$
}
}
else { // !na
if (sb.length() > 1) {
sb.append(" & "); //$NON-NLS-1$
}
sb.append("!is.na(").append(varExpression).append(')'); //$NON-NLS-1$
}
// }
sb.append(')');
return (sb.length() <= 2) ? "" : sb.toString(); //$NON-NLS-1$
}
public RStore<? extends Number> getMinMaxData() {
return this.minMaxData;
}
public IObservableValue<Number> getSelectedLowerValue() {
return this.selectedLowerValue;
}
public IObservableValue<Number> getSelectedUpperValue() {
return this.selectedUpperValue;
}
public IObservableValue<Boolean> getSelectedNA() {
return this.selectedNA;
}
}