diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f175fdc --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +**/bin +*.so +**/native-image/*-*.json + +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* diff --git a/draw2d/.classpath b/draw2d/.classpath new file mode 100644 index 0000000..4328baf --- /dev/null +++ b/draw2d/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/draw2d/.project b/draw2d/.project new file mode 100644 index 0000000..2482c9f --- /dev/null +++ b/draw2d/.project @@ -0,0 +1,17 @@ + + + demo.draw2d + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/draw2d/README.md b/draw2d/README.md new file mode 100644 index 0000000..a18a330 --- /dev/null +++ b/draw2d/README.md @@ -0,0 +1,17 @@ +build source +``` +./build.sh +``` +run and generate configuration for native image +``` +./run.sh -trace +``` +build native image +``` +./build.sh -native +``` +launch +``` +./draw2dapp +``` +Blog: [Graalvm Native Image Demo - JFace and Draw2D](https://www.spket.com/blog/graalvm-native-image-demo-jface-and-draw2d/) diff --git a/draw2d/build.sh b/draw2d/build.sh new file mode 100755 index 0000000..62a825e --- /dev/null +++ b/draw2d/build.sh @@ -0,0 +1,26 @@ +#! /bin/sh + +if [ -z "$GRAALVM_HOME" ]; then + GRAALVM_HOME=$HOME/tools/graalvm +fi + +LIBS_3RD=../../third-party +SWT_HOME=$LIBS_3RD/swt +SKIJA_HOME=$LIBS_3RD/skija +RCP_HOME=$LIBS_3RD/rcp +GEF_HOME=$LIBS_3RD/gef +CP=$SWT_HOME/swt.jar:$SKIJA_HOME/skija.jar:\ +$RCP_HOME/plugins/org.eclipse.jface_3.22.0.v20201106-0834.jar:\ +$RCP_HOME/plugins/org.eclipse.core.commands_3.9.800.v20201021-1339.jar:\ +$RCP_HOME/plugins/org.eclipse.equinox.common_3.14.0.v20201102-2053.jar:\ +$RCP_HOME/plugins/org.eclipse.ui.workbench_3.122.0.v20201122-1345.jar:\ +$GEF_HOME/plugins/org.eclipse.draw2d_3.10.100.201606061308.jar:\ +$GEF_HOME/plugins/org.eclipse.gef_3.11.0.201606061308.jar:\ +$GEF_HOME/plugins/org.eclipse.zest.core_1.5.300.201606061308.jar:\ +$GEF_HOME/plugins/org.eclipse.zest.layouts_1.1.300.201606061308.jar + +if [ "$1" = "-native" ]; then + $GRAALVM_HOME/bin/native-image -cp bin:res:$CP com.spket.demo.draw2d.Draw2DApp draw2dapp +else + $GRAALVM_HOME/bin/javac -cp res:$CP -d bin -sourcepath src:gtk src/com/spket/demo/draw2d/Draw2DApp.java +fi diff --git a/draw2d/gtk/com/spket/demo/draw2d/FigureCanvasGL.java b/draw2d/gtk/com/spket/demo/draw2d/FigureCanvasGL.java new file mode 100644 index 0000000..f07a021 --- /dev/null +++ b/draw2d/gtk/com/spket/demo/draw2d/FigureCanvasGL.java @@ -0,0 +1,301 @@ +package com.spket.demo.draw2d; + +import org.eclipse.draw2d.FigureCanvas; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.DPIUtil; +import org.eclipse.swt.internal.gtk.GDK; +import org.eclipse.swt.internal.gtk.GTK; +import org.eclipse.swt.internal.gtk.GdkWindowAttr; +import org.eclipse.swt.internal.gtk.OS; +import org.eclipse.swt.internal.opengl.glx.GLX; +import org.eclipse.swt.internal.opengl.glx.XVisualInfo; +import org.eclipse.swt.opengl.GLData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Listener; +import org.jetbrains.skija.BackendRenderTarget; +import org.jetbrains.skija.ColorSpace; +import org.jetbrains.skija.DirectContext; +import org.jetbrains.skija.FramebufferFormat; +import org.jetbrains.skija.Surface; +import org.jetbrains.skija.SurfaceColorFormat; +import org.jetbrains.skija.SurfaceOrigin; + +public class FigureCanvasGL extends FigureCanvas { + private static int checkStyle(int style) { + style |= SWT.V_SCROLL | SWT.H_SCROLL; + + return style; + } + + private static GLData createDefaultData() { + GLData data = new GLData(); + data.doubleBuffer = true; + data.stencilSize = 8; + return data; + } + + long foreContext; + long backContext; + + //long context; + long xWindow; + long glWindow; + XVisualInfo vinfo; + static final int MAX_ATTRIBUTES = 32; + + private Surface surface; + private DirectContext context; + private BackendRenderTarget renderTarget; + + public FigureCanvasGL(Composite parent) { + this(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND, createDefaultData()); + } + + public FigureCanvasGL(Composite parent, int style) { + this(parent, style, createDefaultData()); + } + + public FigureCanvasGL(Composite parent, int style, GLData data) { + super(checkStyle(style), parent, new LightweightSystemGL()); + + initGL(data, style); + } + + protected void initGL(GLData data, int style) { + if (OS.IsWin32) SWT.error (SWT.ERROR_NOT_IMPLEMENTED); + if (data == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); + int glxAttrib [] = new int [MAX_ATTRIBUTES]; + int pos = 0; + glxAttrib [pos++] = GLX.GLX_RGBA; + if (data.doubleBuffer) glxAttrib [pos++] = GLX.GLX_DOUBLEBUFFER; + if (data.stereo) glxAttrib [pos++] = GLX.GLX_STEREO; + if (data.redSize > 0) { + glxAttrib [pos++] = GLX.GLX_RED_SIZE; + glxAttrib [pos++] = data.redSize; + } + if (data.greenSize > 0) { + glxAttrib [pos++] = GLX.GLX_GREEN_SIZE; + glxAttrib [pos++] = data.greenSize; + } + if (data.blueSize > 0) { + glxAttrib [pos++] = GLX.GLX_BLUE_SIZE; + glxAttrib [pos++] = data.blueSize; + } + if (data.alphaSize > 0) { + glxAttrib [pos++] = GLX.GLX_ALPHA_SIZE; + glxAttrib [pos++] = data.alphaSize; + } + if (data.depthSize > 0) { + glxAttrib [pos++] = GLX.GLX_DEPTH_SIZE; + glxAttrib [pos++] = data.depthSize; + } + if (data.stencilSize > 0) { + glxAttrib [pos++] = GLX.GLX_STENCIL_SIZE; + glxAttrib [pos++] = data.stencilSize; + } + if (data.accumRedSize > 0) { + glxAttrib [pos++] = GLX.GLX_ACCUM_RED_SIZE; + glxAttrib [pos++] = data.accumRedSize; + } + if (data.accumGreenSize > 0) { + glxAttrib [pos++] = GLX.GLX_ACCUM_GREEN_SIZE; + glxAttrib [pos++] = data.accumGreenSize; + } + if (data.accumBlueSize > 0) { + glxAttrib [pos++] = GLX.GLX_ACCUM_BLUE_SIZE; + glxAttrib [pos++] = data.accumBlueSize; + } + if (data.accumAlphaSize > 0) { + glxAttrib [pos++] = GLX.GLX_ACCUM_ALPHA_SIZE; + glxAttrib [pos++] = data.accumAlphaSize; + } + if (data.sampleBuffers > 0) { + glxAttrib [pos++] = GLX.GLX_SAMPLE_BUFFERS; + glxAttrib [pos++] = data.sampleBuffers; + } + if (data.samples > 0) { + glxAttrib [pos++] = GLX.GLX_SAMPLES; + glxAttrib [pos++] = data.samples; + } + glxAttrib [pos++] = 0; + GTK.gtk_widget_realize (handle); + long window = GTK.gtk_widget_get_window (handle); + + long xDisplay = GDK.gdk_x11_display_get_xdisplay(GDK.gdk_window_get_display(window)); + long infoPtr = GLX.glXChooseVisual (xDisplay, OS.XDefaultScreen (xDisplay), glxAttrib); + if (infoPtr == 0) { + dispose (); + SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH); + } + vinfo = new XVisualInfo (); + GLX.memmove (vinfo, infoPtr, XVisualInfo.sizeof); + OS.XFree (infoPtr); + long screen = GDK.gdk_screen_get_default (); + long gdkvisual = GDK.gdk_x11_screen_lookup_visual (screen, vinfo.visualid); + long share = /* data.shareContext != null ? data.shareContext.context : */0; + foreContext = GLX.glXCreateContext (xDisplay, vinfo, share, true); + if (foreContext == 0) SWT.error (SWT.ERROR_NO_HANDLES); + GdkWindowAttr attrs = new GdkWindowAttr (); + attrs.width = 1; + attrs.height = 1; + attrs.event_mask = GDK.GDK_KEY_PRESS_MASK | GDK.GDK_KEY_RELEASE_MASK | + GDK.GDK_FOCUS_CHANGE_MASK | GDK.GDK_POINTER_MOTION_MASK | + GDK.GDK_BUTTON_PRESS_MASK | GDK.GDK_BUTTON_RELEASE_MASK | + GDK.GDK_ENTER_NOTIFY_MASK | GDK.GDK_LEAVE_NOTIFY_MASK | + GDK.GDK_EXPOSURE_MASK | GDK.GDK_POINTER_MOTION_HINT_MASK; + attrs.window_type = GDK.GDK_WINDOW_CHILD; + attrs.visual = gdkvisual; + glWindow = GDK.gdk_window_new (window, attrs, GDK.GDK_WA_VISUAL); + GDK.gdk_window_set_user_data (glWindow, handle); + if ((style & SWT.NO_BACKGROUND) != 0) { + //TODO: implement this on GTK3 as pixmaps are gone. + } + + if (GTK.GTK4) { + // TODO: Enable when the GdkWindow to GdkSurface changes are in + //xWindow = GDK.gdk_x11_surface_get_xid(glWindow); + } else { + xWindow = GDK.gdk_x11_window_get_xid (glWindow); + } + + GDK.gdk_window_show (glWindow); + //* + Listener listener = event -> { + switch (event.type) { + case SWT.Paint: + int [] viewport = new int [4]; + GLX.glGetIntegerv (GLX.GL_VIEWPORT, viewport); + GLX.glViewport (viewport [0],viewport [1],viewport [2],viewport [3]); + break; + case SWT.Resize: + Rectangle clientArea = DPIUtil.autoScaleUp(getClientArea()); + GDK.gdk_window_move (glWindow, clientArea.x, clientArea.y); + GDK.gdk_window_resize (glWindow, clientArea.width, clientArea.height); + break; + case SWT.Dispose: + onDispose(); + break; + } + }; + + addListener (SWT.Resize, listener); + addListener (SWT.Paint, listener); + addListener (SWT.Dispose, listener); + //*/ + } + + public boolean setCurrent(boolean set) { + return setCurrent(SWT.FOREGROUND, set); + } + + public boolean setCurrent(int pos, boolean set) { + long ctx = foreContext; + if (SWT.BACKGROUND == pos) { + //if (backContext == 0) ; //throw @error? + if (backContext != 0) + ctx = backContext; + } + return makeCurrent(ctx, set); + } + + private void releaseContext() { + long window1 = GTK.gtk_widget_get_window(handle); + long xDisplay1 = gdk_x11_display_get_xdisplay(window1); + if (backContext != 0) { + GLX.glXDestroyContext(xDisplay1, backContext); + backContext = 0; + } + if (foreContext != 0) { + if (GLX.glXGetCurrentContext() == foreContext) + GLX.glXMakeCurrent(xDisplay1, 0, 0); + GLX.glXDestroyContext(xDisplay1, foreContext); + foreContext = 0; + } + } + + public DirectContext getContext() { + if (context == null) { + setCurrent(SWT.FOREGROUND, true); + context = DirectContext.makeGL(); + } + return context; + } + + public Surface getSurface() { + checkWidget(); + if (context == null) { + setCurrent(SWT.FOREGROUND, true); + context = DirectContext.makeGL(); + } + if (surface == null) { + Rectangle rect = getClientArea(); + renderTarget = BackendRenderTarget.makeGL(rect.width, rect.height, 0, 8, 0, FramebufferFormat.GR_GL_RGBA8); + surface = Surface.makeFromBackendRenderTarget(context, renderTarget, SurfaceOrigin.BOTTOM_LEFT, SurfaceColorFormat.RGBA_8888, ColorSpace.getDisplayP3()); + } + return surface; + } + + public void swapBuffers() { + checkWidget(); + long window = GTK.gtk_widget_get_window(handle); + long xDisplay = gdk_x11_display_get_xdisplay(window); + GLX.glXSwapBuffers(xDisplay, xWindow); + } + + protected boolean makeCurrent(long context, boolean set) { + boolean rc = false; + if (context != 0) { + //synchronized (this) { + long curContext = GLX.glXGetCurrentContext(); + if (set) { + if (isDisposed()) SWT.error(SWT.ERROR_WIDGET_DISPOSED); + if (curContext == context) { + rc = true; + } else { + long window = GTK.gtk_widget_get_window(handle); + long xDisplay = gdk_x11_display_get_xdisplay(window); + GLX.glXMakeCurrent(xDisplay, xWindow, context); + } + } else if (curContext == context) { + long window = GTK.gtk_widget_get_window(handle); + long xDisplay = gdk_x11_display_get_xdisplay(window); + rc = GLX.glXMakeCurrent(xDisplay, 0, 0); + } + //} + } + return rc; + } + + void releaseSurface() { + if (surface != null) { + surface.close(); + surface = null; + } + if (renderTarget != null) { + renderTarget.close(); + renderTarget = null; + } + } + + private void releaseResource() { + if (context != null) { + context.close(); + context = null; + } + } + + protected void onResize() { + releaseSurface(); + } + + protected void onDispose() { + releaseResource(); + + releaseContext(); + } + + private long gdk_x11_display_get_xdisplay(long window) { + return GDK.gdk_x11_display_get_xdisplay(GDK.gdk_window_get_display(window)); + } +} diff --git a/draw2d/res/META-INF/native-image/native-image.properties b/draw2d/res/META-INF/native-image/native-image.properties new file mode 100644 index 0000000..cbc2ccf --- /dev/null +++ b/draw2d/res/META-INF/native-image/native-image.properties @@ -0,0 +1 @@ +Args=--verbose --no-server --no-fallback --allow-incomplete-classpath --report-unsupported-elements-at-runtime -H:+JNIVerboseLookupErrors -H:+ReportExceptionStackTraces diff --git a/draw2d/res/images/analytics-laptop-svgrepo-com.svg b/draw2d/res/images/analytics-laptop-svgrepo-com.svg new file mode 100644 index 0000000..582abe0 --- /dev/null +++ b/draw2d/res/images/analytics-laptop-svgrepo-com.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/res/images/folder-svgrepo-com.svg b/draw2d/res/images/folder-svgrepo-com.svg new file mode 100644 index 0000000..00d2718 --- /dev/null +++ b/draw2d/res/images/folder-svgrepo-com.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/res/images/gps-geolocalization-svgrepo-com.svg b/draw2d/res/images/gps-geolocalization-svgrepo-com.svg new file mode 100644 index 0000000..607bb7c --- /dev/null +++ b/draw2d/res/images/gps-geolocalization-svgrepo-com.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/res/images/internet-shield-svgrepo-com.svg b/draw2d/res/images/internet-shield-svgrepo-com.svg new file mode 100644 index 0000000..a9ac472 --- /dev/null +++ b/draw2d/res/images/internet-shield-svgrepo-com.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/res/images/internet-svgrepo-com.svg b/draw2d/res/images/internet-svgrepo-com.svg new file mode 100644 index 0000000..508ebe0 --- /dev/null +++ b/draw2d/res/images/internet-svgrepo-com.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/res/images/ipad-svgrepo-com.svg b/draw2d/res/images/ipad-svgrepo-com.svg new file mode 100644 index 0000000..5ddb2a5 --- /dev/null +++ b/draw2d/res/images/ipad-svgrepo-com.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/res/images/search-svgrepo-com.svg b/draw2d/res/images/search-svgrepo-com.svg new file mode 100644 index 0000000..d6af40c --- /dev/null +++ b/draw2d/res/images/search-svgrepo-com.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/res/images/settings-gear-svgrepo-com.svg b/draw2d/res/images/settings-gear-svgrepo-com.svg new file mode 100644 index 0000000..0bf21b4 --- /dev/null +++ b/draw2d/res/images/settings-gear-svgrepo-com.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/draw2d/run.sh b/draw2d/run.sh new file mode 100755 index 0000000..c104e57 --- /dev/null +++ b/draw2d/run.sh @@ -0,0 +1,33 @@ +#! /bin/sh + +if [ -z "$GRAALVM_HOME" ]; then + GRAALVM_HOME=$HOME/tools/graalvm +fi + +LIBS_3RD=../../third-party +SWT_HOME=$LIBS_3RD/swt +SKIJA_HOME=$LIBS_3RD/skija +RCP_HOME=$LIBS_3RD/rcp +GEF_HOME=$LIBS_3RD/gef +CP=$SWT_HOME/swt.jar:$SKIJA_HOME/skija.jar:\ +$RCP_HOME/plugins/org.eclipse.jface_3.22.0.v20201106-0834.jar:\ +$RCP_HOME/plugins/org.eclipse.core.commands_3.9.800.v20201021-1339.jar:\ +$RCP_HOME/plugins/org.eclipse.equinox.common_3.14.0.v20201102-2053.jar:\ +$RCP_HOME/plugins/org.eclipse.ui.workbench_3.122.0.v20201122-1345.jar:\ +$GEF_HOME/plugins/org.eclipse.draw2d_3.10.100.201606061308.jar:\ +$GEF_HOME/plugins/org.eclipse.gef_3.11.0.201606061308.jar:\ +$GEF_HOME/plugins/org.eclipse.zest.core_1.5.300.201606061308.jar:\ +$GEF_HOME/plugins/org.eclipse.zest.layouts_1.1.300.201606061308.jar + +for arg in "$@"; do + if [ "$arg" = "-trace" ]; then + rm -fr $HOME/.swt + JAVA_OPTS="$JAVA_OPTS -agentlib:native-image-agent=config-output-dir=res/META-INF/native-image" + elif [ "$arg" = "-debug" ]; then + JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000" + else + JAVA_OPTS="$JAVA_OPTS $arg" + fi +done + +$GRAALVM_HOME/bin/java $JAVA_OPTS -Djava.library.path=$SKIJA_HOME -cp bin:res:$CP com.spket.demo.draw2d.Draw2DApp diff --git a/draw2d/src/com/spket/demo/draw2d/Draw2DApp.java b/draw2d/src/com/spket/demo/draw2d/Draw2DApp.java new file mode 100644 index 0000000..41d0dbd --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/Draw2DApp.java @@ -0,0 +1,197 @@ +package com.spket.demo.draw2d; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.draw2d.Animation; +import org.eclipse.draw2d.FigureCanvas; +import org.eclipse.draw2d.FreeformLayout; +import org.eclipse.draw2d.IFigure; +import org.eclipse.draw2d.LayoutAnimator; +import org.eclipse.draw2d.geometry.Dimension; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.window.ApplicationWindow; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.zest.core.widgets.internal.ZestRootLayer; +import org.eclipse.zest.layouts.InvalidLayoutConfiguration; +import org.eclipse.zest.layouts.LayoutAlgorithm; +import org.eclipse.zest.layouts.LayoutEntity; +import org.eclipse.zest.layouts.LayoutRelationship; +import org.eclipse.zest.layouts.LayoutStyles; +import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm; +import org.jetbrains.skija.impl.Library; + +import com.spket.demo.draw2d.actions.ExitAction; +import com.spket.demo.draw2d.actions.LayoutAction; +import com.spket.demo.draw2d.actions.NewWizardAction; + +public class Draw2DApp extends ApplicationWindow { + public static void main(String[] args) { + loadLibrary(); + + Draw2DApp app = new Draw2DApp(); + + app.setBlockOnOpen(true); + + app.open(); + } + + private static void loadLibrary() { + System.loadLibrary("skija"); + System.setProperty("skija.staticLoad", String.valueOf(true)); + Library._loaded = true; + Library._nAfterLoad(); + } + + private FigureCanvasGL canvas; + private LayoutAlgorithm layoutAlgorithm; + private LayoutEntity[] nodes; + private LayoutRelationship[] connections; + private boolean hasPendingLayoutRequest; + + public Draw2DApp() { + super(null); + + createMenu(); + } + + @Override + protected void configureShell(Shell shell) { + super.configureShell(shell); + + shell.setText("Draw2D Demo"); + } + + @Override + protected Control createContents(Composite parent) { + canvas = new FigureCanvasGL(parent); + canvas.setScrollBarVisibility(FigureCanvas.NEVER); + + Images.load(); + + canvas.getViewport().setContents(createContent()); + + canvas.addListener(SWT.Resize, e -> applyLayout()); + + return canvas; + } + + @Override + protected Point getInitialSize() { + return new Point(800, 600); + } + + protected void createMenu() { + addMenuBar(); + + MenuManager menu = getMenuBarManager(); + + MenuManager file = new MenuManager("&File"); + createFileMenu(file); + + menu.add(file); + + MenuManager layout = new MenuManager("&Layout"); + LayoutAction.fill(this, layout); + + menu.add(layout); + } + + protected void createFileMenu(MenuManager menu) { + menu.add(new NewWizardAction(this)); + + menu.add(new Separator()); + + menu.add(new ExitAction(this)); + } + + + protected IFigure createContent() { + ZestRootLayer zestRootLayer = new ZestRootLayer(); + + zestRootLayer.setLayoutManager(new FreeformLayout()); + + zestRootLayer.addLayoutListener(LayoutAnimator.getDefault()); + + createNodes(zestRootLayer); + + return zestRootLayer; + } + + protected void createNodes(ZestRootLayer zest) { + SVGFigure analytics, internet, search, folder, gear, shield, gps, ipad; + List ents = new ArrayList<>(); + List conns = new ArrayList<>(); + ents.add(analytics = new SVGFigure(Images.getImage(Images.ANALYTICS_LAPTOP))); + ents.add(internet = new SVGFigure(Images.getImage(Images.INTERNET))); + ents.add(shield = new SVGFigure(Images.getImage(Images.INTERNET_SHIELD))); + ents.add(search = new SVGFigure(Images.getImage(Images.SEARCH))); + ents.add(folder = new SVGFigure(Images.getImage(Images.FOLDER))); + ents.add(gear = new SVGFigure(Images.getImage(Images.SETTINGS_GEAR))); + ents.add(gps = new SVGFigure(Images.getImage(Images.GPS))); + ents.add(ipad = new SVGFigure(Images.getImage(Images.IPAD))); + + conns.add(new SVGRelationship(search, analytics)); + conns.add(new SVGRelationship(search, folder)); + conns.add(new SVGRelationship(search, internet)); + conns.add(new SVGRelationship(internet, shield)); + conns.add(new SVGRelationship(internet, gear)); + conns.add(new SVGRelationship(gps, ipad)); + //conns.add(new SVGRelationship(internet, shield)); + conns.add(new SVGRelationship(search, gps)); + + ents.toArray(nodes = new LayoutEntity[ents.size()]); + conns.toArray(connections = new LayoutRelationship[conns.size()]); + + for (IFigure c : conns) + zest.addConnection(c); + for (IFigure e : ents) + zest.addNode(e); + } + + public void applyLayout() { + if (!hasPendingLayoutRequest) { + hasPendingLayoutRequest = true; + + canvas.redraw(); + + canvas.getDisplay().asyncExec(() -> doLayout()); + } + } + + public void applyLayout(LayoutAlgorithm algorithm) { + if (layoutAlgorithm != algorithm) { + layoutAlgorithm = algorithm; + + applyLayout(); + } + } + + protected void doLayout() { + hasPendingLayoutRequest = false; + if (canvas.isDisposed()) + return; + + int layoutStyle = LayoutStyles.NO_LAYOUT_NODE_RESIZING; + if (layoutAlgorithm == null) { + layoutAlgorithm = new TreeLayoutAlgorithm(layoutStyle); + } else { + layoutAlgorithm.setStyle(layoutAlgorithm.getStyle() | layoutStyle); + } + Dimension d = canvas.getViewport().getSize(); + + try { + Animation.markBegin(); + layoutAlgorithm.applyLayout(nodes, connections, 0, 0, d.width, d.height, false, false); + Animation.run(500); + //canvas.getLightweightSystem().getUpdateManager().performUpdate(); + } catch (InvalidLayoutConfiguration e) { + e.printStackTrace(); + } + } +} diff --git a/draw2d/src/com/spket/demo/draw2d/ISkiaFigure.java b/draw2d/src/com/spket/demo/draw2d/ISkiaFigure.java new file mode 100644 index 0000000..b439519 --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/ISkiaFigure.java @@ -0,0 +1,20 @@ +package com.spket.demo.draw2d; + +import org.jetbrains.skija.Canvas; + +public interface ISkiaFigure { + default void paint(Canvas canvas) { + int sp = canvas.save(); + try { + paintFigure(canvas); + paintClientArea(canvas); + paintBorder(canvas); + } finally { + canvas.restoreToCount(sp); + } + } + + void paintBorder(Canvas canvas); + void paintFigure(Canvas canvas); + void paintClientArea(Canvas canvas); +} diff --git a/draw2d/src/com/spket/demo/draw2d/Images.java b/draw2d/src/com/spket/demo/draw2d/Images.java new file mode 100644 index 0000000..8aab5c3 --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/Images.java @@ -0,0 +1,67 @@ +package com.spket.demo.draw2d; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +import org.jetbrains.skija.Data; +import org.jetbrains.skija.svg.DOM; + +public class Images { + public static final String ANALYTICS_LAPTOP = "analytics-laptop-svgrepo-com.svg"; + public static final String FOLDER = "folder-svgrepo-com.svg"; + public static final String GPS = "gps-geolocalization-svgrepo-com.svg"; + public static final String INTERNET_SHIELD = "internet-shield-svgrepo-com.svg"; + public static final String INTERNET = "internet-svgrepo-com.svg"; + public static final String IPAD = "ipad-svgrepo-com.svg"; + public static final String SEARCH = "search-svgrepo-com.svg"; + public static final String SETTINGS_GEAR = "settings-gear-svgrepo-com.svg"; + //public static final String STRATEGY = "strategy-svgrepo-com.svg"; + + private static Map images = new HashMap<>(); + + public static void load() { + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + load(ANALYTICS_LAPTOP, out); + load(FOLDER, out); + load(GPS, out); + load(INTERNET_SHIELD, out); + load(INTERNET, out); + load(IPAD, out); + load(SEARCH, out); + load(SETTINGS_GEAR, out); + //load(STRATEGY, out); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + private static void load(String name, ByteArrayOutputStream out) throws IOException { + DOM dom = null; + try (InputStream in = Images.class.getResourceAsStream("/images/" + name)) { + out.reset(); + in.transferTo(out); + try (Data data = Data.makeFromBytes(out.toByteArray())) { + dom = new DOM(data); + dom.setContainerSize(64, 64); + } + } + + if (dom != null) + images.put(name, dom); + } + + public static void dispose() { + for (DOM dom : images.values()) { + dom.close(); + } + images.clear(); + } + + public static DOM getImage(String name) { + return images.get(name); + } +} diff --git a/draw2d/src/com/spket/demo/draw2d/LightweightSystemGL.java b/draw2d/src/com/spket/demo/draw2d/LightweightSystemGL.java new file mode 100644 index 0000000..5072d69 --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/LightweightSystemGL.java @@ -0,0 +1,130 @@ +package com.spket.demo.draw2d; + +import org.eclipse.draw2d.Graphics; +import org.eclipse.draw2d.GraphicsSource; +import org.eclipse.draw2d.LightweightSystem; +import org.eclipse.draw2d.StackLayout; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.GC; +import org.jetbrains.skija.Canvas; +import org.jetbrains.skija.ColorAlphaType; +import org.jetbrains.skija.ImageInfo; +import org.jetbrains.skija.Surface; + +public class LightweightSystemGL extends LightweightSystem implements GraphicsSource { + private class RootFigureGL extends RootFigure { + private Rectangle clip = new Rectangle(); + + @Override + public void paint(Graphics graphics) { + if (graphics instanceof SkiaGraphics) { + super.paint(graphics); + } else { + graphics.getClip(clip); + + Graphics g = getGraphics(clip); + + super.paint(g); + + g.dispose(); + + flushGraphics(clip); + } + } + } + + private FigureCanvasGL glCanvas; + private Surface surface; + + @Override + public void setControl(org.eclipse.swt.widgets.Canvas c) { + if (c != glCanvas) { + if (c instanceof FigureCanvasGL) { + glCanvas = (FigureCanvasGL) c; + } else { + glCanvas = null; + } + super.setControl(c); + if (glCanvas != null) + getUpdateManager().setGraphicsSource(this); + } + } + + @Override + public void paint(GC gc) { + super.paint(gc); + + swapBuffer(); + } + + @Override + public Graphics getGraphics(Rectangle region) { + return new SkiaGraphics(getCanvas(), region); + } + + @Override + public void flushGraphics(Rectangle region) { + surface.flush(); + + swapBuffer(); + //glCanvas.redraw(region.x, region.y, region.width, region.height, false); + } + + @Override + protected RootFigure createRootFigure() { + RootFigure f = new RootFigureGL(); + f.addNotify(); + f.setOpaque(true); + f.setLayoutManager(new StackLayout()); + return f; + } + + @Override + protected void addListeners() { + super.addListeners(); + if (glCanvas != null) { + glCanvas.addListener(SWT.Dispose, e -> onDispose()); + } + } + + @Override + protected void controlResized() { + if (surface != null) { + surface.close(); + surface = null; + } + glCanvas.releaseSurface(); + + super.controlResized(); + } + + protected void onDispose() { + if (surface != null && glCanvas != null && !glCanvas.isDisposed()) { + surface.close(); + surface = null; + } + Images.dispose(); + } + + private void swapBuffer() { + Surface surf = glCanvas.getSurface(); + Canvas canvas = surf.getCanvas(); + if (surface != null) { + surface.draw(canvas, 0, 0, null); + } else { + canvas.clear(0xffffffff); + } + surf.flush(); + glCanvas.swapBuffers(); + } + + private Canvas getCanvas() { + if (surface == null) { + org.eclipse.swt.graphics.Rectangle r = glCanvas.getClientArea(); + ImageInfo info = ImageInfo.makeN32(r.width, r.height, ColorAlphaType.OPAQUE); + surface = Surface.makeRenderTarget(glCanvas.getContext(), false, info); + } + return surface.getCanvas(); + } +} diff --git a/draw2d/src/com/spket/demo/draw2d/SVGFigure.java b/draw2d/src/com/spket/demo/draw2d/SVGFigure.java new file mode 100644 index 0000000..5d9de59 --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/SVGFigure.java @@ -0,0 +1,117 @@ +package com.spket.demo.draw2d; + +import org.eclipse.draw2d.Figure; +import org.eclipse.draw2d.Graphics; +import org.eclipse.draw2d.geometry.Dimension; +import org.eclipse.draw2d.geometry.PrecisionDimension; +import org.eclipse.draw2d.geometry.PrecisionRectangle; +import org.eclipse.zest.layouts.LayoutEntity; +import org.eclipse.zest.layouts.constraints.LayoutConstraint; +import org.jetbrains.skija.Point; +import org.jetbrains.skija.svg.DOM; + +public class SVGFigure extends Figure implements LayoutEntity { + private static final Dimension DEFAULT_SIZE = new PrecisionDimension(64, 64); + + private DOM svg; + private Object layoutInfo; + + public SVGFigure() { + } + + public SVGFigure(DOM svg) { + this.svg = svg; + initSize(); + } + + protected void initSize() { + Dimension pSize = DEFAULT_SIZE; + //* + Point size = svg.getContainerSize(); + if (size != null) + pSize = new PrecisionDimension(size.getX(), size.getY()); + + //*/ + setPreferredSize(pSize); + setSize(pSize); + } + + @Override + protected void paintFigure(Graphics graphics) { + if (svg != null) { + if (graphics instanceof SkiaGraphics) { + org.eclipse.draw2d.geometry.Rectangle b = getBounds(); + ((SkiaGraphics) graphics).draw(svg, b.x, b.y); + } + } + } + + @Override + public void setGraphData(Object o) { + if (svg != o) { + if (o instanceof DOM) { + svg = (DOM) o; + } else { + svg = null; + } + initSize(); + } + } + + @Override + public Object getGraphData() { + return svg; + } + + @Override + public int compareTo(Object o) { + return 0; + } + + @Override + public void setLocationInLayout(double x, double y) { + getParent().setConstraint(this, new PrecisionRectangle(x, y, bounds.preciseWidth(), bounds.preciseHeight())); + //setLocation(new PrecisionPoint(x, y)); + } + + @Override + public void setSizeInLayout(double width, double height) { + } + + @Override + public double getXInLayout() { + return bounds.preciseX(); + } + + @Override + public double getYInLayout() { + return bounds.preciseY(); + } + + @Override + public double getWidthInLayout() { + return bounds.preciseWidth(); + } + + @Override + public double getHeightInLayout() { + return bounds.preciseHeight(); + } + + @Override + public Object getLayoutInformation() { + return layoutInfo; + } + + @Override + public void setLayoutInformation(Object internalEntity) { + layoutInfo = internalEntity; + } + + @Override + public void populateLayoutConstraint(LayoutConstraint constraint) { + // TODO Auto-generated method stub + + } + +} diff --git a/draw2d/src/com/spket/demo/draw2d/SVGRelationship.java b/draw2d/src/com/spket/demo/draw2d/SVGRelationship.java new file mode 100644 index 0000000..3939fa1 --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/SVGRelationship.java @@ -0,0 +1,59 @@ +package com.spket.demo.draw2d; + +import org.eclipse.draw2d.ChopboxAnchor; +import org.eclipse.zest.core.widgets.internal.PolylineArcConnection; +import org.eclipse.zest.layouts.LayoutBendPoint; +import org.eclipse.zest.layouts.LayoutEntity; +import org.eclipse.zest.layouts.LayoutRelationship; +import org.eclipse.zest.layouts.constraints.LayoutConstraint; + +public class SVGRelationship extends PolylineArcConnection implements LayoutRelationship { + private Object layoutInfo; + + public SVGRelationship(SVGFigure source, SVGFigure target) { + setSourceAnchor(new ChopboxAnchor(source)); + setTargetAnchor(new ChopboxAnchor(target)); + } + + @Override + public Object getGraphData() { + return null; + } + + @Override + public void setGraphData(Object o) { + } + + @Override + public LayoutEntity getSourceInLayout() { + return (LayoutEntity) getSourceAnchor().getOwner(); + } + + @Override + public LayoutEntity getDestinationInLayout() { + return (LayoutEntity) getTargetAnchor().getOwner(); + } + + @Override + public Object getLayoutInformation() { + return layoutInfo; + } + + @Override + public void setLayoutInformation(Object layoutInformation) { + layoutInfo = layoutInformation; + } + + @Override + public void setBendPoints(LayoutBendPoint[] bendPoints) { + } + + @Override + public void clearBendPoints() { + } + + @Override + public void populateLayoutConstraint(LayoutConstraint constraint) { + } + +} diff --git a/draw2d/src/com/spket/demo/draw2d/SkiaGraphics.java b/draw2d/src/com/spket/demo/draw2d/SkiaGraphics.java new file mode 100644 index 0000000..eeff310 --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/SkiaGraphics.java @@ -0,0 +1,551 @@ +package com.spket.demo.draw2d; + +import org.eclipse.draw2d.Graphics; +import org.eclipse.draw2d.geometry.PointList; +import org.eclipse.draw2d.geometry.Rectangle; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.LineAttributes; +import org.eclipse.swt.graphics.Path; +import org.eclipse.swt.graphics.Pattern; +import org.eclipse.swt.graphics.TextLayout; +import org.jetbrains.skija.Canvas; +import org.jetbrains.skija.Paint; +import org.jetbrains.skija.PaintMode; +import org.jetbrains.skija.Rect; +import org.jetbrains.skija.svg.DOM; + +public class SkiaGraphics extends Graphics { + private Canvas canvas; + private Paint cFill; + private Paint cStroke; + + private org.jetbrains.skija.Path path; + private Rectangle clip; + + private int savePoint; + + public SkiaGraphics(Canvas canvas, Rectangle region) { + this.canvas = canvas; + + savePoint = canvas.save(); + + clip = region; + cFill = new Paint(); + cFill.setMode(PaintMode.FILL).setColor(0xffffffff); + cStroke = new Paint(); + cStroke.setMode(PaintMode.STROKE); + path = new org.jetbrains.skija.Path(); + } + + public void draw(DOM dom, float x, float y) { + canvas.translate(x, y); + dom.render(canvas); + canvas.translate(-x, -y); + } + + @Override + public void clipRect(Rectangle r) { + //TODO + canvas.clipRect(Rect.makeXYWH(r.x, r.y, r.width, r.height), false); + } + + @Override + public void dispose() { + cFill.close(); + cStroke.close(); + path.close(); + + canvas.restoreToCount(savePoint); + } + + @Override + public void drawArc(int x, int y, int w, int h, int offset, int length) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawFocus(int x, int y, int w, int h) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawImage(Image srcImage, int x, int y) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawImage(Image srcImage, int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawLine(int x1, int y1, int x2, int y2) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawOval(int x, int y, int w, int h) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawPolygon(PointList points) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawPolyline(PointList points) { + int[] ps = points.toIntArray(); + float[] fps = new float[ps.length]; + + for (int i = 0; i < ps.length; i++) + fps[i] = ps[i]; + + path.addPoly(fps, false); + + canvas.drawPath(path, cStroke); + } + + @Override + public void drawRectangle(int x, int y, int width, int height) { + canvas.drawRect(Rect.makeXYWH(x, y, width, height), cStroke); + } + + @Override + public void drawRoundRectangle(Rectangle r, int arcWidth, int arcHeight) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawString(String s, int x, int y) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawText(String s, int x, int y) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillArc(int x, int y, int w, int h, int offset, int length) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillGradient(int x, int y, int w, int h, boolean vertical) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillOval(int x, int y, int w, int h) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillPolygon(PointList points) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillRectangle(int x, int y, int width, int height) { + canvas.drawRect(Rect.makeXYWH(x, y, width, height), cFill); + } + + @Override + public void fillRoundRectangle(Rectangle r, int arcWidth, int arcHeight) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillString(String s, int x, int y) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillText(String s, int x, int y) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public Color getBackgroundColor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Rectangle getClip(Rectangle rect) { + rect.setBounds(clip); + + return rect; + } + + @Override + public Font getFont() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public FontMetrics getFontMetrics() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public Color getForegroundColor() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public int getLineStyle() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int getLineWidth() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public float getLineWidthFloat() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean getXORMode() { + return false; + } + + @Override + public void popState() { + canvas.restore(); + } + + @Override + public void pushState() { + canvas.save(); + } + + @Override + public void restoreState() { + canvas.restore(); + canvas.save(); + } + + @Override + public void scale(double amount) { + float s = (float) amount; + + canvas.scale(s, s); + } + + @Override + public void setBackgroundColor(Color rgb) { + cFill.setARGB(rgb.getAlpha(), rgb.getRed(), rgb.getGreen(), rgb.getBlue()); + } + + @Override + public void setClip(Rectangle r) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setFont(Font f) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setForegroundColor(Color rgb) { + cStroke.setARGB(rgb.getAlpha(), rgb.getRed(), rgb.getGreen(), rgb.getBlue()); + } + + @Override + public void setLineStyle(int style) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setLineWidth(int width) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setLineWidthFloat(float width) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setLineMiterLimit(float miterLimit) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setXORMode(boolean b) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void translate(int dx, int dy) { + canvas.translate(dx, dy); + } + + @Override + public void clipPath(Path path) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawPath(Path path) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawPoint(int x, int y) { + canvas.drawPoint(x, y, cStroke); + } + + @Override + public void drawPolygon(int[] points) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawPolyline(int[] points) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawText(String s, int x, int y, int style) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void drawTextLayout(TextLayout layout, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillPath(Path path) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void fillPolygon(int[] points) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public double getAbsoluteScale() { + // TODO Auto-generated method stub + return 1.0; + } + + @Override + public boolean getAdvanced() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public int getAlpha() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public int getAntialias() { + return SWT.ON; + } + + @Override + public int getFillRule() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public int getInterpolation() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public LineAttributes getLineAttributes() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public int getLineCap() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public int getLineJoin() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public float getLineMiterLimit() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public int getTextAntialias() { + // TODO Auto-generated method stub + return SWT.ON; + } + + @Override + public void rotate(float degrees) { + canvas.rotate(degrees); + } + + @Override + public void scale(float horizontal, float vertical) { + canvas.scale(horizontal, vertical); + } + + @Override + public void setAlpha(int alpha) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setAdvanced(boolean advanced) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setAntialias(int value) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setBackgroundPattern(Pattern pattern) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setClip(Path path) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setFillRule(int rule) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setForegroundPattern(Pattern pattern) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setInterpolation(int interpolation) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException(); + } + + @Override + public void setLineAttributes(LineAttributes attributes) { + // TODO Auto-generated method stub + //super.setLineAttributes(attributes); + } + + @Override + public void setLineCap(int cap) { + // TODO Auto-generated method stub + //super.setLineCap(cap); + } + + @Override + public void setLineDash(int[] dash) { + // TODO Auto-generated method stub + //super.setLineDash(dash); + } + + @Override + public void setLineDash(float[] value) { + // TODO Auto-generated method stub + //super.setLineDash(value); + } + + @Override + public void setLineDashOffset(float value) { + // TODO Auto-generated method stub + //super.setLineDashOffset(value); + } + + @Override + public void setLineJoin(int join) { + // TODO Auto-generated method stub + //super.setLineJoin(join); + } + + @Override + public void setTextAntialias(int value) { + // TODO Auto-generated method stub + //super.setTextAntialias(value); + } + + @Override + public void shear(float horz, float vert) { + //canvas. + } + + @Override + public void translate(float dx, float dy) { + canvas.translate(dx, dy); + } +} diff --git a/draw2d/src/com/spket/demo/draw2d/actions/ExitAction.java b/draw2d/src/com/spket/demo/draw2d/actions/ExitAction.java new file mode 100644 index 0000000..01573be --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/actions/ExitAction.java @@ -0,0 +1,19 @@ +package com.spket.demo.draw2d.actions; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.window.ApplicationWindow; + +public class ExitAction extends Action { + private ApplicationWindow window; + + public ExitAction(ApplicationWindow window) { + super("&Exit"); + + this.window = window; + } + + @Override + public void run() { + window.close(); + } +} diff --git a/draw2d/src/com/spket/demo/draw2d/actions/LayoutAction.java b/draw2d/src/com/spket/demo/draw2d/actions/LayoutAction.java new file mode 100644 index 0000000..e4f6059 --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/actions/LayoutAction.java @@ -0,0 +1,53 @@ +package com.spket.demo.draw2d.actions; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IContributionManager; +import org.eclipse.zest.layouts.LayoutAlgorithm; +import org.eclipse.zest.layouts.LayoutStyles; +import org.eclipse.zest.layouts.algorithms.GridLayoutAlgorithm; +import org.eclipse.zest.layouts.algorithms.HorizontalLayoutAlgorithm; +import org.eclipse.zest.layouts.algorithms.HorizontalTreeLayoutAlgorithm; +import org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm; +import org.eclipse.zest.layouts.algorithms.SpringLayoutAlgorithm; +import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm; +import org.eclipse.zest.layouts.algorithms.VerticalLayoutAlgorithm; + +import com.spket.demo.draw2d.Draw2DApp; + +public final class LayoutAction extends Action { + private static final String[] algorithmNames = { "Spring", "Tree - V", "Tree - H", "Radial", "Grid", "Horizontal", "Vertical" }; + private static final LayoutAlgorithm[] algorithms = { + new SpringLayoutAlgorithm(LayoutStyles.NONE), + new TreeLayoutAlgorithm(LayoutStyles.NONE), + new HorizontalTreeLayoutAlgorithm(LayoutStyles.NONE), + new RadialLayoutAlgorithm(LayoutStyles.NONE), + new GridLayoutAlgorithm(LayoutStyles.NONE), + new HorizontalLayoutAlgorithm(LayoutStyles.NONE), + new VerticalLayoutAlgorithm(LayoutStyles.NONE) + }; + + public static void fill(Draw2DApp application, IContributionManager manager) { + for (int i = 0, length = algorithmNames.length; i < length; i++) { + LayoutAction action = new LayoutAction(application, algorithmNames[i], algorithms[i]); + if (i == 1) + action.setChecked(true); + manager.add(action); + } + } + + private Draw2DApp application; + private LayoutAlgorithm algorithm; + + private LayoutAction(Draw2DApp application, String name, LayoutAlgorithm algorithm) { + super(name, IAction.AS_RADIO_BUTTON); + + this.application = application; + this.algorithm = algorithm; + } + + @Override + public void run() { + application.applyLayout(algorithm); + } +} diff --git a/draw2d/src/com/spket/demo/draw2d/actions/NewWizardAction.java b/draw2d/src/com/spket/demo/draw2d/actions/NewWizardAction.java new file mode 100644 index 0000000..9e5e68f --- /dev/null +++ b/draw2d/src/com/spket/demo/draw2d/actions/NewWizardAction.java @@ -0,0 +1,22 @@ +package com.spket.demo.draw2d.actions; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.swt.widgets.Shell; + +public class NewWizardAction extends Action { + private IShellProvider shellProvider; + + public NewWizardAction(IShellProvider shellProvider) { + super("&New..."); + this.shellProvider = shellProvider; + } + + @Override + public void run() { + Shell shell = shellProvider.getShell(); + if (shell != null) { + //TODO + } + } +} diff --git a/draw2d/win32/com/spket/demo/draw2d/FigureCanvasGL.java b/draw2d/win32/com/spket/demo/draw2d/FigureCanvasGL.java new file mode 100644 index 0000000..77acb93 --- /dev/null +++ b/draw2d/win32/com/spket/demo/draw2d/FigureCanvasGL.java @@ -0,0 +1,234 @@ +package com.spket.demo.draw2d; + +import org.eclipse.draw2d.FigureCanvas; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.internal.opengl.win32.PIXELFORMATDESCRIPTOR; +import org.eclipse.swt.internal.opengl.win32.WGL; +import org.eclipse.swt.internal.win32.OS; +import org.eclipse.swt.opengl.GLData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.jetbrains.skija.BackendRenderTarget; +import org.jetbrains.skija.ColorSpace; +import org.jetbrains.skija.DirectContext; +import org.jetbrains.skija.FramebufferFormat; +import org.jetbrains.skija.Surface; +import org.jetbrains.skija.SurfaceColorFormat; +import org.jetbrains.skija.SurfaceOrigin; + +public class FigureCanvasGL extends FigureCanvas { + private static final String USE_OWNDC_KEY = "org.eclipse.swt.internal.win32.useOwnDC"; //$NON-NLS-1$ + + private static int checkStyle(Composite parent, int style) { + parent.getDisplay().setData(USE_OWNDC_KEY, Boolean.TRUE); + + style |= SWT.V_SCROLL | SWT.H_SCROLL; + + return style; + } + + private static GLData createDefaultData() { + GLData data = new GLData(); + data.doubleBuffer = true; + data.stencilSize = 8; + return data; + } + + int foreContext; + int backContext; + + private Surface surface; + private DirectContext context; + private BackendRenderTarget renderTarget; + + public FigureCanvasGL(Composite parent) { + this(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND, createDefaultData()); + } + + public FigureCanvasGL(Composite parent, int style) { + this(parent, style, createDefaultData()); + } + + public FigureCanvasGL(Composite parent, int style, GLData data) { + super(checkStyle(parent, style), parent, new LightweightSystemGL()); + + Display display = parent.getDisplay(); + + display.setData(USE_OWNDC_KEY, Boolean.FALSE); + + initGL(parent.getDisplay(), data, (style & SWT.MULTI) != 0); + + //getLightweightSystem().setUpdateManager(new DeferredUpdateManagerGL()); + + addListener(SWT.Dispose, e -> onDispose()); + } + + protected void initGL(Display display, GLData data, boolean createBackContext) { + display.setData(USE_OWNDC_KEY, Boolean.FALSE); + if (data == null) + SWT.error(SWT.ERROR_NULL_ARGUMENT); + PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR(); + pfd.nSize = (short) PIXELFORMATDESCRIPTOR.sizeof; + pfd.nVersion = 1; + pfd.dwFlags = WGL.PFD_DRAW_TO_WINDOW | WGL.PFD_SUPPORT_OPENGL; + pfd.dwLayerMask = WGL.PFD_MAIN_PLANE; + pfd.iPixelType = (byte) WGL.PFD_TYPE_RGBA; + if (data.doubleBuffer) pfd.dwFlags |= WGL.PFD_DOUBLEBUFFER; + if (data.stereo) pfd.dwFlags |= WGL.PFD_STEREO; + pfd.cRedBits = (byte) data.redSize; + pfd.cGreenBits = (byte) data.greenSize; + pfd.cBlueBits = (byte) data.blueSize; + pfd.cAlphaBits = (byte) data.alphaSize; + pfd.cDepthBits = (byte) data.depthSize; + pfd.cStencilBits = (byte) data.stencilSize; + pfd.cAccumRedBits = (byte) data.accumRedSize; + pfd.cAccumGreenBits = (byte) data.accumGreenSize; + pfd.cAccumBlueBits = (byte) data.accumBlueSize; + pfd.cAccumAlphaBits = (byte) data.accumAlphaSize; + pfd.cAccumBits = (byte) (pfd.cAccumRedBits + pfd.cAccumGreenBits + pfd.cAccumBlueBits + pfd.cAccumAlphaBits); + + int hDC = OS.GetDC(handle); + int pixelFormat = WGL.ChoosePixelFormat(hDC, pfd); + if (pixelFormat == 0 || !WGL.SetPixelFormat(hDC, pixelFormat, pfd)) { + OS.ReleaseDC(handle, hDC); + dispose(); + SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH); + } + foreContext = WGL.wglCreateContext(hDC); + if (foreContext == 0) { + OS.ReleaseDC(handle, hDC); + SWT.error(SWT.ERROR_NO_HANDLES); + } else if (createBackContext) { + backContext = WGL.wglCreateContext(hDC); + if (backContext != 0) { + boolean rc = WGL.wglShareLists(foreContext, backContext); + if (!rc ) { + WGL.wglDeleteContext(backContext); + backContext = 0; + } + } + } + OS.ReleaseDC(handle, hDC); + } + + public boolean setCurrent(boolean set) { + return setCurrent(SWT.FOREGROUND, set); + } + + public boolean setCurrent(int pos, boolean set) { + int ctx = foreContext; + if (SWT.BACKGROUND == pos) { + //if (backContext == 0) ; //throw @error? + if (backContext != 0) + ctx = backContext; + } + return makeCurrent(ctx, set); + } + + public void releaseContext() { + if (backContext != 0) { + if (WGL.wglDeleteContext(backContext)) + backContext = 0; + } + if (foreContext != 0) { + if (WGL.wglGetCurrentContext() == foreContext) + WGL.wglMakeCurrent(0, 0); + if (WGL.wglDeleteContext(foreContext)) + foreContext = 0; + } + } + + public DirectContext getContext() { + if (context == null) { + setCurrent(SWT.FOREGROUND, true); + context = DirectContext.makeGL(); + } + return context; + } + + public Surface getSurface() { + checkWidget(); + if (context == null) { + setCurrent(SWT.FOREGROUND, true); + context = DirectContext.makeGL(); + } + if (surface == null) { + Rectangle rect = getClientArea(); + renderTarget = BackendRenderTarget.makeGL(rect.width, rect.height, 0, 8, 0, FramebufferFormat.GR_GL_RGBA8); + surface = Surface.makeFromBackendRenderTarget(context, renderTarget, SurfaceOrigin.BOTTOM_LEFT, SurfaceColorFormat.RGBA_8888, ColorSpace.getDisplayP3()); + } + return surface; + } + /* + public Canvas getCanvas() { + checkWidget(); + if (context == null) { + setCurrent(SWT.FOREGROUND, true); + context = DirectContext.makeGL(); + } + if (surface == null) { + Rectangle rect = getClientArea(); + renderTarget = BackendRenderTarget.makeGL(rect.width, rect.height, 0, 8, 0, FramebufferFormat.GR_GL_RGBA8); + surface = Surface.makeFromBackendRenderTarget(context, renderTarget, SurfaceOrigin.BOTTOM_LEFT, SurfaceColorFormat.RGBA_8888, ColorSpace.getDisplayP3()); + } + return surface.getCanvas(); + } + //*/ + public void swapBuffers() { + checkWidget(); + int hDC = OS.GetDC(handle); + WGL.SwapBuffers(hDC); + OS.ReleaseDC(handle, hDC); + } + + protected boolean makeCurrent(int context, boolean set) { + boolean rc = false; + if (context != 0) { + //synchronized (this) { + int curContext = WGL.wglGetCurrentContext(); + if (set) { + if (isDisposed()) SWT.error(SWT.ERROR_WIDGET_DISPOSED); + if (curContext == context) { + rc = true; + } else { + int hDC = OS.GetDC(handle); + rc = WGL.wglMakeCurrent(hDC, context); + OS.ReleaseDC(handle, hDC); + } + } else if (curContext == context) { + rc = WGL.wglMakeCurrent(0, 0); + } + //} + } + return rc; + } + + void releaseSurface() { + if (surface != null) { + surface.close(); + surface = null; + } + if (renderTarget != null) { + renderTarget.close(); + renderTarget = null; + } + } + + private void releaseResource() { + if (context != null) { + context.close(); + context = null; + } + } + + protected void onResize() { + releaseSurface(); + } + + protected void onDispose() { + releaseResource(); + + releaseContext(); + } +}