package net.jeeeyul.eclipse.themes.ui.hotswap;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import net.jeeeyul.eclipse.themes.JThemesCore;
import net.jeeeyul.eclipse.themes.ui.internal.Debug;
import net.jeeeyul.eclipse.themes.ui.preference.JTPConstants;
import net.jeeeyul.eclipse.themes.ui.preference.JThemePreferenceStore;
import net.jeeeyul.swtend.SWTExtensions;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.core.resources.IResourcesRegistry;
import org.eclipse.e4.ui.internal.workbench.swt.CSSRenderingUtils;
import org.eclipse.e4.ui.widgets.ImageBasedFrame;
import org.eclipse.e4.ui.workbench.renderers.swt.TrimmedPartLayout;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Resource;
import org.eclipse.swt.graphics.Transform;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.w3c.dom.Element;
import org.w3c.dom.css.CSSStyleDeclaration;
/**
*
* @author Jeeeyul
*/
@SuppressWarnings("restriction")
public class HotSwap {
/**
*
*/
public static final HotSwap INSTANCE = new HotSwap();
private HashMap<ImageBasedFrame, HashSet<Resource>> trackedFrames = new HashMap<ImageBasedFrame, HashSet<Resource>>();
private HotSwap() {
}
private void bind(ImageBasedFrame owner, Resource... r) {
HashSet<Resource> hashSet = trackedFrames.get(owner);
if (hashSet == null) {
hashSet = new HashSet<Resource>();
trackedFrames.put(owner, hashSet);
}
hashSet.addAll(Arrays.asList(r));
}
private void disposeBindedResources(ImageBasedFrame f) {
HashSet<Resource> hashSet = trackedFrames.get(f);
if (hashSet != null) {
Debug.println(MessageFormat.format("Image Frame {0} disposed {1} resources", f.hashCode(), hashSet.size()));
SWTExtensions.INSTANCE.safeDispose(hashSet);
hashSet.clear();
}
}
/**
* @param cssEngine
*/
public void fixDragHandles(CSSEngine cssEngine) {
for (Shell each : Display.getDefault().getShells()) {
Iterator<? extends Widget> iter = SWTExtensions.INSTANCE.getAllContent(each);
while (iter.hasNext()) {
Widget w = iter.next();
if (w instanceof ImageBasedFrame) {
fixHandle(cssEngine, w);
}
}
}
}
private Image rotateImage(Display display, Image image, Integer[] frameInts) {
// Swap the widths / heights of the 'cuts'
if (frameInts != null) {
int tmp;
tmp = frameInts[0];
frameInts[0] = frameInts[2];
frameInts[2] = tmp;
tmp = frameInts[1];
frameInts[1] = frameInts[3];
frameInts[3] = tmp;
}
// rotate 90 degrees,,,
Rectangle bounds = image.getBounds();
ImageData imageData = new ImageData(bounds.height, bounds.width, 32, new PaletteData(0xFF0000, 0x00FF00, 0x0000FF));
Image rotatedImage = new Image(display, imageData);
GC gc = new GC(rotatedImage);
RGB rgb = new RGB(0x7d, 0, 0);
Color offRed = new Color(display, rgb);
gc.setBackground(offRed);
gc.fillRectangle(0, 0, bounds.height, bounds.width);
Transform t = new Transform(display);
int w = image.getBounds().height;
int offset = 0; // (w+1) % 2;
t.translate(w - offset, 0);
t.rotate(90);
gc.setTransform(t);
gc.drawImage(image, 0, 0);
gc.dispose();
t.dispose();
offRed.dispose();
ImageData alphaData = rotatedImage.getImageData();
rotatedImage.dispose();
int transparentPix = alphaData.palette.getPixel(rgb);
for (int i = 0; i < alphaData.width; i++) {
for (int j = 0; j < alphaData.height; j++) {
if (alphaData.getPixel(i, j) != transparentPix) {
alphaData.setAlpha(i, j, 255);
}
}
}
rotatedImage = new Image(display, alphaData);
// Return the new one
return rotatedImage;
}
private void fixHandle(CSSEngine cssEngine, Widget w) {
final ImageBasedFrame f = (ImageBasedFrame) w;
if (!trackedFrames.containsKey(f)) {
f.addListener(SWT.Dispose, new Listener() {
@Override
public void handleEvent(Event event) {
disposeBindedResources(f);
trackedFrames.remove(f);
}
});
}
Element element = cssEngine.getElement(f);
CSSStyleDeclaration style = cssEngine.getViewCSS().getComputedStyle(element, "");
if (style != null) {
try {
Control firstChild = f.getChildren()[0];
if (!(firstChild instanceof ToolBar)) {
return;
}
ToolBar toolBar = (ToolBar) firstChild;
boolean vertical = (toolBar.getStyle() & SWT.VERTICAL) != 0;
CSSRenderingUtils util = new CSSRenderingUtils();
Integer[] frameInts = new Integer[4];
Image frameImage = util.createImage(f, null, "frame-image", frameInts);
if (frameImage != null && vertical) {
frameImage = rotateImage(f.getDisplay(), frameImage, frameInts);
bind(f, frameImage);
}
Image handleImage = util.createImage(f, null, "handle-image", null);
if (handleImage != null && vertical) {
handleImage = rotateImage(f.getDisplay(), handleImage, null);
bind(f, handleImage);
}
if (frameImage != null) {
f.setImages(frameImage, frameInts, handleImage);
} else if (handleImage != null) {
f.setImages(null, null, handleImage);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private Rectangle windowMargins() {
JThemePreferenceStore store = JThemesCore.getDefault().getPreferenceStore();
Rectangle margins = store.getRectangle(JTPConstants.Window.MARGINS);
if (store.getBoolean(JTPConstants.Layout.SHOW_SHADOW)) {
margins.x = Math.max(margins.x - 1, 0);
margins.width = Math.max(margins.width - 4, 0);
margins.height = Math.max(margins.height - 4, 0);
} else {
margins.width = Math.max(margins.width - 1, 0);
margins.height = Math.max(margins.height - 1, 0);
}
return margins;
}
/**
*
*/
public void fixWindowMargins() {
for (IWorkbenchWindow each : PlatformUI.getWorkbench().getWorkbenchWindows()) {
TrimmedPartLayout layout = (TrimmedPartLayout) each.getShell().getLayout();
Rectangle margins = windowMargins();
layout.gutterTop = margins.y;
layout.gutterBottom = margins.height;
layout.gutterLeft = margins.x;
layout.gutterRight = margins.width;
}
}
/**
* @param cssEngine
*/
public void releaseHandleImages(CSSEngine cssEngine) {
IResourcesRegistry resourcesRegistry = cssEngine.getResourcesRegistry();
new ResourceRegistryHack().disposeDynamicImages(resourcesRegistry);
}
}