1 /*******************************************************************************
2  * Copyright (c) 2014 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.e4.ui.css.swt.helpers;
15 
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
20 import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
21 import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
22 import org.osgi.service.prefs.Preferences;
23 
24 public class EclipsePreferencesHelper {
25 	public static final String PROPS_OVERRIDDEN_BY_CSS_PROP = "overriddenByCSS";
26 
27 	public static final String SEPARATOR = ",";
28 
29 	private static final String MULTI_VALUE_FORMATTER = "%s%s" + SEPARATOR;
30 
31 	private static IPreferenceChangeListener preferenceChangeListener;
32 
33 	private static String previousThemeId;
34 
35 	private static String currentThemeId;
36 
appendOverriddenPropertyName( IEclipsePreferences preferences, String name)37 	public static void appendOverriddenPropertyName(
38 			IEclipsePreferences preferences, String name) {
39 		String value = preferences.get(PROPS_OVERRIDDEN_BY_CSS_PROP, SEPARATOR);
40 		if (value.equals(SEPARATOR)) {
41 			preferences
42 			.addPreferenceChangeListener(getPreferenceChangeListener());
43 		}
44 		if (!isOverriddenByCSS(value, name)) {
45 			preferences.put(PROPS_OVERRIDDEN_BY_CSS_PROP,
46 					String.format(MULTI_VALUE_FORMATTER, value, name));
47 		}
48 	}
49 
getPreferenceChangeListener()50 	public static IPreferenceChangeListener getPreferenceChangeListener() {
51 		if (preferenceChangeListener == null) {
52 			preferenceChangeListener = new PreferenceOverriddenByCssChangeListener();
53 		}
54 		return preferenceChangeListener;
55 	}
56 
isOverriddenByCSS(String propertiesOverriddenByCSS, String property)57 	private static boolean isOverriddenByCSS(String propertiesOverriddenByCSS,
58 			String property) {
59 		return propertiesOverriddenByCSS.contains(SEPARATOR + property
60 				+ SEPARATOR);
61 	}
62 
getOverriddenPropertyNames( IEclipsePreferences preferences)63 	public static List<String> getOverriddenPropertyNames(
64 			IEclipsePreferences preferences) {
65 		String value = preferences.get(PROPS_OVERRIDDEN_BY_CSS_PROP, null);
66 		if (value == null) {
67 			return Collections.emptyList();
68 		}
69 		List<String> result = new ArrayList<>();
70 		for (String name : value.split(SEPARATOR)) {
71 			if (name != null && !name.isEmpty()) {
72 				result.add(name);
73 			}
74 		}
75 		return result;
76 	}
77 
removeOverriddenPropertyNames( IEclipsePreferences preferences)78 	public static void removeOverriddenPropertyNames(
79 			IEclipsePreferences preferences) {
80 		preferences.remove(PROPS_OVERRIDDEN_BY_CSS_PROP);
81 		preferences
82 		.removePreferenceChangeListener(getPreferenceChangeListener());
83 	}
84 
removeOverriddenByCssProperty( IEclipsePreferences preferences, String preferenceToRemove)85 	public static void removeOverriddenByCssProperty(
86 			IEclipsePreferences preferences, String preferenceToRemove) {
87 		StringBuilder overriddenByCSS = new StringBuilder(SEPARATOR);
88 		for (String preference : getOverriddenPropertyNames(preferences)) {
89 			if (!preference.equals(preferenceToRemove)) {
90 				overriddenByCSS.append(preference).append(SEPARATOR);
91 			}
92 		}
93 		preferences.put(PROPS_OVERRIDDEN_BY_CSS_PROP,
94 				overriddenByCSS.toString());
95 	}
96 
setPreviousThemeId(String themeId)97 	public static void setPreviousThemeId(String themeId) {
98 		previousThemeId = themeId;
99 	}
100 
setCurrentThemeId(String themeId)101 	public static void setCurrentThemeId(String themeId) {
102 		currentThemeId = themeId;
103 	}
104 
isThemeChanged()105 	public static boolean isThemeChanged() {
106 		return currentThemeId != null && !currentThemeId.equals(previousThemeId);
107 	}
108 
109 	public static class PreferenceOverriddenByCssChangeListener implements
110 	IPreferenceChangeListener {
111 		@Override
preferenceChange(PreferenceChangeEvent event)112 		public void preferenceChange(PreferenceChangeEvent event) {
113 			if (isModified(event) && isRelatedToOverriddenByCss(event)) {
114 				removeOverriddenByCssProperty(event);
115 			}
116 		}
117 
isModified(PreferenceChangeEvent event)118 		private boolean isModified(PreferenceChangeEvent event) {
119 			return event.getOldValue() != null && event.getNewValue() != null;
120 		}
121 
isRelatedToOverriddenByCss(PreferenceChangeEvent event)122 		private boolean isRelatedToOverriddenByCss(PreferenceChangeEvent event) {
123 			return isOverriddenByCSS(
124 					event.getNode()
125 					.get(PROPS_OVERRIDDEN_BY_CSS_PROP, SEPARATOR),
126 					event.getKey());
127 		}
128 
removeOverriddenByCssProperty(PreferenceChangeEvent event)129 		protected void removeOverriddenByCssProperty(PreferenceChangeEvent event) {
130 			Preferences preferences = event.getNode();
131 			if (preferences instanceof IEclipsePreferences) {
132 				EclipsePreferencesHelper.removeOverriddenByCssProperty(
133 						(IEclipsePreferences) preferences, event.getKey());
134 			}
135 		}
136 	}
137 }
138