/******************************************************************************* * Copyright (c) 2015, 2017 Pivotal, Inc. * 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: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash.model; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IProject; import org.springframework.ide.eclipse.boot.dash.metadata.IPropertyStore; import org.springframework.ide.eclipse.boot.dash.metadata.PropertyStoreApi; import org.springframework.ide.eclipse.boot.dash.metadata.PropertyStoreFactory; import org.springframework.ide.eclipse.boot.util.Log; import org.springsource.ide.eclipse.commons.livexp.core.AsyncLiveExpression.AsyncMode; import org.springsource.ide.eclipse.commons.livexp.core.LiveExpression; import org.springsource.ide.eclipse.commons.livexp.core.LiveSetVariable; import org.springsource.ide.eclipse.commons.livexp.core.ValueListener; import org.springsource.ide.eclipse.commons.livexp.ui.Ilabelable; import org.springsource.ide.eclipse.commons.livexp.util.Filter; import org.springsource.ide.eclipse.commons.livexp.util.Filters; import com.google.common.collect.ImmutableSet; /** * The 'toggle filters' are fixed set of view filters that can be toggled on/off by the user. * This model element tracks the currently selected 'toggle' filters and the corresponding composite * filter that results from composing them. * * @author Kris De Volder */ public class ToggleFiltersModel { private static final Filter<BootDashElement> HIDE_SOLITARY_CONFS = new Filter<BootDashElement>() { public boolean accept(BootDashElement e) { if (e instanceof LaunchConfDashElement) { LaunchConfDashElement conf = (LaunchConfDashElement) e; return conf.getParent().getCurrentChildren().size()!=1; } return true; } }; private static final Filter<BootDashElement> HIDE_NON_WORKSPACE_ELEMENTS = new Filter<BootDashElement>() { public boolean accept(BootDashElement t) { if (t!=null) { IProject p = t.getProject(); return p!=null && p.exists(); } return false; } }; private static final Filter<BootDashElement> HIDE_LOCAL_SERVICES = new Filter<BootDashElement>() { @Override public boolean accept(BootDashElement t) { return !(t instanceof LocalCloudServiceDashElement); } }; public static final FilterChoice FILTER_CHOICE_HIDE_NON_WORKSPACE_ELEMENTS = new FilterChoice("hide.non-workspace", "Hide non-workspace elements", HIDE_NON_WORKSPACE_ELEMENTS); public static final FilterChoice FILTER_CHOICE_HIDE_SOLITARY_CONFS = new FilterChoice("hide.solitary-launch-config", "Hide solitary launch configs", HIDE_SOLITARY_CONFS, true); public static final FilterChoice FILTER_CHOICE_HIDE_LOCAL_SERVICES = new FilterChoice("hide.local-cloud-services", "Hide local cloud services", HIDE_LOCAL_SERVICES); private static final String STORE_ID = "toggle-filters"; private static final FilterChoice[] FILTERS = { FILTER_CHOICE_HIDE_NON_WORKSPACE_ELEMENTS, FILTER_CHOICE_HIDE_SOLITARY_CONFS, FILTER_CHOICE_HIDE_LOCAL_SERVICES }; private final PropertyStoreApi persistentProperties; public ToggleFiltersModel(BootDashModelContext context) { this(PropertyStoreFactory.createSubStore(STORE_ID, context.getViewProperties())); } public ToggleFiltersModel(IPropertyStore propertyStore) { this.persistentProperties = new PropertyStoreApi(propertyStore); this.selectedFilters = new LiveSetVariable<>(restoreFilters(), AsyncMode.SYNC); this.compositeFilter = new LiveExpression<Filter<BootDashElement>>() { { dependsOn(selectedFilters); } @Override protected Filter<BootDashElement> compute() { Filter<BootDashElement> composed = Filters.acceptAll(); for (FilterChoice chosen : selectedFilters.getValues()) { composed = Filters.compose(composed, chosen.getFilter()); } return composed; } }; selectedFilters.addListener(new ValueListener<ImmutableSet<FilterChoice>>() { public void gotValue(LiveExpression<ImmutableSet<FilterChoice>> exp, ImmutableSet<FilterChoice> value) { saveFilters(value); } }); } public static class FilterChoice implements Ilabelable { private final String id; private final String label; private final Filter<BootDashElement> filter; private final boolean defaultEnable; public FilterChoice(String id, String label, Filter<BootDashElement> filter) { this(id, label, filter, false); } public FilterChoice(String id, String label, Filter<BootDashElement> filter, boolean defaultEnable) { this.id = id; this.label = label; this.filter = filter; this.defaultEnable = defaultEnable; } @Override public String toString() { return "FilterChoice("+getLabel()+")"; } @Override public String getLabel() { return label; } public Filter<BootDashElement> getFilter() { return filter; } public String getId() { return id; } } private final LiveSetVariable<FilterChoice> selectedFilters; private final LiveExpression<Filter<BootDashElement>> compositeFilter; /** * @return The filter that is defined by composing all the selected toggle filters. */ public LiveExpression<Filter<BootDashElement>> getFilter() { return compositeFilter; } private Set<FilterChoice> restoreFilters() { Set<FilterChoice> builder = new HashSet<>(); for (FilterChoice filter : getAvailableFilters()) { if (persistentProperties.get(filter.getId(), filter.defaultEnable)) { builder.add(filter); } } return builder; } private void saveFilters(ImmutableSet<FilterChoice> filters) { try { for (FilterChoice f : getAvailableFilters()) { boolean active = filters.contains(f); if (active==f.defaultEnable) { //don't store default values that way if we change the default in the future then // users will get the new default rather than their persisted value persistentProperties.put(f.getId(), (String)null); } else { persistentProperties.put(f.getId(), active); } } } catch (Exception e) { //trouble saving filters... log and move on. This is not critical Log.log(e); } } public FilterChoice[] getAvailableFilters() { return FILTERS; } public LiveSetVariable<FilterChoice> getSelectedFilters() { return selectedFilters; } }