/* * Copyright (c) 2015-2015 Vladimir Schneider <vladimir.schneider@gmail.com> * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 com.vladsch.idea.multimarkdown.settings; import com.intellij.openapi.application.ApplicationInfo; import com.intellij.ui.EditorTextField; import com.vladsch.idea.multimarkdown.MultiMarkdownPlugin; import org.apache.log4j.Logger; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.ArrayList; public class Settings { private static final Logger logger = Logger.getLogger(Settings.class); final protected ArrayList<Setting> settings = new ArrayList<Setting>(50); @Nullable final protected SettingsNotifier notifier; public ArrayList<Setting> getSettings() { return settings; } public Settings(@Nullable SettingsNotifier notifier) { this.notifier = notifier; } public BooleanSetting BooleanSetting(Boolean initialValue, String persistName, int flags) { return new BooleanSetting(initialValue, persistName, flags, false, false); } public BooleanSetting BooleanSetting(Boolean initialValue, String persistName, int flags, boolean isLicensedFeature) { return new BooleanSetting(initialValue, persistName, flags, isLicensedFeature, false); } public BooleanSetting LocalBooleanSetting(Boolean initialValue, String persistName, int flags) { return new BooleanSetting(initialValue, persistName, flags, false, true); } public BooleanSetting LocalBooleanSetting(Boolean initialValue, String persistName, int flags, boolean isLicensedFeature) { return new BooleanSetting(initialValue, persistName, flags, isLicensedFeature, true); } public ElementSetting ElementSetting(Element initialValue, String persistName) { return new ElementSetting(initialValue, persistName, false, false); } public ElementSetting LocalElementSetting(Element initialValue, String persistName) { return new ElementSetting(initialValue, persistName, false, true); } public IntegerSetting IntegerSetting(Integer initialValue, String persistName) { return new IntegerSetting(initialValue, persistName); } public DoubleSetting DoubleSetting(Double initialValue, String persistName) { return new DoubleSetting(initialValue, persistName); } public StringSetting StringSetting(String initialValue, String persistName) { return new StringSetting(initialValue, persistName, false, false); } public StringSetting StringSetting(String initialValue, String persistName, boolean isLicensedFeature) { return new StringSetting(initialValue, persistName, isLicensedFeature, false); } public StringSetting LocalStringSetting(String initialValue, String persistName) { return new StringSetting(initialValue, persistName, false, true); } public StringSetting LocalStringSetting(String initialValue, String persistName, boolean isLicensedFeature) { return new StringSetting(initialValue, persistName, isLicensedFeature, true); } public FailedBuildSetting FailedBuildSetting(String initialValue, String persistName) { return new FailedBuildSetting(initialValue, persistName, false, true); } public FailedBuildSetting FailedBuildSetting(String initialValue, String persistName, boolean withJdk) { return new FailedBuildSetting(initialValue, persistName, withJdk, true); } //public Element getState(String name) { // final Element element = new Element(name); // for (Setting setting : settings) { // setting.saveState(element); // } // return element; //} public void getState(Element element, Boolean isRoamingDisabled) { for (Setting setting : settings) { if (isRoamingDisabled == null || setting.isNonRoaming == isRoamingDisabled) { setting.saveState(element); } } } public Element getState(String name, ComponentProvider provider, Boolean isRoamingDisabled) { final Element element = new Element(name); for (Setting setting : settings) { if (isRoamingDisabled == null || setting.isNonRoaming == isRoamingDisabled) { String value = (String) provider.getComponent(setting.persistName); //noinspection unchecked setting.setValue(value == null ? setting.getDefaultValue() : setting.fromString(value)); setting.saveState(element); } } return element; } public void loadState(@NotNull Element element, Boolean isRoamingDisabled) { if (notifier != null) notifier.startGroupNotifications(); for (Setting setting : settings) { if (isRoamingDisabled == null || setting.isNonRoaming == isRoamingDisabled) { setting.loadState(element); } } if (notifier != null) notifier.endGroupNotifications(); } public boolean isChanged(@NotNull Element element, @NotNull ComponentProvider componentProvider) { for (Settings.Setting setting : settings) { if (setting instanceof ElementSetting) { ((ElementSetting) setting).isChanged(element); } else { String storedValue = element.getAttributeValue(setting.persistName); String currentValue = (String) componentProvider.getComponent(setting.persistName); //noinspection ConstantConditions if ((storedValue == null) != (currentValue == null) || (storedValue != null && currentValue != null && !setting.fromString(currentValue).equals(setting.fromString(storedValue)))) return true; } } return false; } public int getExtensionsValue() { int extensionFlags = 0; for (Setting setting : settings) { extensionFlags |= setting.getExtensionValue(); } return extensionFlags; } public abstract class Setting<T> { private T value; final protected T initialValue; final protected boolean isLicensedFeature; final protected boolean isNonRoaming; protected String persistName; public Setting(T initialValue, String persistName) { this(initialValue, persistName, false, false); } public Setting(T initialValue, String persistName, boolean isLicensedFeature) { this(initialValue, persistName, isLicensedFeature, false); } public Setting(T initialValue, String persistName, boolean isLicensedFeature, boolean isNonRoaming) { this.initialValue = initialValue; this.value = initialValue; this.persistName = persistName; this.isLicensedFeature = isLicensedFeature; this.isNonRoaming = isNonRoaming; settings.add(this); } public T getValue() { return (!isLicensedFeature) ? value : initialValue; } public void setValue(T value) { if (!isLicensedFeature) { if (!isEqual(value)) { this.value = value; if (notifier != null) notifier.notifyListeners(); } } } public boolean isEqual(T value) { return this.value == value; } public void loadState(Element element) { if (!isLicensedFeature) { String value = element.getAttributeValue(persistName); if (value != null) setValue(fromString(value)); } } public void saveState(Element element) { if (!isLicensedFeature) { //logger.info("saving state for " + persistName); element.setAttribute(persistName, value.toString()); } } public int getExtensionValue() { return 0; } public boolean isChanged(T that) { return !value.equals(that); } abstract public T fromString(String value); abstract public T getDefaultValue(); } public class IntegerSetting extends Setting<Integer> { public IntegerSetting(Integer initialValue, String persistName) { super(initialValue, persistName); } @Override public Integer fromString(String value) { return Integer.parseInt(value); } @Override public Integer getDefaultValue() { return 0; } public void setValue(JSpinner component) { setValue((Integer) component.getValue()); } public void reset(JSpinner component) { component.setValue(getValue()); } public boolean isChanged(JSpinner component) { return !getValue().equals((Integer) component.getValue()); } public void setValue(JComboBox component) { setValue((Integer) component.getSelectedIndex()); } public void reset(JComboBox component) { component.setSelectedIndex(getValue()); } public boolean isChanged(JComboBox component) { return !getValue().equals((Integer) component.getSelectedIndex()); } public void setValue(JTabbedPane component) { setValue((Integer) component.getSelectedIndex()); } public void reset(JTabbedPane component) { component.setSelectedIndex(getValue()); } public boolean isChanged(JTabbedPane component) { return !getValue().equals((Integer) component.getSelectedIndex()); } public void setValue(JList component) { setValue((Integer) component.getSelectedIndex()); } public void reset(JList component) { component.setSelectedIndex(getValue()); } public boolean isChanged(JList component) { return !getValue().equals((Integer) component.getSelectedIndex()); } } public class DoubleSetting extends Setting<Double> { public DoubleSetting(Double initialValue, String persistName) { super(initialValue, persistName); } @Override public Double fromString(String text) { return Double.parseDouble(text); } @Override public Double getDefaultValue() { return 0.0; } public void setValue(JSpinner component) { setValue((Double) component.getValue()); } public void reset(JSpinner component) { component.setValue(getValue()); } public boolean isChanged(JSpinner component) { return !getValue().equals((Double) component.getValue()); } } public class BooleanSetting extends Setting<Boolean> { final protected int flags; public BooleanSetting(Boolean initialValue, String persistName, int flags, boolean isLicensedFeature, boolean isNonRoaming) { super(initialValue, persistName, isLicensedFeature, isNonRoaming); this.flags = flags; } @Override public Boolean fromString(String text) { return Boolean.parseBoolean(text); } @Override public Boolean getDefaultValue() { return false; } @Override public int getExtensionValue() { return getValue() ? flags : 0; } public void setValue(JCheckBox component) { setValue(component.isSelected()); } public void reset(JCheckBox component) { component.setSelected(getValue()); } public boolean isChanged(JCheckBox component) { return !getValue().equals((Boolean) component.isSelected()); } } public class StringSetting extends Setting<String> { public StringSetting(String initialValue, String persistName, boolean isLicensedFeature, boolean isNonRoaming) { super(initialValue, persistName, isLicensedFeature, isNonRoaming); } @Override public String fromString(String text) { return text; } @Override public String getDefaultValue() { return ""; } @Override public boolean isEqual(String text) { return getValue().equals(text); } public void setValue(JTextArea component) { setValue(component.getText()); } public void setValue(EditorTextField component) { setValue(component.getText()); } public void reset(JTextArea component) { component.setText(getValue()); } public void reset(EditorTextField component) { component.setText(getValue()); } public boolean isChanged(JTextArea component) { return !getValue().equals(component.getText()); } public boolean isChanged(EditorTextField component) { return !getValue().equals(component.getText()); } } public class FailedBuildSetting extends StringSetting { protected final boolean withJdk; public FailedBuildSetting(String initialValue, String persistName, boolean withJdk, boolean isNonRoaming) { super(initialValue, persistName, false, true); this.withJdk = withJdk; } protected String currentBuild() { String ideaBuild = ApplicationInfo.getInstance().getBuild().asString(); if (withJdk) { ideaBuild += ", " + System.getProperty("java.home"); } return ideaBuild; } public boolean isFailedBuild() { String ideaBuild = currentBuild(); return getValue() != null && getValue().equals(ideaBuild); } public <T> T runBuild(FailedBuildRunnable<T> runnable) { String ideaBuild = currentBuild(); if (getValue() == null || !getValue().equals(ideaBuild)) { try { return runnable.runCanFail(); } catch (Throwable e) { setValue(ideaBuild); } } return runnable.run(); } } public class ElementSetting extends Setting<Element> { public ElementSetting(Element initialValue, String persistName, boolean isLicensedFeature, boolean isNonRoaming) { super(initialValue != null ? initialValue.clone() : null, persistName, isLicensedFeature, isNonRoaming); } @Override public void setValue(Element element) { super.setValue(element != null ? element.clone() : null); } @Override public Element fromString(String text) { return null; } @Override public Element getDefaultValue() { return null; } @Override public void loadState(@NotNull Element element) { Element child = element.getChild(persistName); setValue(child); } @Override public void saveState(@NotNull Element element) { if (getValue() != null) { element.addContent(getValue().clone()); } } public void setValue(@NotNull ComponentState component) { setValue(component.getState(persistName)); } public void reset(@NotNull ComponentState component) { component.loadState(getValue()); } public boolean isChanged(@NotNull ComponentState component) { return getValue() == null || component.isChanged(getValue()); } } }