/*
* Copyright 2013-2016 consulo.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package consulo.options;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.NotNullComputable;
import consulo.annotations.RequiredDispatchThread;
import consulo.ui.Component;
import consulo.ui.RequiredUIAccess;
import consulo.ui.ValueComponent;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* @author VISTALL
* @since 19-Nov-16.
*/
public abstract class SimpleConfigurableByProperties extends SimpleConfigurable<SimpleConfigurableByProperties.LayoutWrapper> {
protected static class LayoutWrapper implements NotNullComputable<Component> {
private Component myComponent;
public LayoutWrapper(Component component) {
myComponent = component;
}
@NotNull
@Override
public Component compute() {
return myComponent;
}
}
private static class Property<T> {
private Supplier<T> myUIGetter;
private Consumer<T> myUISetter;
private Supplier<T> mySettingGetter;
private Consumer<T> mySettingSetter;
private Property(Supplier<T> uiGetter, Consumer<T> uiSetter, Supplier<T> settingGetter, Consumer<T> settingSetter) {
myUIGetter = uiGetter;
myUISetter = uiSetter;
mySettingGetter = settingGetter;
mySettingSetter = settingSetter;
}
public boolean isModified() {
T uiValue = myUIGetter.get();
T settingValue = mySettingGetter.get();
return !Comparing.equal(uiValue, settingValue);
}
public void reset() {
myUISetter.accept(mySettingGetter.get());
}
public void apply() {
mySettingSetter.accept(myUIGetter.get());
}
}
protected static class PropertyBuilder {
private List<Property<?>> myProperties = new ArrayList<>();
public <T> void add(@NotNull ValueComponent<T> valueComponent, @NotNull Supplier<T> getter, @NotNull Consumer<T> setter) {
myProperties.add(new Property<T>(valueComponent::getValue, valueComponent::setValue, getter, setter));
}
}
private List<Property<?>> myProperties = Collections.emptyList();
@RequiredUIAccess
@NotNull
protected abstract Component createLayout(PropertyBuilder propertyBuilder);
@RequiredUIAccess
@NotNull
@Override
protected final SimpleConfigurableByProperties.LayoutWrapper createPanel() {
PropertyBuilder builder;
Component panel = createLayout(builder = new PropertyBuilder());
myProperties = builder.myProperties;
return new LayoutWrapper(panel);
}
@RequiredUIAccess
@Override
protected boolean isModified(@NotNull SimpleConfigurableByProperties.LayoutWrapper component) {
for (Property<?> property : myProperties) {
if (property.isModified()) {
return true;
}
}
return false;
}
@RequiredUIAccess
@Override
protected void apply(@NotNull SimpleConfigurableByProperties.LayoutWrapper component) throws ConfigurationException {
for (Property<?> property : myProperties) {
property.apply();
}
}
@RequiredUIAccess
@Override
protected void reset(@NotNull SimpleConfigurableByProperties.LayoutWrapper component) {
for (Property<?> property : myProperties) {
property.reset();
}
}
@RequiredDispatchThread
@Override
protected void disposeUIResources(@NotNull SimpleConfigurableByProperties.LayoutWrapper component) {
super.disposeUIResources(component);
myProperties = Collections.emptyList();
}
}