/*
* Copyright (c) 2011-2014 Julien Nicoulaud <julien.nicoulaud@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 net.nicoulaj.idea.markdown.settings;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.pegdown.Extensions;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Set;
/**
* Persistent global settings object for the Markdown plugin.
*
* @author Julien Nicoulaud <julien.nicoulaud@gmail.com>
* @since 0.6
*/
@State(
name = "MarkdownSettings",
storages = @Storage(id = "other", file = "$APP_CONFIG$/markdown.xml")
)
public class MarkdownGlobalSettings implements PersistentStateComponent<Element> {
/** A set of listeners to this object state changes. */
protected Set<WeakReference<MarkdownGlobalSettingsListener>> listeners;
/** Parsing timeout (milliseconds). */
private int parsingTimeout = 10000;
/** Whether the "SmartyPants style pretty ellipsises, dashes and apostrophes" extension should be enabled. */
private boolean smarts = false;
/** Whether the "SmartyPants style pretty single and double quotes" extension should be enabled. */
private boolean quotes = false;
/** Whether the "PHP Markdown Extra style abbreviations" extension should be enabled. */
private boolean abbreviations = false;
/** Whether the "PHP Markdown Extra style definition lists" extension should be enabled. */
private boolean definitions = false;
/** Whether the "PHP Markdown Extra style fenced code blocks" extension should be enabled. */
private boolean fencedCodeBlocks = false;
/** Whether the "Github style hard wraps parsing as HTML linebreaks" extension should be enabled. */
private boolean hardWraps = false;
/** Whether the "Github style plain auto-links" extension should be enabled. */
private boolean autoLinks = false;
/** Whether the "Wiki-style links" extension should be enabled. */
private boolean wikiLinks = false;
/** Whether the "MultiMarkdown style tables support" extension should be enabled. */
private boolean tables = false;
/** Whether the "Suppress HTML blocks" extension should be enabled. */
private boolean suppressHTMLBlocks = false;
/** Whether the "Suppress inline HTML tags" extension should be enabled. */
private boolean suppressInlineHTML = false;
/** Whether the "Strikethroughs" extension should be enabled. */
private boolean strikethrough = false;
/**
* Get the instance of this service.
*
* @return the unique {@link MarkdownGlobalSettings} instance.
*/
public static MarkdownGlobalSettings getInstance() {
return ServiceManager.getService(MarkdownGlobalSettings.class);
}
/**
* Get the parsing timeout (milliseconds).
*
* @return parsing timeout (milliseconds)
*/
public int getParsingTimeout() {
return parsingTimeout;
}
/**
* Set parsing timeout (milliseconds).
*
* @param parsingTimeout parsing timeout (milliseconds)
*/
public void setParsingTimeout(int parsingTimeout) {
if (this.parsingTimeout != parsingTimeout) {
this.parsingTimeout = parsingTimeout;
notifyListeners();
}
}
/**
* Whether the "Strikethroughs" extension should be enabled.
*
* @return {@link #strikethrough}
*/
public boolean isStrikethrough() {
return strikethrough;
}
/**
* Whether the "Strikethroughs" extension should be enabled.
*
* @param strikethrough whether the "Suppress inline HTML tags" extension should be enabled.
*/
public void setStrikethrough(boolean strikethrough) {
if (this.strikethrough != strikethrough) {
this.strikethrough = strikethrough;
notifyListeners();
}
}
/**
* Whether the "Suppress inline HTML tags" extension should be enabled.
*
* @return {@link #suppressInlineHTML}
*/
public boolean isSuppressInlineHTML() {
return suppressInlineHTML;
}
/**
* Whether the "Suppress inline HTML tags" extension should be enabled.
*
* @param suppressInlineHTML whether the "Suppress inline HTML tags" extension should be enabled.
*/
public void setSuppressInlineHTML(boolean suppressInlineHTML) {
if (this.suppressInlineHTML != suppressInlineHTML) {
this.suppressInlineHTML = suppressInlineHTML;
notifyListeners();
}
}
/**
* Whether the "Suppress HTML blocks" extension should be enabled.
*
* @return {@link #suppressHTMLBlocks}
*/
public boolean isSuppressHTMLBlocks() {
return suppressHTMLBlocks;
}
/**
* Whether the "Suppress HTML blocks" extension should be enabled.
*
* @param suppressHTMLBlocks whether the "Suppress HTML blocks" extension should be enabled.
*/
public void setSuppressHTMLBlocks(boolean suppressHTMLBlocks) {
if (this.suppressHTMLBlocks != suppressHTMLBlocks) {
this.suppressHTMLBlocks = suppressHTMLBlocks;
notifyListeners();
}
}
/**
* Whether the "MultiMarkdown style tables support" extension should be enabled.
*
* @return {@link #tables}
*/
public boolean isTables() {
return tables;
}
/**
* Whether the "MultiMarkdown style tables support" extension should be enabled.
*
* @param tables whether the "MultiMarkdown style tables support" extension should be enabled.
*/
public void setTables(boolean tables) {
if (this.tables != tables) {
this.tables = tables;
notifyListeners();
}
}
/**
* Whether the "Wiki-style links" extension should be enabled.
*
* @return {@link #wikiLinks}
*/
public boolean isWikiLinks() {
return wikiLinks;
}
/**
* Whether the "Wiki-style links" extension should be enabled.
*
* @param wikiLinks whether the "Wiki-style links" extension should be enabled.
*/
public void setWikiLinks(boolean wikiLinks) {
if (this.wikiLinks != wikiLinks) {
this.wikiLinks = wikiLinks;
notifyListeners();
}
}
/**
* Whether the "Github style plain auto-links" extension should be enabled.
*
* @return {@link #autoLinks}
*/
public boolean isAutoLinks() {
return autoLinks;
}
/**
* Whether the "Github style plain auto-links" extension should be enabled.
*
* @param autoLinks whether the "Github style plain auto-links" extension should be enabled.
*/
public void setAutoLinks(boolean autoLinks) {
if (this.autoLinks != autoLinks) {
this.autoLinks = autoLinks;
notifyListeners();
}
}
/**
* Whether the "Github style hard wraps parsing as HTML linebreaks" extension should be enabled.
*
* @return {@link #hardWraps}
*/
public boolean isHardWraps() {
return hardWraps;
}
/**
* Whether the "Github style hard wraps parsing as HTML linebreaks" extension should be enabled.
*
* @param hardWraps whether the "Github style hard wraps parsing as HTML linebreaks" extension should be enabled.
*/
public void setHardWraps(boolean hardWraps) {
if (this.hardWraps != hardWraps) {
this.hardWraps = hardWraps;
notifyListeners();
}
}
/**
* Whether the "PHP Markdown Extra style fenced code blocks" extension should be enabled.
*
* @return {@link #fencedCodeBlocks}
*/
public boolean isFencedCodeBlocks() {
return fencedCodeBlocks;
}
/**
* Whether the "PHP Markdown Extra style fenced code blocks" extension should be enabled.
*
* @param fencedCodeBlocks whether the "PHP Markdown Extra style fenced code blocks" extension should be enabled.
*/
public void setFencedCodeBlocks(boolean fencedCodeBlocks) {
if (this.fencedCodeBlocks != fencedCodeBlocks) {
this.fencedCodeBlocks = fencedCodeBlocks;
notifyListeners();
}
}
/**
* Whether the "PHP Markdown Extra style definition lists" extension should be enabled.
*
* @return {@link #definitions}
*/
public boolean isDefinitions() {
return definitions;
}
/**
* Whether the "PHP Markdown Extra style definition lists" extension should be enabled.
*
* @param definitions whether the "PHP Markdown Extra style definition lists" extension should be enabled.
*/
public void setDefinitions(boolean definitions) {
if (this.definitions != definitions) {
this.definitions = definitions;
notifyListeners();
}
}
/**
* Whether the "PHP Markdown Extra style abbreviations" extension should be enabled.
*
* @return {@link #abbreviations}
*/
public boolean isAbbreviations() {
return abbreviations;
}
/**
* Whether the "PHP Markdown Extra style abbreviations" extension should be enabled.
*
* @param abbreviations whether the "PHP Markdown Extra style abbreviations" extension should be enabled.
*/
public void setAbbreviations(boolean abbreviations) {
if (this.abbreviations != abbreviations) {
this.abbreviations = abbreviations;
notifyListeners();
}
}
/**
* Whether the "SmartyPants style pretty single and double quotes" extension should be enabled.
*
* @return {@link #quotes}
*/
public boolean isQuotes() {
return quotes;
}
/**
* Whether the "SmartyPants style pretty single and double quotes" extension should be enabled.
*
* @param quotes whether the "SmartyPants style pretty single and double quotes" extension should be enabled.
*/
public void setQuotes(boolean quotes) {
if (this.quotes != quotes) {
this.quotes = quotes;
notifyListeners();
}
}
/**
* Whether the "SmartyPants style pretty ellipsises, dashes and apostrophes" extension should be enabled.
*
* @return {@link #smarts}
*/
public boolean isSmarts() {
return smarts;
}
/**
* Whether the "SmartyPants style pretty ellipsises, dashes and apostrophes" extension should be enabled.
*
* @param smarts whether the "SmartyPants style pretty ellipsises, dashes and apostrophes" extension should be enabled.
*/
public void setSmarts(boolean smarts) {
if (this.smarts != smarts) {
this.smarts = smarts;
notifyListeners();
}
}
/**
* Get the settings state as a DOM element.
*
* @return an ready to serialize DOM {@link Element}.
* @see {@link #loadState(org.jdom.Element)}
*/
public Element getState() {
final Element element = new Element("MarkdownSettings");
element.setAttribute("parsingTimeout", Integer.toString(parsingTimeout));
element.setAttribute("smarts", Boolean.toString(smarts));
element.setAttribute("quotes", Boolean.toString(quotes));
element.setAttribute("abbreviations", Boolean.toString(abbreviations));
element.setAttribute("hardWraps", Boolean.toString(hardWraps));
element.setAttribute("autoLinks", Boolean.toString(autoLinks));
element.setAttribute("wikiLinks", Boolean.toString(wikiLinks));
element.setAttribute("tables", Boolean.toString(tables));
element.setAttribute("definitions", Boolean.toString(definitions));
element.setAttribute("fencedCodeBlocks", Boolean.toString(fencedCodeBlocks));
element.setAttribute("suppressHTMLBlocks", Boolean.toString(suppressHTMLBlocks));
element.setAttribute("suppressInlineHTML", Boolean.toString(suppressInlineHTML));
element.setAttribute("strikethrough", Boolean.toString(strikethrough));
return element;
}
/**
* Load the settings state from the DOM {@link Element}.
*
* @param element the {@link Element} to load values from.
* @see {@link #getState()}
*/
public void loadState(@NotNull Element element) {
String value = element.getAttributeValue("parsingTimeout");
if (value != null) parsingTimeout = Integer.parseInt(value);
value = element.getAttributeValue("smarts");
if (value != null) smarts = Boolean.parseBoolean(value);
value = element.getAttributeValue("quotes");
if (value != null) quotes = Boolean.parseBoolean(value);
value = element.getAttributeValue("abbreviations");
if (value != null) abbreviations = Boolean.parseBoolean(value);
value = element.getAttributeValue("hardWraps");
if (value != null) hardWraps = Boolean.parseBoolean(value);
value = element.getAttributeValue("autoLinks");
if (value != null) autoLinks = Boolean.parseBoolean(value);
value = element.getAttributeValue("wikiLinks");
if (value != null) wikiLinks = Boolean.parseBoolean(value);
value = element.getAttributeValue("tables");
if (value != null) tables = Boolean.parseBoolean(value);
value = element.getAttributeValue("definitions");
if (value != null) definitions = Boolean.parseBoolean(value);
value = element.getAttributeValue("fencedCodeBlocks");
if (value != null) fencedCodeBlocks = Boolean.parseBoolean(value);
value = element.getAttributeValue("suppressHTMLBlocks");
if (value != null) suppressHTMLBlocks = Boolean.parseBoolean(value);
value = element.getAttributeValue("suppressInlineHTML");
if (value != null) suppressInlineHTML = Boolean.parseBoolean(value);
value = element.getAttributeValue("strikethrough");
if (value != null) strikethrough = Boolean.parseBoolean(value);
notifyListeners();
}
/**
* Get the extensions value to setup PegDown parser with.
*
* @return the value to use with {@link org.pegdown.PegDownProcessor(int)}
*/
public int getExtensionsValue() {
return
(smarts ? Extensions.SMARTS : 0) +
(quotes ? Extensions.QUOTES : 0) +
(abbreviations ? Extensions.ABBREVIATIONS : 0) +
(hardWraps ? Extensions.HARDWRAPS : 0) +
(autoLinks ? Extensions.AUTOLINKS : 0) +
(wikiLinks ? Extensions.WIKILINKS : 0) +
(tables ? Extensions.TABLES : 0) +
(definitions ? Extensions.DEFINITIONS : 0) +
(fencedCodeBlocks ? Extensions.FENCED_CODE_BLOCKS : 0) +
(suppressHTMLBlocks ? Extensions.SUPPRESS_HTML_BLOCKS : 0) +
(suppressInlineHTML ? Extensions.SUPPRESS_INLINE_HTML : 0) +
(strikethrough ? Extensions.STRIKETHROUGH : 0);
}
/**
* Add a listener to this settings object changes.
*
* @param listener the {@link MarkdownGlobalSettingsListener}.
*/
public void addListener(@NotNull final MarkdownGlobalSettingsListener listener) {
if (listeners == null) listeners = new HashSet<WeakReference<MarkdownGlobalSettingsListener>>();
listeners.add(new WeakReference<MarkdownGlobalSettingsListener>(listener));
}
/** Notify event listeners of changes. */
protected void notifyListeners() {
if (listeners != null)
for (final WeakReference<MarkdownGlobalSettingsListener> listenerRef : listeners)
if (listenerRef.get() != null) listenerRef.get().handleSettingsChanged(this);
}
}