package net.jeeeyul.eclipse.themes.ui.hotswap;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import net.jeeeyul.eclipse.themes.JThemesCore;
import net.jeeeyul.eclipse.themes.ui.internal.Debug;
import net.jeeeyul.eclipse.themes.ui.internal.ENVHelper;
import org.eclipse.e4.ui.css.core.dom.ExtendedCSSRule;
import org.eclipse.e4.ui.css.core.dom.ExtendedDocumentCSS;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.swt.dom.WidgetElement;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.w3c.css.sac.SelectorList;
import org.w3c.dom.css.CSSRuleList;
import org.w3c.dom.css.CSSStyleSheet;
import org.w3c.dom.css.DocumentCSS;
import org.w3c.dom.stylesheets.StyleSheet;
import org.w3c.dom.stylesheets.StyleSheetList;
/**
* re-generate "jeeeyul-custom.css" and replace with existing style sheet.
*
* @author Jeeeyul
* @since 1.2
*/
@SuppressWarnings("restriction")
public class RewriteCustomTheme {
/**
* A selector text to detect custom theme sheet.
*
* @see #findCustomThemeSheet(DocumentCSS)
*/
public static final String CUSTOM_THEME_FIRST_SELECTOR = "*[class=\"jeeeyul-custom-theme\"]";
private Display display = Display.getDefault();
private boolean hotSwap;
/**
*
*/
public RewriteCustomTheme() {
this(false);
}
/**
* @param hotSwap
*/
public RewriteCustomTheme(boolean hotSwap) {
this.hotSwap = hotSwap;
}
private void applyTheme(String css) throws IOException {
Debug.println("Theme is about to rewrite");
CSSEngine cssEngine = WidgetElement.getEngine(display);
if (hotSwap) {
HotSwap.INSTANCE.fixWindowMargins();
}
ExtendedDocumentCSS documentCSS = (ExtendedDocumentCSS) cssEngine.getDocumentCSS();
StyleSheet customThemeSheet = findCustomThemeSheet(documentCSS);
StyleSheet newSheet = cssEngine.parseStyleSheet(new StringReader(css));
StyleSheetList oldSheetList = documentCSS.getStyleSheets();
List<StyleSheet> newSheetList = new ArrayList<StyleSheet>();
for (int i = 0; i < oldSheetList.getLength(); i++) {
StyleSheet oldSheet = oldSheetList.item(i);
if (oldSheet != customThemeSheet) {
if (!newSheetList.contains(oldSheet))
newSheetList.add(oldSheet);
} else {
if (!newSheetList.contains(newSheet))
newSheetList.add(newSheet);
}
}
documentCSS.removeAllStyleSheets();
if (hotSwap && ENVHelper.INSTANCE.isLunaOrAbove()) {
HotSwap.INSTANCE.releaseHandleImages(cssEngine);
Debug.println("Old handle and frame images are disposed.");
}
for (StyleSheet each : newSheetList) {
documentCSS.addStyleSheet(each);
}
cssEngine.reapply();
for (Shell each : Display.getDefault().getShells()) {
each.layout(true, true);
}
if (hotSwap && ENVHelper.INSTANCE.isLunaOrAbove()) {
HotSwap.INSTANCE.fixDragHandles(cssEngine);
Debug.println("Old handle and frame images are hot-swapped.");
}
Debug.println("Theme was re-written");
}
/**
* find and returns a {@link StyleSheet} which represent
* "jeeeyul-custom.css".
*
* @param documentCSS
* @return
* @since 1.2
*/
private StyleSheet findCustomThemeSheet(DocumentCSS documentCSS) {
StyleSheet customThemeSheet = null;
StyleSheetList styleSheets = documentCSS.getStyleSheets();
SearchCustomThemeSheet: for (int i = 0; i < styleSheets.getLength(); i++) {
StyleSheet eachSheet = styleSheets.item(i);
if (eachSheet instanceof CSSStyleSheet) {
CSSRuleList cssRules = ((CSSStyleSheet) eachSheet).getCssRules();
for (int j = 0; j < cssRules.getLength(); j++) {
ExtendedCSSRule rule = (ExtendedCSSRule) cssRules.item(j);
SelectorList selectorList = rule.getSelectorList();
String selectorText = selectorList.item(0).toString();
if (CUSTOM_THEME_FIRST_SELECTOR.equals(selectorText)) {
customThemeSheet = eachSheet;
break SearchCustomThemeSheet;
}
}
}
}
return customThemeSheet;
}
/**
* Rewrite "/css/jeeeyul-custom.css" with user preference.
*/
public void rewrite() {
try {
CustomThemeGenerator generator = new CustomThemeGenerator(JThemesCore.getDefault().getPreferenceStore());
String newCSSContent = generator.generate().toString();
applyTheme(newCSSContent);
} catch (Exception e) {
e.printStackTrace();
}
}
}