Ver código fonte

Merge remote-tracking branch 'Stan/development' into development

kindlich 6 anos atrás
pai
commit
a9f5d30209
Nenhuma chave conhecida encontrada para esta assinatura no banco de dados
100 arquivos alterados com 6331 adições e 0 exclusões
  1. 33
    0
      Constructor/libraries/stdlib/src/Arrays.zs
  2. 34
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/Library.java
  3. 4
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/Main.java
  4. 12
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/Project.java
  5. 23
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java
  6. 2
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/ModuleReference.java
  7. 22
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourceFile.java
  8. 31
    0
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourcePackage.java
  9. 24
    0
      DrawableGui/build.gradle
  10. 89
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/BaseComponentGroup.java
  11. 67
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DCanvas.java
  12. 16
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DClipboard.java
  13. 21
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIcon.java
  14. 59
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DComponent.java
  15. 39
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DDimensionPreferences.java
  16. 18
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DDrawable.java
  17. 53
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DEmptyView.java
  18. 70
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DFont.java
  19. 15
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DFontFamily.java
  20. 22
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DFontMetrics.java
  21. 31
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DIRectangle.java
  22. 211
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DKeyEvent.java
  23. 51
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DMouseEvent.java
  24. 75
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DPath.java
  25. 70
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DPathBoundsCalculator.java
  26. 14
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DPathCommand.java
  27. 22
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DPathTracer.java
  28. 14
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DPreparedPath.java
  29. 261
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DSideLayout.java
  30. 17
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DTimerHandle.java
  31. 70
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DTransform2D.java
  32. 50
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DUIContext.java
  33. 35
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DUIWindow.java
  34. 25
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DBorder.java
  35. 184
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java
  36. 35
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorderStyle.java
  37. 43
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java
  38. 56
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java
  39. 28
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/listeners/DummyListenerHandle.java
  40. 27
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/listeners/ListenerHandle.java
  41. 165
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/listeners/ListenerList.java
  42. 39
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveBool.java
  43. 36
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveObject.java
  44. 80
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveArrayList.java
  45. 28
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveBool.java
  46. 155
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveConcatList.java
  47. 73
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveEmptyList.java
  48. 24
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveInt.java
  49. 44
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveList.java
  50. 111
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveMappedList.java
  51. 24
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveObject.java
  52. 64
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePredicateBool.java
  53. 124
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePrefixedList.java
  54. 46
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveBool.java
  55. 35
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveInt.java
  56. 39
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveObject.java
  57. 173
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java
  58. 31
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBarStyle.java
  59. 320
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java
  60. 23
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPaneStyle.java
  61. 20
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DDimension.java
  62. 25
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DDpDimension.java
  63. 53
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStyleDefinition.java
  64. 21
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStylesheets.java
  65. 25
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DPxDimension.java
  66. 26
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DShadow.java
  67. 27
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleClass.java
  68. 29
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleDefinition.java
  69. 14
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePath.java
  70. 38
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePathRoot.java
  71. 16
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleSheets.java
  72. 46
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/JavaClipboard.java
  73. 209
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingCanvas.java
  74. 49
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingFontMetrics.java
  75. 172
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingGraphicsContext.java
  76. 553
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingRoot.java
  77. 145
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingWindow.java
  78. 35
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/CollapsedArrow.java
  79. 39
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/ColoredCollapsedArrow.java
  80. 29
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeNode.java
  81. 237
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeView.java
  82. 91
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeViewStyle.java
  83. 35
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedArrow.java
  84. 39
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedColoredArrow.java
  85. 24
    0
      DrawableGuiIconConverter/build.gradle
  86. 323
    0
      DrawableGuiIconConverter/src/main/java/org/openzen/drawablegui/iconconverter/Main.java
  87. 19
    0
      IDE/build.gradle
  88. 35
    0
      IDE/src/main/java/org/openzen/zenscript/ide/Main.java
  89. 20
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/DevelopmentHost.java
  90. 18
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/IDELibrary.java
  91. 16
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/IDEModule.java
  92. 20
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/IDEPackage.java
  93. 21
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/IDESourceFile.java
  94. 39
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalLibrary.java
  95. 32
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalModule.java
  96. 57
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalPackage.java
  97. 53
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalProjectDevelopmentHost.java
  98. 54
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalSourceFile.java
  99. 20
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectBar.java
  100. 0
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectBarControl.java

+ 33
- 0
Constructor/libraries/stdlib/src/Arrays.zs Ver arquivo

@@ -19,6 +19,7 @@ export expand <T> T[] {
19 19
 	
20 20
 	public get first as T?;
21 21
 	public get last as T?;
22
+	public get reversed as T[];
22 23
 	
23 24
 	public map<U>(projection as function(value as T) as U) as U[] {
24 25
 		val result as U[] = new U[](this.length);
@@ -79,6 +80,38 @@ export expand <T> T[] {
79 80
 		return true;
80 81
 	}
81 82
 	
83
+	public first(predicate as function(value as T) as bool) as T? {
84
+		for value in this
85
+			if predicate(value)
86
+				return value;
87
+		
88
+		return null;
89
+	}
90
+	
91
+	public first(predicate as function(i as int, value as T) as bool) as T? {
92
+		for i, value in this
93
+			if predicate(i, value)
94
+				return value;
95
+		
96
+		return null;
97
+	}
98
+	
99
+	public last(predicate as function(value as T) as bool) as T? {
100
+		for i, value in this.reversed
101
+			if predicate(value)
102
+				return value;
103
+		
104
+		return null;
105
+	}
106
+	
107
+	public last(predicate as function(value as T) as bool) as T? {
108
+		for i, value in this.reversed
109
+			if predicate(value)
110
+				return value
111
+		
112
+		return null;
113
+	}
114
+	
82 115
 	public count(predicate as function(value as T) as bool) as int {
83 116
 		var result = 0;
84 117
 		for value in this

+ 34
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/Library.java Ver arquivo

@@ -0,0 +1,34 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.constructor;
7
+
8
+import java.io.File;
9
+import org.json.JSONArray;
10
+import org.json.JSONObject;
11
+import org.openzen.zenscript.constructor.module.DirectoryModuleLoader;
12
+import org.openzen.zenscript.constructor.module.ModuleReference;
13
+
14
+/**
15
+ *
16
+ * @author Hoofdgebruiker
17
+ */
18
+public class Library {
19
+	public final String name;
20
+	public final File directory;
21
+	public final ModuleReference[] modules;
22
+	
23
+	public Library(ModuleLoader loader, File directory, String name, JSONObject json) {
24
+		this.name = name;
25
+		this.directory = new File(directory, json.getString("directory"));
26
+		
27
+		JSONArray modulesJson = json.getJSONArray("modules");
28
+		modules = new ModuleReference[modulesJson.length()];
29
+		for (int i = 0; i < modulesJson.length(); i++) {
30
+			String moduleName = modulesJson.getString(i);
31
+			modules[i] = new DirectoryModuleLoader(loader, moduleName, new File(this.directory, moduleName), false);
32
+		}
33
+	}
34
+}

+ 4
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/Main.java Ver arquivo

@@ -22,6 +22,10 @@ public class Main {
22 22
 		moduleLoader.register("stdlib", new DirectoryModuleLoader(moduleLoader, "stdlib", new File("libraries/stdlib"), true));
23 23
 		
24 24
 		Project project = new Project(moduleLoader, currentDirectory);
25
+		for (Library library : project.libraries) {
26
+			for (ModuleReference module : library.modules)
27
+				moduleLoader.register(module.getName(), module);
28
+		}
25 29
 		for (ModuleReference module : project.modules) {
26 30
 			moduleLoader.register(module.getName(), module);
27 31
 		}

+ 12
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/Project.java Ver arquivo

@@ -17,9 +17,13 @@ import org.openzen.zenscript.constructor.module.ModuleReference;
17 17
  * @author Hoofdgebruiker
18 18
  */
19 19
 public class Project {
20
+	public final String name;
20 21
 	public final ModuleReference[] modules;
22
+	public final Library[] libraries;
21 23
 	
22 24
 	public Project(ModuleLoader loader, File directory) throws IOException {
25
+		name = directory.getName();
26
+		
23 27
 		if (!directory.exists())
24 28
 			throw new ConstructorException("Project directory doesn't exist");
25 29
 		if (!directory.isDirectory())
@@ -31,6 +35,14 @@ public class Project {
31 35
 		
32 36
 		JSONObject json = JSONUtils.load(projectFile);
33 37
 		
38
+		JSONObject jsonLibraries = json.getJSONObject("libraries");
39
+		libraries = new Library[jsonLibraries.length()];
40
+		int k = 0;
41
+		for (String key : jsonLibraries.keySet()) {
42
+			libraries[k] = new Library(loader, directory, key, jsonLibraries.getJSONObject(key));
43
+			k++;
44
+		}
45
+		
34 46
 		JSONArray jsonModules = json.getJSONArray("modules");
35 47
 		modules = new ModuleReference[jsonModules.length()];
36 48
 		for (int i = 0; i < jsonModules.length(); i++) {

+ 23
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java Ver arquivo

@@ -28,6 +28,7 @@ public class DirectoryModuleLoader implements ModuleReference {
28 28
 	private final String moduleName;
29 29
 	private final File directory;
30 30
 	private final boolean isStdlib;
31
+	private SourcePackage rootPackage = null;
31 32
 	
32 33
 	public DirectoryModuleLoader(ModuleLoader loader, String moduleName, File directory, boolean isStdlib) {
33 34
 		this.loader = loader;
@@ -93,4 +94,26 @@ public class DirectoryModuleLoader implements ModuleReference {
93 94
 			throw new ConstructorException("Loading module files failed: " + ex.getMessage(), ex);
94 95
 		}
95 96
 	}
97
+	
98
+	@Override
99
+	public SourcePackage getRootPackage() {
100
+		if (rootPackage == null)
101
+			rootPackage = loadPackage("", new File(directory, "src"));
102
+		
103
+		return rootPackage;
104
+	}
105
+	
106
+	private SourcePackage loadPackage(String name, File directory) {
107
+		SourcePackage pkg = new SourcePackage(name);
108
+		
109
+		for (File file : directory.listFiles()) {
110
+			if (file.isDirectory()) {
111
+				pkg.addPackage(loadPackage(file.getName(), file));
112
+			} else if (file.isFile() && file.getName().toLowerCase().endsWith(".zs")) {
113
+				pkg.addFile(new SourceFile(file.getName(), file));
114
+			}
115
+		}
116
+		
117
+		return pkg;
118
+	}
96 119
 }

+ 2
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/ModuleReference.java Ver arquivo

@@ -13,4 +13,6 @@ public interface ModuleReference {
13 13
 	public String getName();
14 14
 	
15 15
 	public SemanticModule load();
16
+	
17
+	public SourcePackage getRootPackage();
16 18
 }

+ 22
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourceFile.java Ver arquivo

@@ -0,0 +1,22 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.constructor.module;
7
+
8
+import java.io.File;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class SourceFile {
15
+	public final String name;
16
+	public final File file;
17
+	
18
+	public SourceFile(String name, File file) {
19
+		this.name = name;
20
+		this.file = file;
21
+	}
22
+}

+ 31
- 0
Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourcePackage.java Ver arquivo

@@ -0,0 +1,31 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.constructor.module;
7
+
8
+import java.util.HashMap;
9
+import java.util.Map;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class SourcePackage {
16
+	public final String name;
17
+	public final Map<String, SourcePackage> subPackages = new HashMap<>();
18
+	public final Map<String, SourceFile> sourceFiles = new HashMap<>();
19
+	
20
+	public SourcePackage(String name) {
21
+		this.name = name;
22
+	}
23
+	
24
+	public void addPackage(SourcePackage pkg) {
25
+		subPackages.put(pkg.name, pkg);
26
+	}
27
+	
28
+	public void addFile(SourceFile file) {
29
+		sourceFiles.put(file.name, file);
30
+	}
31
+}

+ 24
- 0
DrawableGui/build.gradle Ver arquivo

@@ -0,0 +1,24 @@
1
+// Note: "common.gradle" in the root project contains additional initialization
2
+//   for this project. This initialization is applied in the "build.gradle"
3
+//   of the root project.
4
+
5
+// NetBeans will automatically add "run" and "debug" tasks relying on the
6
+// "mainClass" property. You may however define the property prior executing
7
+// tasks by passing a "-PmainClass=<QUALIFIED_CLASS_NAME>" argument.
8
+//
9
+// Note however, that you may define your own "run" and "debug" task if you
10
+// prefer. In this case NetBeans will not add these tasks but you may rely on
11
+// your own implementation.
12
+if (!hasProperty('mainClass')) {
13
+    ext.mainClass = ''
14
+}
15
+
16
+dependencies {
17
+    // TODO: Add dependencies here
18
+    //   but note that JUnit should have already been added in parent.gradle.
19
+    //   By default, only the Maven Central Repository is specified in
20
+    //   parent.gradle.
21
+    //
22
+    // You can read more about how to add dependency here:
23
+    //   http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
24
+}

+ 89
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/BaseComponentGroup.java Ver arquivo

@@ -0,0 +1,89 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import java.util.function.Consumer;
9
+import java.util.function.Predicate;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public abstract class BaseComponentGroup implements DComponent {
16
+	private DComponent hovering = null;
17
+	
18
+	protected abstract void forEachChild(Consumer<DComponent> children);
19
+	
20
+	protected abstract DComponent findChild(Predicate<DComponent> predicate);
21
+	
22
+	@Override
23
+	public void onMouseEnter(DMouseEvent e) {
24
+		DComponent target = getComponent(e.x, e.y);
25
+		setHovering(target, e);
26
+	}
27
+	
28
+	@Override
29
+	public void onMouseExit(DMouseEvent e) {
30
+		setHovering(null, e);
31
+	}
32
+	
33
+	@Override
34
+	public void onMouseMove(DMouseEvent e) {
35
+		DComponent target = getComponent(e.x, e.y);
36
+		if (target == hovering) {
37
+			if (target != null)
38
+				target.onMouseMove(e);
39
+		} else {
40
+			setHovering(target, e);
41
+		}
42
+	}
43
+	
44
+	@Override
45
+	public void onMouseDrag(DMouseEvent e) {
46
+		if (hovering != null)
47
+			hovering.onMouseDrag(e);
48
+	}
49
+	
50
+	@Override
51
+	public void onMouseClick(DMouseEvent e) {
52
+		if (hovering != null)
53
+			hovering.onMouseClick(e);
54
+	}
55
+	
56
+	@Override
57
+	public void onMouseDown(DMouseEvent e) {
58
+		if (hovering != null)
59
+			hovering.onMouseDown(e);
60
+	}
61
+	
62
+	@Override
63
+	public void onMouseRelease(DMouseEvent e) {
64
+		if (hovering != null)
65
+			hovering.onMouseRelease(e);
66
+		onMouseMove(e);
67
+	}
68
+	
69
+	@Override
70
+	public void onMouseScroll(DMouseEvent e) {
71
+		if (hovering != null)
72
+			hovering.onMouseScroll(e);
73
+	}
74
+	
75
+	private void setHovering(DComponent component, DMouseEvent e) {
76
+		if (component == hovering)
77
+			return;
78
+		
79
+		if (hovering != null)
80
+			hovering.onMouseExit(e);
81
+		hovering = component;
82
+		if (hovering != null)
83
+			hovering.onMouseEnter(e);
84
+	}
85
+	
86
+	private DComponent getComponent(int x, int y) {
87
+		return findChild(child -> child.getBounds().contains(x, y));
88
+	}
89
+}

+ 67
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DCanvas.java Ver arquivo

@@ -0,0 +1,67 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import org.openzen.drawablegui.style.DShadow;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface DCanvas {
15
+	void pushBounds(DIRectangle bounds);
16
+	
17
+	void popBounds();
18
+	
19
+	void pushOffset(int x, int y);
20
+	
21
+	void popOffset();
22
+	
23
+	DIRectangle getBounds();
24
+	
25
+	DUIContext getContext();
26
+	
27
+	void drawText(DFont font, int color, float x, float y, String text);
28
+	
29
+	/**
30
+	 * Strokes a given path.
31
+	 * 
32
+	 * @param path path to be stroked
33
+	 * @param transform path transform
34
+	 * @param color path color
35
+	 * @param lineWidth path line width
36
+	 */
37
+	void strokePath(DPath path, DTransform2D transform, int color, float lineWidth);
38
+	
39
+	/**
40
+	 * Fills a given path.
41
+	 * 
42
+	 * @param path path to be filled
43
+	 * @param transform 
44
+	 * @param color
45
+	 */
46
+	void fillPath(DPath path, DTransform2D transform, int color);
47
+	
48
+	/**
49
+	 * Draws the shadow for a given path.
50
+	 * 
51
+	 * @param path
52
+	 * @param transform
53
+	 * @param shadow
54
+	 */
55
+	void shadowPath(DPath path, DTransform2D transform, DShadow shadow);
56
+	
57
+	/**
58
+	 * Fills a rectangle.
59
+	 * 
60
+	 * @param x
61
+	 * @param y
62
+	 * @param width
63
+	 * @param height
64
+	 * @param color 
65
+	 */
66
+	void fillRectangle(int x, int y, int width, int height, int color);
67
+}

+ 16
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DClipboard.java Ver arquivo

@@ -0,0 +1,16 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DClipboard {
13
+	void copyAsString(String value);
14
+	
15
+	String getAsString();
16
+}

+ 21
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIcon.java Ver arquivo

@@ -0,0 +1,21 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DTransform2D;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface DColorableIcon {
16
+	void draw(DCanvas canvas, DTransform2D transform, int color);
17
+	
18
+	float getNominalWidth();
19
+	
20
+	float getNominalHeight();
21
+}

+ 59
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DComponent.java Ver arquivo

@@ -0,0 +1,59 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import java.io.Closeable;
9
+import org.openzen.drawablegui.live.LiveObject;
10
+import org.openzen.drawablegui.style.DStylePath;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public interface DComponent extends Closeable {
17
+	void setContext(DStylePath parent, DUIContext context);
18
+	
19
+	LiveObject<DDimensionPreferences> getDimensionPreferences();
20
+	
21
+	DIRectangle getBounds();
22
+	
23
+	void setBounds(DIRectangle bounds);
24
+	
25
+	void paint(DCanvas canvas);
26
+	
27
+	default void onMounted() {}
28
+	
29
+	default void onUnmounted() {}
30
+	
31
+	default void onMouseEnter(DMouseEvent e) {}
32
+	
33
+	default void onMouseExit(DMouseEvent e) {}
34
+	
35
+	default void onMouseMove(DMouseEvent e) {}
36
+	
37
+	default void onMouseDrag(DMouseEvent e) {}
38
+	
39
+	default void onMouseClick(DMouseEvent e) {}
40
+	
41
+	default void onMouseDown(DMouseEvent e) {}
42
+	
43
+	default void onMouseRelease(DMouseEvent e) {}
44
+	
45
+	default void onMouseScroll(DMouseEvent e) {}
46
+	
47
+	default void onFocusLost() {}
48
+	
49
+	default void onFocusGained() {}
50
+	
51
+	default void onKeyTyped(DKeyEvent e) {}
52
+	
53
+	default void onKeyPressed(DKeyEvent e) {}
54
+	
55
+	default void onKeyReleased(DKeyEvent e) {}
56
+	
57
+	@Override
58
+	void close();
59
+}

+ 39
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DDimensionPreferences.java Ver arquivo

@@ -0,0 +1,39 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DDimensionPreferences {
13
+	public static final DDimensionPreferences EMPTY = new DDimensionPreferences(0, 0);
14
+	
15
+	public final int minimumWidth;
16
+	public final int minimumHeight;
17
+	public final int preferredWidth;
18
+	public final int preferredHeight;
19
+	public final int maximumWidth;
20
+	public final int maximumHeight;
21
+	
22
+	public DDimensionPreferences(int preferredWidth, int preferredHeight) {
23
+		this.minimumWidth = 0;
24
+		this.minimumHeight = 0;
25
+		this.preferredWidth = preferredWidth;
26
+		this.preferredHeight = preferredHeight;
27
+		this.maximumWidth = 1000000;
28
+		this.maximumHeight = 1000000;
29
+	}
30
+	
31
+	public DDimensionPreferences(int minimumWidth, int minimumHeight, int preferredWidth, int preferredHeight, int maximumWidth, int maximumHeight) {
32
+		this.minimumWidth = minimumWidth;
33
+		this.minimumHeight = minimumHeight;
34
+		this.preferredWidth = preferredWidth;
35
+		this.preferredHeight = preferredHeight;
36
+		this.maximumWidth = maximumWidth;
37
+		this.maximumHeight = maximumHeight;
38
+	}
39
+}

+ 18
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DDrawable.java Ver arquivo

@@ -0,0 +1,18 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DDrawable {
13
+	void draw(DCanvas canvas, DTransform2D transform);
14
+	
15
+	float getNominalWidth();
16
+	
17
+	float getNominalHeight();
18
+}

+ 53
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DEmptyView.java Ver arquivo

@@ -0,0 +1,53 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import org.openzen.drawablegui.live.ImmutableLiveObject;
9
+import org.openzen.drawablegui.live.LiveObject;
10
+import org.openzen.drawablegui.style.DStylePath;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class DEmptyView implements DComponent {
17
+	public static final DEmptyView INSTANCE = new DEmptyView();
18
+	
19
+	private static final LiveObject<DDimensionPreferences> DIMENSION = new ImmutableLiveObject(new DDimensionPreferences(0, 0));
20
+	private static final DIRectangle NO_BOUNDS = new DIRectangle(0, 0, 0, 0);
21
+	
22
+	private DEmptyView() {}
23
+
24
+	@Override
25
+	public void setContext(DStylePath parent, DUIContext context) {
26
+		
27
+	}
28
+	
29
+	@Override
30
+	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
31
+		return DIMENSION;
32
+	}
33
+	
34
+	@Override
35
+	public DIRectangle getBounds() {
36
+		return NO_BOUNDS;
37
+	}
38
+
39
+	@Override
40
+	public void setBounds(DIRectangle bounds) {
41
+		
42
+	}
43
+
44
+	@Override
45
+	public void paint(DCanvas canvas) {
46
+		
47
+	}
48
+
49
+	@Override
50
+	public void close() {
51
+		// nothing to clean up
52
+	}
53
+}

+ 70
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DFont.java Ver arquivo

@@ -0,0 +1,70 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import java.util.Objects;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class DFont {
15
+	public final DFontFamily family;
16
+	public final boolean bold;
17
+	public final boolean italic;
18
+	public final boolean underline;
19
+	public final int size;
20
+	
21
+	public Object cached;
22
+	
23
+	public DFont(DFontFamily family, boolean bold, boolean italic, boolean underline, int size) {
24
+		this.family = family;
25
+		this.bold = bold;
26
+		this.italic = italic;
27
+		this.underline = underline;
28
+		this.size = size;
29
+	}
30
+
31
+	@Override
32
+	public int hashCode() {
33
+		int hash = 3;
34
+		hash = 29 * hash + Objects.hashCode(this.family);
35
+		hash = 29 * hash + (this.bold ? 1 : 0);
36
+		hash = 29 * hash + (this.italic ? 1 : 0);
37
+		hash = 29 * hash + (this.underline ? 1 : 0);
38
+		hash = 29 * hash + Float.floatToIntBits(this.size);
39
+		return hash;
40
+	}
41
+
42
+	@Override
43
+	public boolean equals(Object obj) {
44
+		if (this == obj) {
45
+			return true;
46
+		}
47
+		if (obj == null) {
48
+			return false;
49
+		}
50
+		if (getClass() != obj.getClass()) {
51
+			return false;
52
+		}
53
+		final DFont other = (DFont) obj;
54
+		if (this.bold != other.bold) {
55
+			return false;
56
+		}
57
+		if (this.italic != other.italic) {
58
+			return false;
59
+		}
60
+		if (this.underline != other.underline) {
61
+			return false;
62
+		}
63
+		if (this.size != other.size)
64
+			return false;
65
+		if (this.family != other.family) {
66
+			return false;
67
+		}
68
+		return true;
69
+	}
70
+}

+ 15
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DFontFamily.java Ver arquivo

@@ -0,0 +1,15 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public enum DFontFamily {
13
+	UI,
14
+	CODE
15
+}

+ 22
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DFontMetrics.java Ver arquivo

@@ -0,0 +1,22 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DFontMetrics {
13
+	int getAscent();
14
+	
15
+	int getDescent();
16
+	
17
+	int getLeading();
18
+	
19
+	int getWidth(String str);
20
+	
21
+	int getWidth(String str, int offset, int length);
22
+}

+ 31
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DIRectangle.java Ver arquivo

@@ -0,0 +1,31 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DIRectangle {
13
+	public static final DIRectangle EMPTY = new DIRectangle(0, 0, 0, 0);
14
+	
15
+	public final int x;
16
+	public final int y;
17
+	public final int width;
18
+	public final int height;
19
+	
20
+	public DIRectangle(int x, int y, int width, int height) {
21
+		this.x = x;
22
+		this.y = y;
23
+		this.width = width;
24
+		this.height = height;
25
+	}
26
+	
27
+	public boolean contains(int x, int y) {
28
+		return x >= this.x && x < (this.x + this.width)
29
+				&& y >= this.y && y < (this.y + this.height);
30
+	}
31
+}

+ 211
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DKeyEvent.java Ver arquivo

@@ -0,0 +1,211 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DKeyEvent {
13
+	public static final char CHAR_UNDEFINED = 65535;
14
+	
15
+	public static final int BUTTON1 = 1;
16
+	public static final int BUTTON2 = 2;
17
+	public static final int BUTTON3 = 4;
18
+	public static final int ALT = 256;
19
+	public static final int CTRL = 512;
20
+	public static final int SHIFT = 1024;
21
+	public static final int META = 2048;
22
+	public static final int ALT_GRAPH = 4096;
23
+	
24
+	public final char character;
25
+	public final KeyCode keyCode;
26
+	public final int modifiers;
27
+	
28
+	public DKeyEvent(char character, KeyCode keyCode, int modifiers) {
29
+		this.character = character;
30
+		this.keyCode = keyCode;
31
+		this.modifiers = modifiers;
32
+	}
33
+	
34
+	public boolean has(int modifiers) {
35
+		return (this.modifiers & modifiers) == modifiers;
36
+	}
37
+	
38
+	public enum KeyCode {
39
+		ENTER,
40
+		BACKSPACE,
41
+		TAB,
42
+		CANCEL,
43
+		CLEAR,
44
+		SHIFT,
45
+		CONTROL,
46
+		ALT,
47
+		PAUSE,
48
+		CAPS_LOCK,
49
+		ESCAPE,
50
+		SPACE,
51
+		PAGE_UP,
52
+		PAGE_DOWN,
53
+		END,
54
+		HOME,
55
+		LEFT,
56
+		UP,
57
+		RIGHT,
58
+		DOWN,
59
+		COMMA,
60
+		MINUS,
61
+		PERIOD,
62
+		SLASH,
63
+		NUM0,
64
+		NUM1,
65
+		NUM2,
66
+		NUM3,
67
+		NUM4,
68
+		NUM5,
69
+		NUM6,
70
+		NUM7,
71
+		NUM8,
72
+		NUM9,
73
+		SEMICOLON,
74
+		EQUALS,
75
+		A,
76
+		B,
77
+		C,
78
+		D,
79
+		E,
80
+		F,
81
+		G,
82
+		H,
83
+		I,
84
+		J,
85
+		K,
86
+		L,
87
+		M,
88
+		N,
89
+		O,
90
+		P,
91
+		Q,
92
+		R,
93
+		S,
94
+		T,
95
+		U,
96
+		V,
97
+		W,
98
+		X,
99
+		Y,
100
+		Z,
101
+		OPEN_BRACKET,
102
+		BACKSLASH,
103
+		CLOSE_BRACKET,
104
+		NUMPAD0,
105
+		NUMPAD1,
106
+		NUMPAD2,
107
+		NUMPAD3,
108
+		NUMPAD4,
109
+		NUMPAD5,
110
+		NUMPAD6,
111
+		NUMPAD7,
112
+		NUMPAD8,
113
+		NUMPAD9,
114
+		MULTIPLY,
115
+		ADD,
116
+		SEPARATOR,
117
+		SUBTRACT,
118
+		DECIMAL,
119
+		DIVIDE,
120
+		DELETE,
121
+		NUM_LOCK,
122
+		SCROLL_LOCK,
123
+		F1,
124
+		F2,
125
+		F3,
126
+		F4,
127
+		F5,
128
+		F6,
129
+		F7,
130
+		F8,
131
+		F9,
132
+		F10,
133
+		F11,
134
+		F12,
135
+		F13,
136
+		F14,
137
+		F15,
138
+		F16,
139
+		F17,
140
+		F18,
141
+		F19,
142
+		F20,
143
+		F21,
144
+		F22,
145
+		F23,
146
+		F24,
147
+		PRINTSCREEN,
148
+		INSERT,
149
+		HELP,
150
+		META,
151
+		BACKQUOTE,
152
+		QUOTE,
153
+		KEYPAD_UP,
154
+		KEYPAD_DOWN,
155
+		KEYPAD_LEFT,
156
+		KEYPAD_RIGHT,
157
+		AMPERSAND,
158
+		ASTERISK,
159
+		QUOTEDBL,
160
+		LESS,
161
+		GREATER,
162
+		BRACELEFT,
163
+		BRACERIGHT,
164
+		AT,
165
+		COLON,
166
+		CIRCUMFLEX,
167
+		DOLLAR,
168
+		EURO_SIGN,
169
+		EXCLAMATION_MARK,
170
+		INVERTED_EXCLAMATION_MARK,
171
+		LEFT_PARENTHESIS,
172
+		NUMBER_SIGN,
173
+		PLUS,
174
+		RIGHT_PARENTHESIS,
175
+		UNDERSCORE,
176
+		WINDOWS,
177
+		CONTEXT_MENU,
178
+		FINAL,
179
+		CONVERT,
180
+		NONCONVERT,
181
+		ACCEPT,
182
+		KANA,
183
+		KANJI,
184
+		ALPHANUMERIC,
185
+		KATAKANA,
186
+		HIRAGANA,
187
+		FULL_WIDTH,
188
+		HALF_WIDTH,
189
+		ROMAN_CHARACTERS,
190
+		ALL_CANDIDATES,
191
+		PREVIOUS_CANDIDATE,
192
+		CODE_INPUT,
193
+		JAPANESE_KATAKANA,
194
+		JAPANESE_HIRAGANA,
195
+		JAPANESE_ROMAN,
196
+		KANA_LOCK,
197
+		INPUT_METHOD_ON_OFF,
198
+		CUT,
199
+		COPY,
200
+		PASTE,
201
+		UNDO,
202
+		AGAIN,
203
+		FIND,
204
+		PROPS,
205
+		STOP,
206
+		COMPOSE,
207
+		ALT_GRAPH,
208
+		BEGIN,
209
+		UNKNOWN
210
+	}
211
+}

+ 51
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DMouseEvent.java Ver arquivo

@@ -0,0 +1,51 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DMouseEvent {
13
+	public static final int BUTTON1 = 1;
14
+	public static final int BUTTON2 = 2;
15
+	public static final int BUTTON3 = 4;
16
+	public static final int ALT = 256;
17
+	public static final int CTRL = 512;
18
+	public static final int SHIFT = 1024;
19
+	public static final int META = 2048;
20
+	public static final int ALT_GRAPH = 4096;
21
+	
22
+	public final int x;
23
+	public final int y;
24
+	public final int modifiers;
25
+	public final int deltaZ;
26
+	public final int clickCount;
27
+	
28
+	public DMouseEvent(int x, int y, int modifiers, int deltaZ, int clickCount) {
29
+		this.x = x;
30
+		this.y = y;
31
+		this.modifiers = modifiers;
32
+		this.deltaZ = deltaZ;
33
+		this.clickCount = clickCount;
34
+	}
35
+	
36
+	public boolean isSingleClick() {
37
+		return clickCount == 1;
38
+	}
39
+	
40
+	public boolean isDoubleClick() {
41
+		return clickCount == 2;
42
+	}
43
+	
44
+	public boolean isTripleClick() {
45
+		return clickCount == 3;
46
+	}
47
+	
48
+	public boolean has(int modifiers) {
49
+		return (this.modifiers & modifiers) == modifiers;
50
+	}
51
+}

+ 75
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DPath.java Ver arquivo

@@ -0,0 +1,75 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DPath {
13
+	public static DPath circle(float x, float y, float radius) {
14
+		// see http://spencermortensen.com/articles/bezier-circle/
15
+		return tracer -> {
16
+			float c = radius * 0.551915024494f;
17
+			tracer.moveTo(x, y + radius);
18
+			tracer.bezierCubic(
19
+					x + c, y + radius,
20
+					x + radius, y + c,
21
+					x + radius, y);
22
+			tracer.bezierCubic(
23
+					x + radius, y - c,
24
+					x + c, y - radius,
25
+					x, y - radius);
26
+			tracer.bezierCubic(
27
+					x - c, y - radius,
28
+					x - radius, y - c,
29
+					x - radius, y);
30
+			tracer.bezierCubic(
31
+					x - radius, y + c,
32
+					x - c, y + radius,
33
+					x, y + radius);
34
+		};
35
+	}
36
+	
37
+	public static DPath rectangle(float x, float y, float width, float height) {
38
+		return tracer -> {
39
+			tracer.moveTo(x, y);
40
+			tracer.lineTo(x + width, y);
41
+			tracer.lineTo(x + width, y + height);
42
+			tracer.lineTo(x, y + height);
43
+			tracer.close();
44
+		};
45
+	}
46
+	
47
+	public static DPath roundedRectangle(float x, float y, float width, float height, float radius) {
48
+		return tracer -> {
49
+			float c = radius - radius * 0.551915024494f;
50
+			tracer.moveTo(x + width - radius, y + height);
51
+			tracer.bezierCubic(
52
+					x + width - c, y + height,
53
+					x + width, y + height - c,
54
+					x + width, y + height - radius);
55
+			tracer.lineTo(x + width, y + radius);
56
+			tracer.bezierCubic(
57
+					x + width, y + c,
58
+					x + width - c, y,
59
+					x + width - radius, y);
60
+			tracer.lineTo(x + radius, y);
61
+			tracer.bezierCubic(
62
+					x + c, y,
63
+					x, y + c,
64
+					x, y + radius);
65
+			tracer.lineTo(x, y + height - radius);
66
+			tracer.bezierCubic(
67
+					x, y + height - c,
68
+					x + c, y + height,
69
+					x + radius, y + height);
70
+			tracer.close();
71
+		};
72
+	}
73
+	
74
+	void trace(DPathTracer tracer);
75
+}

+ 70
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DPathBoundsCalculator.java Ver arquivo

@@ -0,0 +1,70 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DPathBoundsCalculator implements DPathTracer {
13
+	public static DIRectangle getBounds(DPath path, DTransform2D transform) {
14
+		DPathBoundsCalculator calculator = new DPathBoundsCalculator(transform);
15
+		path.trace(calculator);
16
+		return new DIRectangle(
17
+				(int)calculator.minX,
18
+				(int)calculator.minY,
19
+				(int)Math.ceil(calculator.maxX - calculator.minX),
20
+				(int)Math.ceil(calculator.maxY - calculator.minY));
21
+	}
22
+	
23
+	private final DTransform2D transform;
24
+	private float minX = Float.MAX_VALUE;
25
+	private float minY = Float.MAX_VALUE;
26
+	private float maxX = Float.MIN_VALUE;
27
+	private float maxY = Float.MIN_VALUE;
28
+	
29
+	private DPathBoundsCalculator(DTransform2D transform) {
30
+		this.transform = transform;
31
+	}
32
+	
33
+	private void add(float x, float y) {
34
+		float tx = transform.getX(x, y);
35
+		float ty = transform.getY(x, y);
36
+		
37
+		minX = Math.min(minX, tx);
38
+		minY = Math.min(minY, ty);
39
+		maxX = Math.max(maxX, tx);
40
+		maxY = Math.max(maxY, ty);
41
+	}
42
+
43
+	@Override
44
+	public void moveTo(float x, float y) {
45
+		add(x, y);
46
+	}
47
+
48
+	@Override
49
+	public void lineTo(float x, float y) {
50
+		add(x, y);
51
+	}
52
+
53
+	@Override
54
+	public void bezierCubic(float x1, float y1, float x2, float y2, float x3, float y3) {
55
+		add(x1, y1);
56
+		add(x2, y2);
57
+		add(x3, y3);
58
+	}
59
+
60
+	@Override
61
+	public void bezierQuadratic(float x1, float y1, float x2, float y2) {
62
+		add(x1, y1);
63
+		add(x2, y2);
64
+	}
65
+
66
+	@Override
67
+	public void close() {
68
+		
69
+	}
70
+}

+ 14
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DPathCommand.java Ver arquivo

@@ -0,0 +1,14 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DPathCommand {
13
+	public void accept(DPathTracer tracer);
14
+}

+ 22
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DPathTracer.java Ver arquivo

@@ -0,0 +1,22 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DPathTracer {
13
+	public void moveTo(float x, float y);
14
+	
15
+	public void lineTo(float x, float y);
16
+	
17
+	public void bezierCubic(float x1, float y1, float x2, float y2, float x3, float y3);
18
+	
19
+	public void bezierQuadratic(float x1, float y1, float x2, float y2);
20
+	
21
+	public void close();
22
+}

+ 14
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DPreparedPath.java Ver arquivo

@@ -0,0 +1,14 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DPreparedPath {
13
+	
14
+}

+ 261
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DSideLayout.java Ver arquivo

@@ -0,0 +1,261 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import java.io.Closeable;
9
+import java.util.ArrayList;
10
+import java.util.List;
11
+import java.util.function.Consumer;
12
+import java.util.function.Predicate;
13
+import org.openzen.drawablegui.listeners.ListenerHandle;
14
+import org.openzen.drawablegui.live.LiveObject;
15
+import org.openzen.drawablegui.live.SimpleLiveObject;
16
+import org.openzen.drawablegui.style.DStyleClass;
17
+import org.openzen.drawablegui.style.DStylePath;
18
+
19
+/**
20
+ *
21
+ * @author Hoofdgebruiker
22
+ */
23
+public class DSideLayout extends BaseComponentGroup {
24
+	private final DStyleClass styleClass;
25
+	
26
+	private DComponent main;
27
+	private final List<SideComponent> sides = new ArrayList<>();
28
+	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
29
+	
30
+	private DStylePath path;
31
+	private DUIContext context;
32
+	private DIRectangle bounds;
33
+	
34
+	public DSideLayout(DStyleClass styleClass, DComponent main) {
35
+		this.styleClass = styleClass;
36
+		this.main = main;
37
+	}
38
+	
39
+	public void add(Side side, DComponent component) {
40
+		if (context != null)
41
+			component.setContext(path, context);
42
+		
43
+		sides.add(new SideComponent(side, component));
44
+	}
45
+	
46
+	public void setMain(DComponent component) {
47
+		if (this.main != null)
48
+			this.main.close();
49
+		
50
+		this.main = component;
51
+		
52
+		if (context != null && bounds != null) {
53
+			main.setContext(path, context);
54
+			setBounds(bounds);
55
+			context.repaint(bounds);
56
+		}
57
+	}
58
+
59
+	@Override
60
+	public void setContext(DStylePath parent, DUIContext context) {
61
+		this.context = context;
62
+		this.path = parent.getChild("sidelayout", styleClass);
63
+		
64
+		main.setContext(path, context);
65
+		for (SideComponent side : sides)
66
+			side.component.setContext(path, context);
67
+	}
68
+	
69
+	@Override
70
+	public DIRectangle getBounds() {
71
+		return bounds;
72
+	}
73
+
74
+	@Override
75
+	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
76
+		return dimensionPreferences;
77
+	}
78
+
79
+	@Override
80
+	public void setBounds(DIRectangle bounds) {
81
+		this.bounds = bounds;
82
+		
83
+		int left = bounds.x;
84
+		int right = bounds.x + bounds.width;
85
+		int top = bounds.y;
86
+		int bottom = bounds.y + bounds.height;
87
+		for (int i = sides.size() - 1; i >= 0; i--) {
88
+			SideComponent side = sides.get(i);
89
+			DDimensionPreferences preferences = side.component.getDimensionPreferences().getValue();
90
+			
91
+			switch (side.side) {
92
+				case TOP: {
93
+					int componentWidth = right - left;
94
+					int componentHeight = preferences.preferredHeight;
95
+					int componentX = left;
96
+					int componentY = top;
97
+					
98
+					if (componentWidth > preferences.maximumWidth) {
99
+						componentX += (componentWidth - preferences.maximumWidth) / 2;
100
+						componentWidth = preferences.maximumWidth;
101
+					}
102
+					
103
+					side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
104
+					top += componentHeight;
105
+					break;
106
+				}
107
+				case BOTTOM: {
108
+					int componentWidth = right - left;
109
+					int componentHeight = preferences.preferredHeight;
110
+					bottom -= componentHeight;
111
+					int componentX = left;
112
+					int componentY = bottom;
113
+					
114
+					if (componentWidth > preferences.maximumWidth) {
115
+						componentX += (componentWidth - preferences.maximumWidth) / 2;
116
+						componentWidth = preferences.maximumWidth;
117
+					}
118
+					
119
+					side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
120
+					break;
121
+				}
122
+				case LEFT: {
123
+					int componentWidth = preferences.preferredWidth;
124
+					int componentHeight = bottom - top;
125
+					int componentX = left;
126
+					int componentY = top;
127
+					
128
+					if (componentHeight > preferences.maximumHeight) {
129
+						componentY += (componentHeight - preferences.maximumHeight) / 2;
130
+						componentHeight = preferences.maximumHeight;
131
+					}
132
+					
133
+					side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
134
+					left += componentWidth;
135
+					break;
136
+				}
137
+				case RIGHT: {
138
+					int componentWidth = preferences.preferredWidth;
139
+					int componentHeight = bottom - top;
140
+					right -= componentWidth;
141
+					int componentX = right;
142
+					int componentY = top;
143
+					
144
+					if (componentHeight > preferences.maximumHeight) {
145
+						componentY += (componentHeight - preferences.maximumHeight) / 2;
146
+						componentHeight = preferences.maximumHeight;
147
+					}
148
+					
149
+					side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
150
+					break;
151
+				}
152
+			}
153
+		}
154
+		
155
+		main.setBounds(new DIRectangle(left, top, right - left, bottom - top));
156
+	}
157
+
158
+	@Override
159
+	public void paint(DCanvas canvas) {
160
+		main.paint(canvas);
161
+		
162
+		for (SideComponent component : sides)
163
+			component.component.paint(canvas);
164
+	}
165
+	
166
+	private void recalculateSize() {
167
+		DDimensionPreferences mainPreferences = main.getDimensionPreferences().getValue();
168
+		int minimumWidth = mainPreferences.minimumWidth;
169
+		int minimumHeight = mainPreferences.minimumHeight;
170
+		int preferredWidth = mainPreferences.preferredWidth;
171
+		int preferredHeight = mainPreferences.preferredHeight;
172
+		int maximumWidth = mainPreferences.maximumWidth;
173
+		int maximumHeight = mainPreferences.maximumHeight;
174
+		
175
+		for (SideComponent side : sides) {
176
+			DDimensionPreferences sidePreferences = side.component.getDimensionPreferences().getValue();
177
+			switch (side.side) {
178
+				case LEFT:
179
+				case RIGHT:
180
+					minimumWidth += sidePreferences.preferredWidth;
181
+					preferredWidth += sidePreferences.preferredWidth;
182
+					maximumWidth += sidePreferences.preferredWidth;
183
+					
184
+					minimumHeight = Math.max(minimumHeight, sidePreferences.minimumHeight);
185
+					preferredHeight = Math.max(maximumHeight, sidePreferences.preferredHeight);
186
+					break;
187
+				case BOTTOM:
188
+				case TOP:
189
+					minimumHeight += sidePreferences.preferredHeight;
190
+					preferredHeight += sidePreferences.preferredHeight;
191
+					maximumHeight += sidePreferences.preferredHeight;
192
+					
193
+					minimumWidth = Math.max(minimumWidth, sidePreferences.minimumWidth);
194
+					preferredWidth = Math.max(preferredWidth, sidePreferences.preferredWidth);
195
+					break;
196
+			}
197
+		}
198
+		
199
+		dimensionPreferences.setValue(new DDimensionPreferences(
200
+				minimumWidth,
201
+				minimumHeight,
202
+				preferredWidth,
203
+				preferredHeight,
204
+				maximumWidth,
205
+				maximumHeight));
206
+	}
207
+
208
+	@Override
209
+	protected void forEachChild(Consumer<DComponent> children) {
210
+		children.accept(main);
211
+		for (SideComponent side : sides)
212
+			children.accept(side.component);
213
+	}
214
+	
215
+	@Override
216
+	public DComponent findChild(Predicate<DComponent> predicate) {
217
+		if (predicate.test(main))
218
+			return main;
219
+		for (SideComponent side : sides)
220
+			if (predicate.test(side.component))
221
+				return side.component;
222
+		
223
+		return null;
224
+	}
225
+
226
+	@Override
227
+	public void close() {
228
+		main.close();
229
+		for (SideComponent side : sides)
230
+			side.close();
231
+	}
232
+	
233
+	public class SideComponent implements Closeable, LiveObject.Listener<DDimensionPreferences> {
234
+		public final Side side;
235
+		public final DComponent component;
236
+		public final ListenerHandle<LiveObject.Listener<DDimensionPreferences>> listenerHandle;
237
+
238
+		public SideComponent(Side side, DComponent component) {
239
+			this.side = side;
240
+			this.component = component;
241
+			listenerHandle = component.getDimensionPreferences().addListener(this);
242
+		}
243
+		
244
+		@Override
245
+		public void close() {
246
+			listenerHandle.close();
247
+		}
248
+
249
+		@Override
250
+		public void onUpdated(DDimensionPreferences oldValue, DDimensionPreferences newValue) {
251
+			recalculateSize();
252
+		}
253
+	}
254
+	
255
+	public enum Side {
256
+		LEFT,
257
+		RIGHT,
258
+		TOP,
259
+		BOTTOM
260
+	}
261
+}

+ 17
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DTimerHandle.java Ver arquivo

@@ -0,0 +1,17 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import java.io.Closeable;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface DTimerHandle extends Closeable {
15
+	@Override
16
+	public void close();
17
+}

+ 70
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DTransform2D.java Ver arquivo

@@ -0,0 +1,70 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public final class DTransform2D {
13
+	public static final DTransform2D IDENTITY = new DTransform2D(1, 0, 0, 1, 0, 0);
14
+	
15
+	public static DTransform2D translate(float x, float y) {
16
+		return new DTransform2D(1, 0, 0, 1, x, y);
17
+	}
18
+	
19
+	public static DTransform2D scaleAndTranslate(float x, float y, float scale) {
20
+		return new DTransform2D(scale, 0, 0, scale, x, y);
21
+	}
22
+	
23
+	public static DTransform2D scale(float scale) {
24
+		return new DTransform2D(scale, 0, 0, scale, 0, 0);
25
+	}
26
+	
27
+	public final float xx;
28
+	public final float xy;
29
+	public final float yx;
30
+	public final float yy;
31
+	public final float dx;
32
+	public final float dy;
33
+	
34
+	public DTransform2D(float xx, float xy, float yx, float yy, float dx, float dy) {
35
+		this.xx = xx;
36
+		this.xy = xy;
37
+		this.yx = yx;
38
+		this.yy = yy;
39
+		this.dx = dx;
40
+		this.dy = dy;
41
+	}
42
+	
43
+	public DTransform2D offset(float x, float y) {
44
+		return new DTransform2D(xx, xy, yx, yy, dx + x, dy + y);
45
+	}
46
+	
47
+	public float getX(float x, float y) {
48
+		return x * xx + y * xy + dx;
49
+	}
50
+	
51
+	public float getY(float x, float y) {
52
+		return x * yx + y * yy + dy;
53
+	}
54
+	
55
+	public DTransform2D mul(DTransform2D other) {
56
+		// [xx xy dx]   [xx xy dx]   [xx*xx+xy*yx xx*xy+xy*yy xx*dx+xy*dy+dx]
57
+		// [yx yy dy] x [yx yy dy] = [yx*xx+yy*yx yx*xy+yy*yy yx*dx+yy*dy+dy]
58
+		// [0  0  1 ]   [0  0  1 ]   [0           0           1             ]
59
+		DTransform2D a = this;
60
+		DTransform2D b = other;
61
+		return new DTransform2D(
62
+				a.xx * b.xx + a.xy * b.yx,
63
+				a.xx * b.xy + a.xy * b.yy,
64
+				a.yx * b.xx + a.yy * b.yx,
65
+				a.yx * b.xy + a.yx + b.xy,
66
+				a.xx * b.dx + a.xy * b.dy + dx,
67
+				a.yx * b.dx + a.yy * b.dy + dy
68
+		);
69
+	}
70
+}

+ 50
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DUIContext.java Ver arquivo

@@ -0,0 +1,50 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import org.openzen.drawablegui.live.LiveObject;
9
+import org.openzen.drawablegui.style.DStyleSheets;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface DUIContext {
16
+	DStyleSheets getStylesheets();
17
+	
18
+	float getScale();
19
+	
20
+	void repaint(int x, int y, int width, int height);
21
+	
22
+	default void repaint(DIRectangle rectangle) {
23
+		repaint(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
24
+	}
25
+	
26
+	void setCursor(Cursor cursor);
27
+	
28
+	void focus(DComponent component);
29
+	
30
+	void scrollInView(int x, int y, int width, int height);
31
+	
32
+	DTimerHandle setTimer(int millis, Runnable target);
33
+	
34
+	DClipboard getClipboard();
35
+	
36
+	DFontMetrics getFontMetrics(DFont font);
37
+	
38
+	DUIWindow getWindow();
39
+		
40
+	enum Cursor {
41
+		NORMAL,
42
+		HAND,
43
+		MOVE,
44
+		TEXT,
45
+		E_RESIZE,
46
+		S_RESIZE,
47
+		NE_RESIZE,
48
+		NW_RESIZE,
49
+	}
50
+}

+ 35
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DUIWindow.java Ver arquivo

@@ -0,0 +1,35 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import org.openzen.drawablegui.live.LiveBool;
9
+import org.openzen.drawablegui.live.LiveObject;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface DUIWindow {
16
+	public boolean hasTitleBar();
17
+	
18
+	public void close();
19
+	
20
+	public void maximize();
21
+	
22
+	public void restore();
23
+	
24
+	public void minimize();
25
+	
26
+	LiveObject<State> getWindowState();
27
+	
28
+	LiveBool getActive();
29
+	
30
+	enum State {
31
+		NORMAL,
32
+		MAXIMIZED,
33
+		MINIMIZED
34
+	};
35
+}

+ 25
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DBorder.java Ver arquivo

@@ -0,0 +1,25 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.border;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DIRectangle;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface DBorder {
16
+	public void paint(DCanvas canvas, DIRectangle bounds);
17
+	
18
+	public int getPaddingLeft();
19
+	
20
+	public int getPaddingRight();
21
+	
22
+	public int getPaddingTop();
23
+	
24
+	public int getPaddingBottom();
25
+}

+ 184
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java Ver arquivo

@@ -0,0 +1,184 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.border;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DComponent;
10
+import org.openzen.drawablegui.DDimensionPreferences;
11
+import org.openzen.drawablegui.DMouseEvent;
12
+import org.openzen.drawablegui.DPath;
13
+import org.openzen.drawablegui.DTransform2D;
14
+import org.openzen.drawablegui.DUIContext;
15
+import org.openzen.drawablegui.DUIWindow;
16
+import org.openzen.drawablegui.DIRectangle;
17
+import org.openzen.drawablegui.listeners.ListenerHandle;
18
+import org.openzen.drawablegui.live.ImmutableLiveObject;
19
+import org.openzen.drawablegui.live.LiveBool;
20
+import org.openzen.drawablegui.live.LiveObject;
21
+import org.openzen.drawablegui.style.DStyleClass;
22
+import org.openzen.drawablegui.style.DStylePath;
23
+
24
+/**
25
+ *
26
+ * @author Hoofdgebruiker
27
+ */
28
+public class DCustomWindowBorder implements DComponent {
29
+	private final DStyleClass styleClass;
30
+	private final DComponent content;
31
+	private final LiveObject<DDimensionPreferences> preferences = new ImmutableLiveObject<>(DDimensionPreferences.EMPTY);
32
+	
33
+	private DUIContext context;
34
+	private DCustomWindowBorderStyle style;
35
+	private DIRectangle bounds;
36
+	private DPath border;
37
+	
38
+	private LiveBool active;
39
+	private LiveObject<DUIWindow.State> state;
40
+	
41
+	private ListenerHandle<LiveObject.Listener<DUIWindow.State>> stateListener;
42
+	private ListenerHandle<LiveBool.Listener> activeListener;
43
+	
44
+	public DCustomWindowBorder(DStyleClass styleClass, DComponent content) {
45
+		this.styleClass = styleClass;
46
+		this.content = content;
47
+	}
48
+
49
+	@Override
50
+	public void setContext(DStylePath parent, DUIContext context) {
51
+		this.context = context;
52
+		content.setContext(parent, context);
53
+		
54
+		state = context.getWindow().getWindowState();
55
+		active = context.getWindow().getActive();
56
+		stateListener = state.addListener(this::onStateChanged);
57
+		activeListener = active.addListener(this::onActiveChanged);
58
+		
59
+		DStylePath path = parent.getChild("customwindowborder", styleClass);
60
+		style = new DCustomWindowBorderStyle(context.getStylesheets().get(context, path));
61
+		
62
+		if (bounds != null)
63
+			layout();
64
+	}
65
+
66
+	@Override
67
+	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
68
+		return preferences;
69
+	}
70
+
71
+	@Override
72
+	public DIRectangle getBounds() {
73
+		return bounds;
74
+	}
75
+
76
+	@Override
77
+	public void setBounds(DIRectangle bounds) {
78
+		this.bounds = bounds;
79
+		layout();
80
+	}
81
+	
82
+	private void layout() {	
83
+		if (style == null)
84
+			return;
85
+		
86
+		if (state.getValue() != DUIWindow.State.MAXIMIZED) {
87
+			border = DPath.rectangle(
88
+				bounds.x + style.padding,
89
+				bounds.y + style.padding,
90
+				bounds.width - 2 * style.padding - style.borderWidth,
91
+				bounds.height - 2 * style.padding - style.borderWidth);
92
+			
93
+			int spacing = style.borderWidth + style.padding;
94
+			DIRectangle inner = new DIRectangle(
95
+					bounds.x + spacing,
96
+					bounds.y + spacing,
97
+					bounds.width - 2 * spacing,
98
+					bounds.height - 2 * spacing);
99
+
100
+			content.setBounds(inner);
101
+		} else {
102
+			content.setBounds(bounds);
103
+		}
104
+		context.repaint(bounds);
105
+	}
106
+
107
+	@Override
108
+	public void paint(DCanvas canvas) {
109
+		if (state.getValue() != DUIWindow.State.MAXIMIZED) {
110
+			int spacing = style.borderWidth + style.padding;
111
+			DIRectangle canvasBounds = canvas.getBounds();
112
+			if (canvasBounds == null
113
+					|| canvasBounds.x < bounds.x + spacing
114
+					|| canvasBounds.y < bounds.y + spacing
115
+					|| canvasBounds.x + canvasBounds.width > bounds.x + bounds.width - spacing
116
+					|| canvasBounds.y + canvasBounds.height > bounds.y + bounds.height - spacing) {
117
+				canvas.shadowPath(border, DTransform2D.IDENTITY, style.shadow);
118
+				canvas.fillPath(border, DTransform2D.IDENTITY, style.backgroundColor);
119
+				canvas.strokePath(
120
+						border,
121
+						DTransform2D.IDENTITY,
122
+						active.getValue() ? style.focusedBorderColor : style.inactiveBorderColor,
123
+						style.borderWidth);
124
+			}
125
+		} else {
126
+			canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.backgroundColor);
127
+		}
128
+		
129
+		content.paint(canvas);
130
+	}
131
+
132
+	@Override
133
+	public void onMouseEnter(DMouseEvent e) {
134
+		content.onMouseEnter(e);
135
+	}
136
+	
137
+	@Override
138
+	public void onMouseExit(DMouseEvent e) {
139
+		content.onMouseExit(e);
140
+	}
141
+	
142
+	@Override
143
+	public void onMouseMove(DMouseEvent e) {
144
+		content.onMouseMove(e);
145
+	}
146
+	
147
+	@Override
148
+	public void onMouseDrag(DMouseEvent e) {
149
+		content.onMouseDrag(e);
150
+	}
151
+	
152
+	@Override
153
+	public void onMouseClick(DMouseEvent e) {
154
+		content.onMouseClick(e);
155
+	}
156
+	
157
+	@Override
158
+	public void onMouseDown(DMouseEvent e) {
159
+		content.onMouseDown(e);
160
+	}
161
+	
162
+	@Override
163
+	public void onMouseRelease(DMouseEvent e) {
164
+		content.onMouseRelease(e);
165
+	}
166
+	
167
+	@Override
168
+	public void onMouseScroll(DMouseEvent e) {
169
+		content.onMouseScroll(e);
170
+	}
171
+	
172
+	@Override
173
+	public void close() {
174
+		
175
+	}
176
+	
177
+	private void onStateChanged(DUIWindow.State oldValue, DUIWindow.State newValue) {
178
+		layout();
179
+	}
180
+	
181
+	private void onActiveChanged(boolean oldValue, boolean newValue) {
182
+		context.repaint(bounds);
183
+	}
184
+}

+ 35
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorderStyle.java Ver arquivo

@@ -0,0 +1,35 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.border;
7
+
8
+import org.openzen.drawablegui.style.DDpDimension;
9
+import org.openzen.drawablegui.style.DPxDimension;
10
+import org.openzen.drawablegui.style.DShadow;
11
+import org.openzen.drawablegui.style.DStyleDefinition;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class DCustomWindowBorderStyle {
18
+	public final int padding;
19
+	public final DShadow shadow;
20
+	public final int borderWidth;
21
+	public final int backgroundColor;
22
+	
23
+	public final int focusedBorderColor;
24
+	public final int inactiveBorderColor;
25
+	
26
+	public DCustomWindowBorderStyle(DStyleDefinition style) {
27
+		padding = style.getDimension("padding", new DDpDimension(8));
28
+		shadow = style.getShadow("shadow", context -> new DShadow(0x80888888, 0, 0, 6 * context.getScale()));
29
+		borderWidth = style.getDimension("borderWidth", new DPxDimension(1));
30
+		backgroundColor = style.getColor("backgroundColor", 0xFFEEEEEE);
31
+		
32
+		focusedBorderColor = style.getColor("focusedBorderColor", 0xFF18B0FB);
33
+		inactiveBorderColor = style.getColor("inactiveBorderColor", 0xFF515252);
34
+	}
35
+}

+ 43
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java Ver arquivo

@@ -0,0 +1,43 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.border;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DIRectangle;
10
+import org.openzen.drawablegui.DUIContext;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class DEmptyBorder implements DBorder {
17
+	public static final DEmptyBorder INSTANCE = new DEmptyBorder();
18
+	
19
+	@Override
20
+	public void paint(DCanvas canvas, DIRectangle bounds) {
21
+		
22
+	}
23
+
24
+	@Override
25
+	public int getPaddingLeft() {
26
+		return 0;
27
+	}
28
+
29
+	@Override
30
+	public int getPaddingRight() {
31
+		return 0;
32
+	}
33
+
34
+	@Override
35
+	public int getPaddingTop() {
36
+		return 0;
37
+	}
38
+
39
+	@Override
40
+	public int getPaddingBottom() {
41
+		return 0;
42
+	}
43
+}

+ 56
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java Ver arquivo

@@ -0,0 +1,56 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.border;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DTransform2D;
10
+import org.openzen.drawablegui.DIRectangle;
11
+import org.openzen.drawablegui.DUIContext;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class DLineBorder implements DBorder {
18
+	private final int color;
19
+	private final int borderWidth;
20
+	
21
+	public DLineBorder(int color, int borderWidth) {
22
+		this.color = color;
23
+		this.borderWidth = borderWidth;
24
+	}
25
+
26
+	@Override
27
+	public void paint(DCanvas canvas, DIRectangle bounds) {
28
+		canvas.strokePath(tracer -> {
29
+				tracer.moveTo(bounds.x, bounds.y);
30
+				tracer.lineTo(bounds.x + bounds.width - borderWidth, bounds.y);
31
+				tracer.lineTo(bounds.x + bounds.width - borderWidth, bounds.y + bounds.height - borderWidth);
32
+				tracer.lineTo(bounds.x, bounds.y + bounds.height - borderWidth);
33
+				tracer.close();
34
+			}, DTransform2D.IDENTITY, color, borderWidth);
35
+	}
36
+
37
+	@Override
38
+	public int getPaddingLeft() {
39
+		return borderWidth;
40
+	}
41
+
42
+	@Override
43
+	public int getPaddingRight() {
44
+		return borderWidth;
45
+	}
46
+
47
+	@Override
48
+	public int getPaddingTop() {
49
+		return borderWidth;
50
+	}
51
+
52
+	@Override
53
+	public int getPaddingBottom() {
54
+		return borderWidth;
55
+	}
56
+}

+ 28
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/listeners/DummyListenerHandle.java Ver arquivo

@@ -0,0 +1,28 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.listeners;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DummyListenerHandle<T> implements ListenerHandle<T> {
13
+	private final T listener;
14
+
15
+	public DummyListenerHandle(T listener) {
16
+		this.listener = listener;
17
+	}
18
+
19
+	@Override
20
+	public T getListener() {
21
+		return listener;
22
+	}
23
+
24
+	@Override
25
+	public void close() {
26
+
27
+	}
28
+}

+ 27
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/listeners/ListenerHandle.java Ver arquivo

@@ -0,0 +1,27 @@
1
+/* Licensed under GPLv3 - https://opensource.org/licenses/GPL-3.0 */
2
+package org.openzen.drawablegui.listeners;
3
+
4
+import java.io.Closeable;
5
+
6
+/**
7
+ * An EvenListenerHandle is returned when an EventListener is registered in an
8
+ * EventListenerList, which can then be used to unregister the event listener.
9
+ *
10
+ * @param <T> Event type
11
+ * @author Stan Hebben
12
+ */
13
+public interface ListenerHandle<T> extends Closeable
14
+{
15
+	/**
16
+	 * Gets this handle's listener.
17
+	 *
18
+	 * @return listener
19
+	 */
20
+	public T getListener();
21
+
22
+	/**
23
+	 * Closes (unregisters) the event listener from the list it was registered to.
24
+	 */
25
+	@Override
26
+	public void close();
27
+}

+ 165
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/listeners/ListenerList.java Ver arquivo

@@ -0,0 +1,165 @@
1
+/* Licensed under GPLv3 - https://opensource.org/licenses/GPL-3.0 */
2
+package org.openzen.drawablegui.listeners;
3
+
4
+import java.util.function.Consumer;
5
+
6
+/**
7
+ * Implements a list of event listeners. This class is thread-safe and listeners
8
+ * can be added or removed concurrently, no external locking is ever needed.
9
+ * Also, it's very lightweight.
10
+ *
11
+ * @param <T> event type
12
+ * @author Stan Hebben
13
+ */
14
+public class ListenerList<T>
15
+{
16
+    public static final int PRIORITY_HIGH = 100;
17
+    public static final int PRIORITY_DEFAULT = 0;
18
+    public static final int PRIORITY_LOW = -100;
19
+	
20
+	// implements a linked list of nodes
21
+	protected volatile EventListenerNode first = null;
22
+	protected EventListenerNode last = null;
23
+
24
+	/**
25
+	 * Adds an IEventListener to the list.
26
+	 *
27
+	 * @param listener event listener
28
+	 * @return event listener's handle
29
+	 */
30
+	public ListenerHandle<T> add(T listener)
31
+	{
32
+        return add(listener, PRIORITY_DEFAULT);
33
+    }
34
+
35
+    public ListenerHandle<T> add(T listener, int priority)
36
+	{
37
+		EventListenerNode node = new EventListenerNode(listener, priority);
38
+
39
+		synchronized (this) {
40
+			if (first == null) {
41
+				first = last = node;
42
+			} else {
43
+                // prioritized list: where to insert?
44
+                EventListenerNode previousNode = last;
45
+                while (previousNode != null && priority > previousNode.priority) {
46
+                    previousNode = previousNode.prev;
47
+                }
48
+
49
+                if (previousNode == null) {
50
+                    node.next = first;
51
+                    first.prev = previousNode;
52
+                    first = node;
53
+                } else {
54
+                    if (previousNode.next == null) {
55
+                        last = node;
56
+                    } else {
57
+                        previousNode.next.prev = node;
58
+                    }
59
+
60
+                    previousNode.next = node;
61
+                    node.prev = previousNode;
62
+                }
63
+            }
64
+		}
65
+
66
+		return node;
67
+	}
68
+
69
+	/**
70
+	 * Removes an IEventListener from the list.
71
+	 *
72
+	 * @param listener listener to be removed
73
+	 * @return true if the listener was removed, false it it wasn't there
74
+	 */
75
+	public synchronized boolean remove(T listener)
76
+	{
77
+		EventListenerNode current = first;
78
+
79
+		while (current != null) {
80
+			if (current.listener == listener) {
81
+				current.close();
82
+				return true;
83
+			}
84
+
85
+            current = current.next;
86
+		}
87
+
88
+		return false;
89
+	}
90
+	
91
+	/**
92
+	 * Clears this listener list.
93
+	 */
94
+	public synchronized void clear()
95
+	{
96
+		first = last = null;
97
+	}
98
+	
99
+	/**
100
+	 * Invokes the given consumer for every listener in the list.
101
+	 * 
102
+	 * @param consumer consumer to be called for each listener
103
+	 */
104
+	public void accept(Consumer<T> consumer)
105
+	{
106
+		EventListenerNode current = first;
107
+		
108
+		while (current != null) {
109
+			consumer.accept(current.listener);
110
+			current = current.next;
111
+		}
112
+	}
113
+
114
+	/**
115
+	 * Checks if there are any listeners in this list.
116
+	 *
117
+	 * @return true if empty
118
+	 */
119
+	public boolean isEmpty()
120
+	{
121
+		return first == null;
122
+	}
123
+
124
+	// #######################
125
+	// ### Private classes ###
126
+	// #######################
127
+
128
+	protected class EventListenerNode implements ListenerHandle<T>
129
+	{
130
+		protected final T listener;
131
+        protected final int priority;
132
+		protected EventListenerNode next = null;
133
+		protected EventListenerNode prev = null;
134
+
135
+		public EventListenerNode(T handler, int priority)
136
+		{
137
+			this.listener = handler;
138
+            this.priority = priority;
139
+		}
140
+
141
+		@Override
142
+		public T getListener()
143
+		{
144
+			return listener;
145
+		}
146
+
147
+		@Override
148
+		public void close()
149
+		{
150
+			synchronized (ListenerList.this) {
151
+				if (prev == null) {
152
+					first = next;
153
+				} else {
154
+					prev.next = next;
155
+				}
156
+
157
+				if (next == null) {
158
+					last = prev;
159
+				} else {
160
+					next.prev = prev;
161
+				}
162
+			}
163
+		}
164
+	}
165
+}

+ 39
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveBool.java Ver arquivo

@@ -0,0 +1,39 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.DummyListenerHandle;
9
+import org.openzen.drawablegui.listeners.ListenerHandle;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class ImmutableLiveBool implements LiveBool {
16
+	public static final ImmutableLiveBool TRUE = new ImmutableLiveBool(true);
17
+	public static final ImmutableLiveBool FALSE = new ImmutableLiveBool(false);
18
+	
19
+	private final boolean value;
20
+	
21
+	private ImmutableLiveBool(boolean value) {
22
+		this.value = value;
23
+	}
24
+
25
+	@Override
26
+	public boolean getValue() {
27
+		return value;
28
+	}
29
+
30
+	@Override
31
+	public void setValue(boolean value) {
32
+		throw new UnsupportedOperationException("Cannot modify an immutable value");
33
+	}
34
+
35
+	@Override
36
+	public ListenerHandle<Listener> addListener(Listener listener) {
37
+		return new DummyListenerHandle<>(listener);
38
+	}
39
+}

+ 36
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveObject.java Ver arquivo

@@ -0,0 +1,36 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.DummyListenerHandle;
9
+import org.openzen.drawablegui.listeners.ListenerHandle;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class ImmutableLiveObject<T> implements LiveObject<T> {
16
+	private final T value;
17
+	
18
+	public ImmutableLiveObject(T value) {
19
+		this.value = value;
20
+	}
21
+	
22
+	@Override
23
+	public T getValue() {
24
+		return value;
25
+	}
26
+
27
+	@Override
28
+	public void setValue(T value) {
29
+		throw new UnsupportedOperationException("Immutable value");
30
+	}
31
+
32
+	@Override
33
+	public ListenerHandle<Listener<T>> addListener(Listener<T> listener) {
34
+		return new DummyListenerHandle<>(listener);
35
+	}
36
+}

+ 80
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveArrayList.java Ver arquivo

@@ -0,0 +1,80 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import java.util.ArrayList;
9
+import java.util.Iterator;
10
+import java.util.List;
11
+import org.openzen.drawablegui.listeners.ListenerHandle;
12
+import org.openzen.drawablegui.listeners.ListenerList;
13
+
14
+/**
15
+ *
16
+ * @author Hoofdgebruiker
17
+ */
18
+public class LiveArrayList<T> implements LiveList<T> {
19
+	private final List<T> values = new ArrayList<>();
20
+	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
21
+
22
+	@Override
23
+	public void add(T value) {
24
+		int index = values.size();
25
+		values.add(value);
26
+		listeners.accept(listener -> listener.onInserted(index, value));
27
+	}
28
+
29
+	@Override
30
+	public void add(int index, T value) {
31
+		values.add(index, value);
32
+		listeners.accept(listener -> listener.onInserted(index, value));
33
+	}
34
+
35
+	@Override
36
+	public void set(int index, T value) {
37
+		T oldValue = values.set(index, value);
38
+		listeners.accept(listener -> listener.onChanged(index, oldValue, value));
39
+	}
40
+
41
+	@Override
42
+	public void remove(int index) {
43
+		T oldValue = values.remove(index);
44
+		listeners.accept(listener -> listener.onRemoved(index, oldValue));
45
+	}
46
+
47
+	@Override
48
+	public void remove(T value) {
49
+		int index = indexOf(value);
50
+		if (index < 0)
51
+			return;
52
+		
53
+		remove(index);
54
+	}
55
+
56
+	@Override
57
+	public int indexOf(T value) {
58
+		return values.indexOf(value);
59
+	}
60
+	
61
+	@Override
62
+	public int size() {
63
+		return values.size();
64
+	}
65
+
66
+	@Override
67
+	public T get(int index) {
68
+		return values.get(index);
69
+	}
70
+
71
+	@Override
72
+	public Iterator<T> iterator() {
73
+		return values.iterator();
74
+	}
75
+
76
+	@Override
77
+	public ListenerHandle<Listener<T>> addListener(Listener<T> listener) {
78
+		return listeners.add(listener);
79
+	}
80
+}

+ 28
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveBool.java Ver arquivo

@@ -0,0 +1,28 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.ListenerHandle;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface LiveBool {
15
+	public boolean getValue();
16
+	
17
+	public void setValue(boolean value);
18
+	
19
+	default void toggle() {
20
+		setValue(!getValue());
21
+	}
22
+	
23
+	public ListenerHandle<Listener> addListener(Listener listener);
24
+	
25
+	public interface Listener {
26
+		void onChanged(boolean oldValue, boolean newValue);
27
+	}
28
+}

+ 155
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveConcatList.java Ver arquivo

@@ -0,0 +1,155 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import java.io.Closeable;
9
+import java.util.Iterator;
10
+import org.openzen.drawablegui.listeners.ListenerHandle;
11
+import org.openzen.drawablegui.listeners.ListenerList;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class LiveConcatList<T> implements Closeable, LiveList<T> {
18
+	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
19
+	private final LiveList<T> a;
20
+	private final LiveList<T> b;
21
+	
22
+	private final ListenerHandle<Listener<T>> aListener;
23
+	private final ListenerHandle<Listener<T>> bListener;
24
+	
25
+	public LiveConcatList(LiveList<T> a, LiveList<T> b) {
26
+		this.a = a;
27
+		this.b = b;
28
+		
29
+		aListener = a.addListener(new FirstListListener());
30
+		bListener = b.addListener(new SecondListListener());
31
+	}
32
+	
33
+	@Override
34
+	public void close() {
35
+		aListener.close();
36
+		bListener.close();
37
+	}
38
+
39
+	@Override
40
+	public void add(T value) {
41
+		throw new UnsupportedOperationException("Cannot modify a concat list");
42
+	}
43
+
44
+	@Override
45
+	public void add(int index, T value) {
46
+		throw new UnsupportedOperationException("Cannot modify a concat list");
47
+	}
48
+
49
+	@Override
50
+	public void set(int index, T value) {
51
+		throw new UnsupportedOperationException("Cannot modify a concat list");
52
+	}
53
+
54
+	@Override
55
+	public void remove(int index) {
56
+		throw new UnsupportedOperationException("Cannot modify a concat list");
57
+	}
58
+
59
+	@Override
60
+	public void remove(T value) {
61
+		throw new UnsupportedOperationException("Cannot modify a concat list");
62
+	}
63
+
64
+	@Override
65
+	public int indexOf(T value) {
66
+		int result = a.indexOf(value);
67
+		if (result >= 0)
68
+			return result;
69
+		
70
+		result = b.indexOf(value);
71
+		return result < 0 ? -1 : result + a.size();
72
+	}
73
+
74
+	@Override
75
+	public int size() {
76
+		return a.size() + b.size();
77
+	}
78
+
79
+	@Override
80
+	public T get(int index) {
81
+		return index < a.size() ? a.get(index) : b.get(index - a.size());
82
+	}
83
+
84
+	@Override
85
+	public Iterator<T> iterator() {
86
+		return new ConcatIterator();
87
+	}
88
+
89
+	@Override
90
+	public ListenerHandle<Listener<T>> addListener(Listener<T> listener) {
91
+		return listeners.add(listener);
92
+	}
93
+	
94
+	private class ConcatIterator implements Iterator<T> {
95
+		private boolean firstList = true;
96
+		private Iterator<T> iterator;
97
+
98
+		public ConcatIterator() {
99
+			iterator = a.iterator();
100
+			if (!iterator.hasNext()) {
101
+				firstList = false;
102
+				iterator = b.iterator();
103
+			}
104
+		}
105
+		
106
+		@Override
107
+		public boolean hasNext() {
108
+			return iterator.hasNext();
109
+		}
110
+
111
+		@Override
112
+		public T next() {
113
+			T result = iterator.next();
114
+			if (firstList && !iterator.hasNext()) {
115
+				firstList = false;
116
+				iterator = b.iterator();
117
+			}
118
+			return result;
119
+		}
120
+	}
121
+	
122
+	private class FirstListListener implements Listener<T> {
123
+		@Override
124
+		public void onInserted(int index, T value) {
125
+			listeners.accept(listener -> listener.onInserted(index, value));
126
+		}
127
+
128
+		@Override
129
+		public void onChanged(int index, T oldValue, T newValue) {
130
+			listeners.accept(listener -> listener.onChanged(index, oldValue, newValue));
131
+		}
132
+
133
+		@Override
134
+		public void onRemoved(int index, T oldValue) {
135
+			listeners.accept(listener -> listener.onRemoved(index, oldValue));
136
+		}
137
+	}
138
+	
139
+	private class SecondListListener implements Listener<T> {
140
+		@Override
141
+		public void onInserted(int index, T value) {
142
+			listeners.accept(listener -> listener.onInserted(a.size() + index, value));
143
+		}
144
+
145
+		@Override
146
+		public void onChanged(int index, T oldValue, T newValue) {
147
+			listeners.accept(listener -> listener.onChanged(a.size() + index, oldValue, newValue));
148
+		}
149
+
150
+		@Override
151
+		public void onRemoved(int index, T oldValue) {
152
+			listeners.accept(listener -> listener.onRemoved(a.size() + index, oldValue));
153
+		}
154
+	}
155
+}

+ 73
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveEmptyList.java Ver arquivo

@@ -0,0 +1,73 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import java.util.Collections;
9
+import java.util.Iterator;
10
+import org.openzen.drawablegui.listeners.DummyListenerHandle;
11
+import org.openzen.drawablegui.listeners.ListenerHandle;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class LiveEmptyList<T> implements LiveList<T> {
18
+	private static final LiveEmptyList INSTANCE = new LiveEmptyList();
19
+	
20
+	public static <T> LiveEmptyList<T> get() {
21
+		return INSTANCE;
22
+	}
23
+
24
+	@Override
25
+	public void add(T value) {
26
+		throw new UnsupportedOperationException("Immutable list");
27
+	}
28
+
29
+	@Override
30
+	public void add(int index, T value) {
31
+		throw new UnsupportedOperationException("Immutable list");
32
+	}
33
+
34
+	@Override
35
+	public void set(int index, T value) {
36
+		throw new UnsupportedOperationException("Immutable list");
37
+	}
38
+
39
+	@Override
40
+	public void remove(int index) {
41
+		throw new UnsupportedOperationException("Immutable list");
42
+	}
43
+
44
+	@Override
45
+	public void remove(T value) {
46
+		throw new UnsupportedOperationException("Immutable list");
47
+	}
48
+
49
+	@Override
50
+	public int indexOf(T value) {
51
+		return -1;
52
+	}
53
+	
54
+	@Override
55
+	public int size() {
56
+		return 0;
57
+	}
58
+	
59
+	@Override
60
+	public T get(int index) {
61
+		throw new ArrayIndexOutOfBoundsException(index);
62
+	}
63
+
64
+	@Override
65
+	public Iterator<T> iterator() {
66
+		return Collections.emptyIterator();
67
+	}
68
+
69
+	@Override
70
+	public ListenerHandle<Listener<T>> addListener(Listener<T> listener) {
71
+		return new DummyListenerHandle<>(listener);
72
+	}
73
+}

+ 24
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveInt.java Ver arquivo

@@ -0,0 +1,24 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.ListenerHandle;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface LiveInt {
15
+	int getValue();
16
+	
17
+	void setValue(int value);
18
+	
19
+	ListenerHandle<Listener> addListener(Listener listener);
20
+	
21
+	interface Listener {
22
+		void onChanged(int oldValue, int newValue);
23
+	}
24
+}

+ 44
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveList.java Ver arquivo

@@ -0,0 +1,44 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import java.util.Iterator;
9
+import org.openzen.drawablegui.listeners.ListenerHandle;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface LiveList<T> extends Iterable<T> {
16
+	void add(T value);
17
+	
18
+	void add(int index, T value);
19
+	
20
+	void set(int index, T value);
21
+	
22
+	void remove(int index);
23
+	
24
+	void remove(T value);
25
+	
26
+	int indexOf(T value);
27
+	
28
+	int size();
29
+	
30
+	T get(int index);
31
+	
32
+	@Override
33
+	Iterator<T> iterator();
34
+	
35
+	ListenerHandle<Listener<T>> addListener(Listener<T> listener);
36
+	
37
+	interface Listener<T> {
38
+		void onInserted(int index, T value);
39
+		
40
+		void onChanged(int index, T oldValue, T newValue);
41
+		
42
+		void onRemoved(int index, T oldValue);
43
+	}
44
+}

+ 111
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveMappedList.java Ver arquivo

@@ -0,0 +1,111 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import java.io.Closeable;
9
+import java.util.ArrayList;
10
+import java.util.Iterator;
11
+import java.util.List;
12
+import java.util.function.Function;
13
+import org.openzen.drawablegui.listeners.ListenerHandle;
14
+import org.openzen.drawablegui.listeners.ListenerList;
15
+
16
+/**
17
+ *
18
+ * @author Hoofdgebruiker
19
+ */
20
+public class LiveMappedList<T, U> implements Closeable, LiveList<U> {
21
+	private final ListenerList<Listener<U>> listeners = new ListenerList<>();
22
+	private final Function<T, U> projection;
23
+	private final List<U> mapped;
24
+	private final ListenerHandle<Listener<T>> mappingListenerHandle;
25
+	
26
+	public LiveMappedList(LiveList<T> original, Function<T, U> projection) {
27
+		this.projection = projection;
28
+		mappingListenerHandle = original.addListener(new MappingListener());
29
+		
30
+		mapped = new ArrayList<>();
31
+		for (T originalItem : original)
32
+			mapped.add(projection.apply(originalItem));
33
+	}
34
+	
35
+	@Override
36
+	public void close() {
37
+		mappingListenerHandle.close();
38
+	}
39
+
40
+	@Override
41
+	public void add(U value) {
42
+		throw new UnsupportedOperationException("Cannot modify a mapped list");
43
+	}
44
+
45
+	@Override
46
+	public void add(int index, U value) {
47
+		throw new UnsupportedOperationException("Cannot modify a mapped list");
48
+	}
49
+
50
+	@Override
51
+	public void set(int index, U value) {
52
+		throw new UnsupportedOperationException("Cannot modify a mapped list");
53
+	}
54
+
55
+	@Override
56
+	public void remove(int index) {
57
+		throw new UnsupportedOperationException("Cannot modify a mapped list");
58
+	}
59
+
60
+	@Override
61
+	public void remove(U value) {
62
+		throw new UnsupportedOperationException("Cannot modify a mapped list");
63
+	}
64
+
65
+	@Override
66
+	public int indexOf(U value) {
67
+		return mapped.indexOf(value);
68
+	}
69
+	
70
+	@Override
71
+	public int size() {
72
+		return mapped.size();
73
+	}
74
+
75
+	@Override
76
+	public U get(int index) {
77
+		return mapped.get(index);
78
+	}
79
+
80
+	@Override
81
+	public Iterator<U> iterator() {
82
+		return mapped.iterator();
83
+	}
84
+
85
+	@Override
86
+	public ListenerHandle<Listener<U>> addListener(Listener<U> listener) {
87
+		return listeners.add(listener);
88
+	}
89
+	
90
+	private class MappingListener implements Listener<T> {
91
+		@Override
92
+		public void onInserted(int index, T value) {
93
+			U mappedValue = projection.apply(value);
94
+			mapped.add(index, mappedValue);
95
+			listeners.accept(listener -> listener.onInserted(index, mappedValue));
96
+		}
97
+
98
+		@Override
99
+		public void onChanged(int index, T oldValue, T newValue) {
100
+			U mappedNewValue = projection.apply(newValue);
101
+			U mappedOldValue = mapped.set(index, mappedNewValue);
102
+			listeners.accept(listener -> listener.onChanged(index, mappedOldValue, mappedNewValue));
103
+		}
104
+
105
+		@Override
106
+		public void onRemoved(int index, T oldValue) {
107
+			U oldMappedValue = mapped.remove(index);
108
+			listeners.accept(listener -> listener.onRemoved(index, oldMappedValue));
109
+		}
110
+	}
111
+}

+ 24
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveObject.java Ver arquivo

@@ -0,0 +1,24 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.ListenerHandle;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface LiveObject<T> {
15
+	public T getValue();
16
+	
17
+	public void setValue(T value);
18
+	
19
+	public ListenerHandle<Listener<T>> addListener(Listener<T> listener);
20
+	
21
+	public interface Listener<T> {
22
+		void onUpdated(T oldValue, T newValue);
23
+	}
24
+}

+ 64
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePredicateBool.java Ver arquivo

@@ -0,0 +1,64 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import java.io.Closeable;
9
+import java.util.function.Predicate;
10
+import org.openzen.drawablegui.listeners.ListenerHandle;
11
+import org.openzen.drawablegui.listeners.ListenerList;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class LivePredicateBool<T> implements LiveBool, Closeable, LiveObject.Listener<T> {
18
+	private final ListenerList<LiveBool.Listener> listeners = new ListenerList<>();
19
+	private final LiveObject<T> source;
20
+	private final Predicate<T> predicate;
21
+	private final ListenerHandle<LiveObject.Listener<T>> sourceListener;
22
+	private boolean value;
23
+	
24
+	public LivePredicateBool(LiveObject<T> source, Predicate<T> predicate) {
25
+		this.source = source;
26
+		this.predicate = predicate;
27
+		this.sourceListener = source.addListener(this);
28
+		setValueInternal(predicate.test(source.getValue()));
29
+	}
30
+	
31
+	@Override
32
+	public void close() {
33
+		sourceListener.close();
34
+	}
35
+	
36
+	@Override
37
+	public void setValue(boolean value) {
38
+		throw new UnsupportedOperationException("Cannot modify a calculated value");
39
+	}
40
+
41
+	@Override
42
+	public boolean getValue() {
43
+		return value;
44
+	}
45
+
46
+	@Override
47
+	public ListenerHandle<Listener> addListener(Listener listener) {
48
+		return listeners.add(listener);
49
+	}
50
+	
51
+	private void setValueInternal(boolean value) {
52
+		if (value == this.value)
53
+			return;
54
+		
55
+		boolean oldValue = this.value;
56
+		this.value = value;
57
+		listeners.accept(listener -> listener.onChanged(oldValue, value));
58
+	}
59
+
60
+	@Override
61
+	public void onUpdated(T oldValue, T newValue) {
62
+		setValueInternal(predicate.test(newValue));
63
+	}
64
+}

+ 124
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePrefixedList.java Ver arquivo

@@ -0,0 +1,124 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import java.util.Iterator;
9
+import org.openzen.drawablegui.listeners.ListenerHandle;
10
+import org.openzen.drawablegui.listeners.ListenerList;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class LivePrefixedList<T> implements LiveList<T> {
17
+	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
18
+	private final T prefix;
19
+	private final LiveList<T> values;
20
+	
21
+	public LivePrefixedList(T prefix, LiveList<T> values) {
22
+		this.prefix = prefix;
23
+		this.values = values;
24
+	}
25
+
26
+	@Override
27
+	public void add(T value) {
28
+		values.add(value);
29
+	}
30
+
31
+	@Override
32
+	public void add(int index, T value) {
33
+		if (index == 0)
34
+			throw new UnsupportedOperationException("Cannot add an item at the beginning of a prefixed list");
35
+		values.add(index - 1, value);
36
+	}
37
+
38
+	@Override
39
+	public void set(int index, T value) {
40
+		if (index == 0)
41
+			throw new UnsupportedOperationException("Cannot change the item at the beginning of a prefixed list");
42
+		
43
+		values.set(index - 1, value);
44
+	}
45
+
46
+	@Override
47
+	public void remove(int index) {
48
+		if (index == 0)
49
+			throw new UnsupportedOperationException("Cannot remote the item at the beginning of a prefixed list");
50
+		
51
+		values.remove(index - 1);
52
+	}
53
+
54
+	@Override
55
+	public void remove(T value) {
56
+		values.remove(value);
57
+	}
58
+
59
+	@Override
60
+	public int indexOf(T value) {
61
+		if (value.equals(prefix))
62
+			return 0;
63
+		
64
+		int base = values.indexOf(value);
65
+		return base < 0 ? base : base - 1;
66
+	}
67
+
68
+	@Override
69
+	public int size() {
70
+		return values.size() + 1;
71
+	}
72
+	
73
+	@Override
74
+	public T get(int index) {
75
+		return index == 0 ? prefix : values.get(index);
76
+	}
77
+
78
+	@Override
79
+	public Iterator<T> iterator() {
80
+		return new PrefixIterator();
81
+	}
82
+
83
+	@Override
84
+	public ListenerHandle<Listener<T>> addListener(Listener<T> listener) {
85
+		return listeners.add(listener);
86
+	}
87
+	
88
+	private class PrefixIterator implements Iterator<T> {
89
+		private boolean first = true;
90
+		private Iterator<T> others = values.iterator();
91
+
92
+		@Override
93
+		public boolean hasNext() {
94
+			return first || others.hasNext();
95
+		}
96
+
97
+		@Override
98
+		public T next() {
99
+			if (first) {
100
+				first = false;
101
+				return prefix;
102
+			} else {
103
+				return others.next();
104
+			}
105
+		}
106
+	}
107
+	
108
+	private class BaseListener implements Listener<T> {
109
+		@Override
110
+		public void onInserted(int index, T value) {
111
+			listeners.accept(listener -> listener.onInserted(index + 1, value));
112
+		}
113
+
114
+		@Override
115
+		public void onChanged(int index, T oldValue, T newValue) {
116
+			listeners.accept(listener -> listener.onChanged(index + 1, oldValue, newValue));
117
+		}
118
+
119
+		@Override
120
+		public void onRemoved(int index, T oldValue) {
121
+			listeners.accept(listener -> listener.onRemoved(index + 1, oldValue));
122
+		}
123
+	}
124
+}

+ 46
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveBool.java Ver arquivo

@@ -0,0 +1,46 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.ListenerHandle;
9
+import org.openzen.drawablegui.listeners.ListenerList;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class SimpleLiveBool implements LiveBool {
16
+	private final ListenerList<LiveBool.Listener> listeners = new ListenerList<>();
17
+	private boolean value;
18
+	
19
+	public SimpleLiveBool() {
20
+		this(false);
21
+	}
22
+	
23
+	public SimpleLiveBool(boolean value) {
24
+		this.value = value;
25
+	}
26
+	
27
+	@Override
28
+	public boolean getValue() {
29
+		return value;
30
+	}
31
+	
32
+	@Override
33
+	public void setValue(boolean value) {
34
+		if (value == this.value)
35
+			return;
36
+		
37
+		boolean oldValue = this.value;
38
+		this.value = value;
39
+		listeners.accept(listener -> listener.onChanged(oldValue, value));
40
+	}
41
+	
42
+	@Override
43
+	public ListenerHandle<LiveBool.Listener> addListener(LiveBool.Listener listener) {
44
+		return listeners.add(listener);
45
+	}
46
+}

+ 35
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveInt.java Ver arquivo

@@ -0,0 +1,35 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.ListenerHandle;
9
+import org.openzen.drawablegui.listeners.ListenerList;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class SimpleLiveInt implements LiveInt {
16
+	private final ListenerList<Listener> listeners = new ListenerList<>();
17
+	private int value = 0;
18
+
19
+	@Override
20
+	public int getValue() {
21
+		return value;
22
+	}
23
+
24
+	@Override
25
+	public void setValue(int value) {
26
+		int oldValue = this.value;
27
+		this.value = value;
28
+		listeners.accept(listener -> listener.onChanged(oldValue, value));
29
+	}
30
+
31
+	@Override
32
+	public ListenerHandle<Listener> addListener(Listener listener) {
33
+		return listeners.add(listener);
34
+	}
35
+}

+ 39
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveObject.java Ver arquivo

@@ -0,0 +1,39 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+import org.openzen.drawablegui.listeners.ListenerHandle;
9
+import org.openzen.drawablegui.listeners.ListenerList;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class SimpleLiveObject<T> implements LiveObject<T> {
16
+	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
17
+	private T value;
18
+	
19
+	public SimpleLiveObject(T value) {
20
+		this.value = value;
21
+	}
22
+	
23
+	@Override
24
+	public T getValue() {
25
+		return value;
26
+	}
27
+	
28
+	@Override
29
+	public void setValue(T value) {
30
+		T oldValue = this.value;
31
+		this.value = value;
32
+		listeners.accept(listener -> listener.onUpdated(oldValue, value));
33
+	}
34
+	
35
+	@Override
36
+	public ListenerHandle<Listener<T>> addListener(Listener<T> listener) {
37
+		return listeners.add(listener);
38
+	}
39
+}

+ 173
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java Ver arquivo

@@ -0,0 +1,173 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.scroll;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DComponent;
10
+import org.openzen.drawablegui.DDimensionPreferences;
11
+import org.openzen.drawablegui.DMouseEvent;
12
+import org.openzen.drawablegui.DIRectangle;
13
+import org.openzen.drawablegui.listeners.ListenerHandle;
14
+import org.openzen.drawablegui.live.LiveInt;
15
+import org.openzen.drawablegui.live.LiveObject;
16
+import org.openzen.drawablegui.live.SimpleLiveObject;
17
+import org.openzen.drawablegui.DUIContext;
18
+import org.openzen.drawablegui.style.DStyleClass;
19
+import org.openzen.drawablegui.style.DStylePath;
20
+
21
+/**
22
+ *
23
+ * @author Hoofdgebruiker
24
+ */
25
+public class DScrollBar implements DComponent {
26
+	private final LiveObject<DDimensionPreferences> preferences;
27
+	
28
+	private final DStyleClass styleClass;
29
+	private final LiveInt targetHeight;
30
+	private final LiveInt offset;
31
+	
32
+	private final ListenerHandle<LiveInt.Listener> targetHeightListener;
33
+	private final ListenerHandle<LiveInt.Listener> offsetListener;
34
+	
35
+	private DUIContext context;
36
+	private DScrollBarStyle style;
37
+	private DIRectangle bounds;
38
+	
39
+	private int fromY = 0;
40
+	private int toY = 0;
41
+	private boolean hovering = false;
42
+	private boolean dragging = false;
43
+	private int dragStartOffset;
44
+	private int dragStartY;
45
+	
46
+	public DScrollBar(DStyleClass styleClass, LiveInt targetHeight, LiveInt offset) {
47
+		this.styleClass = styleClass;
48
+		this.targetHeight = targetHeight;
49
+		this.offset = offset;
50
+		this.preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
51
+		
52
+		targetHeightListener = targetHeight.addListener(new ScrollListener());
53
+		offsetListener = offset.addListener(new ScrollListener());
54
+	}
55
+
56
+	@Override
57
+	public void setContext(DStylePath parent, DUIContext context) {
58
+		this.context = context;
59
+		this.style = new DScrollBarStyle(context.getStylesheets().get(context, parent.getChild("scrollbar", styleClass)));
60
+		preferences.setValue(new DDimensionPreferences(style.width, 0));
61
+	}
62
+
63
+	@Override
64
+	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
65
+		return preferences;
66
+	}
67
+
68
+	@Override
69
+	public DIRectangle getBounds() {
70
+		return bounds;
71
+	}
72
+
73
+	@Override
74
+	public void setBounds(DIRectangle bounds) {
75
+		this.bounds = bounds;
76
+		recalculate();
77
+	}
78
+
79
+	@Override
80
+	public void paint(DCanvas canvas) {
81
+		if (targetHeight.getValue() <= this.bounds.height)
82
+			return; // no scrollbar
83
+		
84
+		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.scrollBarBackgroundColor);
85
+		
86
+		int color = style.scrollBarNormalColor;
87
+		if (hovering)
88
+			color = style.scrollBarHoverColor;
89
+		if (dragging)
90
+			color = style.scrollBarPressColor;
91
+		
92
+		canvas.fillRectangle(bounds.x, fromY, this.bounds.width, toY - fromY, color);
93
+	}
94
+	
95
+	@Override
96
+	public void onMouseEnter(DMouseEvent e) {
97
+		checkHover(e);
98
+	}
99
+	
100
+	@Override
101
+	public void onMouseExit(DMouseEvent e) {
102
+		setHovering(false);
103
+		setDragging(false);
104
+	}
105
+	
106
+	@Override
107
+	public void onMouseMove(DMouseEvent e) {
108
+		checkHover(e);
109
+	}
110
+	
111
+	@Override
112
+	public void onMouseDrag(DMouseEvent e) {
113
+		if (dragging) {
114
+			int deltaY = e.y - dragStartY;
115
+			int offsetForDelta = deltaY * targetHeight.getValue() / this.bounds.height;
116
+			offset.setValue(dragStartOffset + offsetForDelta);
117
+		}
118
+	}
119
+	
120
+	@Override
121
+	public void onMouseDown(DMouseEvent e) {
122
+		if (e.y >= fromY && e.y < toY) {
123
+			dragStartOffset = offset.getValue();
124
+			dragStartY = e.y;
125
+			setDragging(true);
126
+		}
127
+	}
128
+	
129
+	@Override
130
+	public void onMouseRelease(DMouseEvent e) {
131
+		setDragging(false);
132
+	}
133
+
134
+	@Override
135
+	public void close() {
136
+		// nothing to clean up
137
+	}
138
+	
139
+	private void checkHover(DMouseEvent e) {
140
+		setHovering(e.y >= fromY && e.y < toY);
141
+	}
142
+	
143
+	private void setHovering(boolean hovering) {
144
+		if (hovering == this.hovering)
145
+			return;
146
+		
147
+		this.hovering = hovering;
148
+		context.repaint(bounds.x, fromY, bounds.width, toY - fromY);
149
+	}
150
+	
151
+	private void setDragging(boolean dragging) {
152
+		if (dragging == this.dragging)
153
+			return;
154
+		
155
+		this.dragging = dragging;
156
+		context.repaint(bounds.x, fromY, bounds.width, toY - fromY);
157
+	}
158
+	
159
+	private void recalculate() {
160
+		if (targetHeight.getValue() == 0 || bounds == null)
161
+			return;
162
+		
163
+		fromY = bounds.y + this.bounds.height * offset.getValue() / targetHeight.getValue();
164
+		toY = bounds.y + this.bounds.height * (offset.getValue() + this.bounds.height) / targetHeight.getValue();
165
+	}
166
+	
167
+	private class ScrollListener implements LiveInt.Listener {
168
+		@Override
169
+		public void onChanged(int oldValue, int newValue) {
170
+			recalculate();
171
+		}
172
+	}
173
+}

+ 31
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBarStyle.java Ver arquivo

@@ -0,0 +1,31 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.scroll;
7
+
8
+import org.openzen.drawablegui.style.DDimension;
9
+import org.openzen.drawablegui.style.DDpDimension;
10
+import org.openzen.drawablegui.DUIContext;
11
+import org.openzen.drawablegui.style.DStyleDefinition;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class DScrollBarStyle {
18
+	public final int scrollBarBackgroundColor;
19
+	public final int scrollBarNormalColor;
20
+	public final int scrollBarHoverColor;
21
+	public final int scrollBarPressColor;
22
+	public final int width;
23
+	
24
+	public DScrollBarStyle(DStyleDefinition style) {
25
+		this.scrollBarBackgroundColor = style.getColor("scrollbar.background.color", 0xFFF0F0F0);
26
+		this.scrollBarNormalColor = style.getColor("scrollbar.color.normal", 0xFFCDCDCD);
27
+		this.scrollBarHoverColor = style.getColor("scrollbar.color.hover", 0xFF888888);
28
+		this.scrollBarPressColor = style.getColor("scrollbar.color.press", 0xFF666666);
29
+		this.width = style.getDimension("width", new DDpDimension(12));
30
+	}
31
+}

+ 320
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java Ver arquivo

@@ -0,0 +1,320 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.scroll;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DClipboard;
10
+import org.openzen.drawablegui.DComponent;
11
+import org.openzen.drawablegui.DDimensionPreferences;
12
+import org.openzen.drawablegui.DFont;
13
+import org.openzen.drawablegui.DFontMetrics;
14
+import org.openzen.drawablegui.DIRectangle;
15
+import org.openzen.drawablegui.DMouseEvent;
16
+import org.openzen.drawablegui.DTimerHandle;
17
+import org.openzen.drawablegui.listeners.ListenerHandle;
18
+import org.openzen.drawablegui.live.LiveInt;
19
+import org.openzen.drawablegui.live.LiveObject;
20
+import org.openzen.drawablegui.live.SimpleLiveInt;
21
+import org.openzen.drawablegui.DUIContext;
22
+import org.openzen.drawablegui.DUIWindow;
23
+import org.openzen.drawablegui.style.DStyleClass;
24
+import org.openzen.drawablegui.style.DStylePath;
25
+import org.openzen.drawablegui.style.DStyleSheets;
26
+
27
+/**
28
+ *
29
+ * @author Hoofdgebruiker
30
+ */
31
+public class DScrollPane implements DComponent {
32
+	private final DStyleClass styleClass;
33
+	private final DComponent contents;
34
+	private final DScrollBar scrollBar;
35
+	private DUIContext context;
36
+	private DIRectangle bounds;
37
+	
38
+	private DScrollPaneStyle style;
39
+	private final LiveInt contentsHeight;
40
+	private final LiveInt offsetX;
41
+	private final LiveInt offsetY;
42
+	
43
+	private final ListenerHandle<LiveInt.Listener> contentsHeightListener;
44
+	private final ListenerHandle<LiveInt.Listener> offsetXListener;
45
+	private final ListenerHandle<LiveInt.Listener> offsetYListener;
46
+	
47
+	private DComponent hovering = null;
48
+	
49
+	public DScrollPane(DStyleClass styleClass, DComponent contents) {
50
+		this.styleClass = styleClass;
51
+		this.contents = contents;
52
+		
53
+		contentsHeight = new SimpleLiveInt();
54
+		offsetX = new SimpleLiveInt();
55
+		offsetY = new SimpleLiveInt();
56
+		
57
+		scrollBar = new DScrollBar(DStyleClass.EMPTY, contentsHeight, offsetY);
58
+		
59
+		contentsHeightListener = contentsHeight.addListener(new ScrollListener());
60
+		offsetXListener = offsetX.addListener(new ScrollListener());
61
+		offsetYListener = offsetY.addListener(new ScrollListener());
62
+		
63
+		contents.getDimensionPreferences().addListener((oldPreferences, newPreferences) -> {
64
+			if (bounds == null)
65
+				return;
66
+			
67
+			contents.setBounds(new DIRectangle(0, 0, bounds.width, Math.max(bounds.height, newPreferences.preferredHeight)));
68
+			contentsHeight.setValue(newPreferences.preferredHeight);
69
+		});
70
+	}
71
+	
72
+	@Override
73
+	public void onMounted() {
74
+		contents.onMounted();
75
+	}
76
+	
77
+	@Override
78
+	public void onUnmounted() {
79
+		contents.onUnmounted();
80
+	}
81
+
82
+	@Override
83
+	public void setContext(DStylePath parent, DUIContext context) {
84
+		this.context = context;
85
+		
86
+		DStylePath path = parent.getChild("scrollpane", styleClass);
87
+		contents.setContext(path, new TranslatedContext());
88
+		scrollBar.setContext(path, context);
89
+		style = new DScrollPaneStyle(context.getStylesheets().get(context, path));
90
+		
91
+		if (bounds != null)
92
+			setBounds(bounds);
93
+	}
94
+
95
+	@Override
96
+	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
97
+		return contents.getDimensionPreferences(); // TODO: derived preferences
98
+	}
99
+
100
+	@Override
101
+	public DIRectangle getBounds() {
102
+		return bounds;
103
+	}
104
+
105
+	@Override
106
+	public void setBounds(DIRectangle bounds) {
107
+		this.bounds = bounds;
108
+		
109
+		if (this.context == null)
110
+			return;
111
+		
112
+		int height = Math.max(
113
+				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom(),
114
+				contents.getDimensionPreferences().getValue().preferredHeight);
115
+		int scrollBarWidth = scrollBar.getDimensionPreferences().getValue().preferredWidth;
116
+		scrollBar.setBounds(new DIRectangle(
117
+				bounds.x + bounds.width - scrollBarWidth - style.border.getPaddingRight(),
118
+				bounds.y + style.border.getPaddingTop(),
119
+				scrollBarWidth,
120
+				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom()));
121
+		contents.setBounds(new DIRectangle(0, 0, bounds.width - scrollBar.getBounds().width, height));
122
+		contentsHeight.setValue(height);
123
+	}
124
+
125
+	@Override
126
+	public void paint(DCanvas canvas) {
127
+		if (bounds == null)
128
+			return;
129
+		
130
+		style.border.paint(canvas, bounds);
131
+		scrollBar.paint(canvas);
132
+		
133
+		canvas.pushBounds(new DIRectangle(
134
+				bounds.x + style.border.getPaddingLeft(),
135
+				bounds.y + style.border.getPaddingTop(),
136
+				bounds.width - style.border.getPaddingLeft() - style.border.getPaddingTop() - scrollBar.getBounds().width,
137
+				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom()));
138
+		canvas.pushOffset(bounds.x - offsetX.getValue(), bounds.y - offsetY.getValue());
139
+		contents.paint(canvas);
140
+		canvas.popOffset();
141
+		canvas.popBounds();
142
+	}
143
+	
144
+	@Override
145
+	public void onMouseScroll(DMouseEvent e) {
146
+		offsetY.setValue(offsetY.getValue() + e.deltaZ * 50);
147
+	}
148
+	
149
+	@Override
150
+	public void onMouseEnter(DMouseEvent e) {
151
+		if (e.x >= scrollBar.getBounds().x) {
152
+			setHovering(scrollBar, e);
153
+		} else {
154
+			setHovering(contents, e);
155
+		}
156
+	}
157
+	
158
+	@Override
159
+	public void onMouseExit(DMouseEvent e) {
160
+		setHovering(null, e);
161
+	}
162
+	
163
+	@Override
164
+	public void onMouseMove(DMouseEvent e) {
165
+		if (e.x >= scrollBar.getBounds().x) {
166
+			if (hovering != scrollBar) {
167
+				setHovering(scrollBar, e);
168
+			} else {
169
+				scrollBar.onMouseMove(e);
170
+			}
171
+		} else {
172
+			if (hovering != contents) {
173
+				setHovering(contents, e);
174
+			} else {
175
+				contents.onMouseMove(translateMouseEvent(e));
176
+			}
177
+		}
178
+	}
179
+	
180
+	@Override
181
+	public void onMouseDrag(DMouseEvent e) {
182
+		if (hovering != null)
183
+			hovering.onMouseDrag(forward(hovering, e));
184
+	}
185
+	
186
+	@Override
187
+	public void onMouseClick(DMouseEvent e) {
188
+		if (hovering != null)
189
+			hovering.onMouseClick(forward(hovering, e));
190
+	}
191
+	
192
+	@Override
193
+	public void onMouseDown(DMouseEvent e) {
194
+		if (hovering != null)
195
+			hovering.onMouseDown(forward(hovering, e));
196
+	}
197
+	
198
+	@Override
199
+	public void onMouseRelease(DMouseEvent e) {
200
+		if (hovering != null)
201
+			hovering.onMouseRelease(forward(hovering, e));
202
+		
203
+		onMouseMove(e);
204
+	}
205
+
206
+	@Override
207
+	public void close() {
208
+		contents.close();
209
+	}
210
+	
211
+	private DMouseEvent forward(DComponent target, DMouseEvent e) {
212
+		return target == contents ? translateMouseEvent(e) : e;
213
+	}
214
+	
215
+	private void setHovering(DComponent target, DMouseEvent e) {
216
+		if (target == hovering)
217
+			return;
218
+		
219
+		if (hovering != null)
220
+			hovering.onMouseExit(forward(hovering, e));
221
+		this.hovering = target;
222
+		if (hovering != null)
223
+			hovering.onMouseEnter(forward(hovering, e));
224
+	}
225
+	
226
+	private DMouseEvent translateMouseEvent(DMouseEvent e) {
227
+		return new DMouseEvent(
228
+				e.x - bounds.x + offsetX.getValue(),
229
+				e.y - bounds.y + offsetY.getValue(),
230
+				e.modifiers,
231
+				e.deltaZ,
232
+				e.clickCount);
233
+	}
234
+	
235
+	private class TranslatedContext implements DUIContext {
236
+		
237
+		@Override
238
+		public DStyleSheets getStylesheets(){
239
+			return context.getStylesheets();
240
+		}
241
+
242
+		@Override
243
+		public float getScale() {
244
+			return context.getScale();
245
+		}
246
+
247
+		@Override
248
+		public void repaint(int x, int y, int width, int height) {
249
+			int left = x + bounds.x - offsetX.getValue();
250
+			int top = y + bounds.y - offsetY.getValue();
251
+			int right = left + width;
252
+			int bottom = top + height;
253
+			
254
+			left = Math.max(bounds.x, left);
255
+			top = Math.max(bounds.y, top);
256
+			right = Math.min(bounds.x + bounds.width, right);
257
+			bottom = Math.min(bounds.y + bounds.height, bottom);
258
+			
259
+			if (left >= right || top >= bottom)
260
+				return;
261
+			
262
+			context.repaint(left, top, right - left, bottom - top);
263
+		}
264
+
265
+		@Override
266
+		public void setCursor(Cursor cursor) {
267
+			context.setCursor(cursor);
268
+		}
269
+
270
+		@Override
271
+		public DFontMetrics getFontMetrics(DFont font) {
272
+			return context.getFontMetrics(font);
273
+		}
274
+
275
+		@Override
276
+		public void focus(DComponent component) {
277
+			context.focus(component);
278
+		}
279
+
280
+		@Override
281
+		public void scrollInView(int x, int y, int width, int height) {
282
+			if (y < offsetY.getValue())
283
+				offsetY.setValue(y);
284
+			if (y + height > offsetY.getValue() + bounds.height)
285
+				offsetY.setValue(y + height - bounds.height);
286
+		}
287
+
288
+		@Override
289
+		public DTimerHandle setTimer(int millis, Runnable target) {
290
+			return context.setTimer(millis, target);
291
+		}
292
+
293
+		@Override
294
+		public DClipboard getClipboard() {
295
+			return context.getClipboard();
296
+		}
297
+
298
+		@Override
299
+		public DUIWindow getWindow() {
300
+			return context.getWindow();
301
+		}
302
+	}
303
+	
304
+	private class ScrollListener implements LiveInt.Listener {
305
+
306
+		@Override
307
+		public void onChanged(int oldValue, int newValue) {
308
+			int value = offsetY.getValue();
309
+			if (value > contentsHeight.getValue() - bounds.height)
310
+				value = contentsHeight.getValue() - bounds.height;
311
+			if (value < 0)
312
+				value = 0;
313
+			
314
+			if (value != offsetY.getValue())
315
+				offsetY.setValue(value);
316
+			if (context != null && bounds != null)
317
+				context.repaint(bounds);
318
+		}
319
+	}
320
+}

+ 23
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPaneStyle.java Ver arquivo

@@ -0,0 +1,23 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.scroll;
7
+
8
+import org.openzen.drawablegui.border.DBorder;
9
+import org.openzen.drawablegui.border.DLineBorder;
10
+import org.openzen.drawablegui.DUIContext;
11
+import org.openzen.drawablegui.style.DStyleDefinition;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class DScrollPaneStyle {
18
+	public final DBorder border;
19
+	
20
+	public DScrollPaneStyle(DStyleDefinition style) {
21
+		this.border = style.getBorder("border", context -> new DLineBorder(0xFF888888, 1));
22
+	}
23
+}

+ 20
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DDimension.java Ver arquivo

@@ -0,0 +1,20 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+import org.openzen.drawablegui.DUIContext;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface DDimension {
15
+	float eval(DUIContext context);
16
+	
17
+	default int evalInt(DUIContext context) {
18
+		return (int)(eval(context) + 0.5f);
19
+	}
20
+}

+ 25
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DDpDimension.java Ver arquivo

@@ -0,0 +1,25 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+import org.openzen.drawablegui.DUIContext;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class DDpDimension implements DDimension {
15
+	private final float value;
16
+	
17
+	public DDpDimension(float value) {
18
+		this.value = value;
19
+	}
20
+
21
+	@Override
22
+	public float eval(DUIContext context) {
23
+		return value * context.getScale();
24
+	}
25
+}

+ 53
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStyleDefinition.java Ver arquivo

@@ -0,0 +1,53 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+import java.util.function.Function;
9
+import org.openzen.drawablegui.DFont;
10
+import org.openzen.drawablegui.DUIContext;
11
+import org.openzen.drawablegui.border.DBorder;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class DEmptyStyleDefinition implements DStyleDefinition {
18
+	private final DUIContext context;
19
+	
20
+	public DEmptyStyleDefinition(DUIContext context) {
21
+		this.context = context;
22
+	}
23
+
24
+	@Override
25
+	public int getDimension(String name, DDimension defaultValue) {
26
+		return defaultValue.evalInt(context);
27
+	}
28
+	
29
+	@Override
30
+	public float getFloatDimension(String name, DDimension defaultValue) {
31
+		return defaultValue.eval(context);
32
+	}
33
+
34
+	@Override
35
+	public int getColor(String name, int defaultValue) {
36
+		return defaultValue;
37
+	}
38
+
39
+	@Override
40
+	public DShadow getShadow(String name, Function<DUIContext, DShadow> defaultValue) {
41
+		return defaultValue.apply(context);
42
+	}
43
+
44
+	@Override
45
+	public DFont getFont(String name, Function<DUIContext, DFont> defaultValue) {
46
+		return defaultValue.apply(context);
47
+	}
48
+
49
+	@Override
50
+	public DBorder getBorder(String name, Function<DUIContext, DBorder> defaultValue) {
51
+		return defaultValue.apply(context);
52
+	}
53
+}

+ 21
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStylesheets.java Ver arquivo

@@ -0,0 +1,21 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+import org.openzen.drawablegui.DUIContext;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class DEmptyStylesheets implements DStyleSheets {
15
+	public static final DEmptyStylesheets INSTANCE = new DEmptyStylesheets();
16
+
17
+	@Override
18
+	public DStyleDefinition get(DUIContext context, DStylePath path) {
19
+		return new DEmptyStyleDefinition(context);
20
+	}
21
+}

+ 25
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DPxDimension.java Ver arquivo

@@ -0,0 +1,25 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+import org.openzen.drawablegui.DUIContext;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class DPxDimension implements DDimension {
15
+	private final float pixels;
16
+	
17
+	public DPxDimension(float pixels) {
18
+		this.pixels = pixels;
19
+	}
20
+
21
+	@Override
22
+	public float eval(DUIContext context) {
23
+		return pixels;
24
+	}
25
+}

+ 26
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DShadow.java Ver arquivo

@@ -0,0 +1,26 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DShadow {
13
+	public static final DShadow NONE = new DShadow(0, 0, 0, 0);
14
+	
15
+	public final int color;
16
+	public final float offsetX;
17
+	public final float offsetY;
18
+	public final float radius;
19
+	
20
+	public DShadow(int color, float offsetX, float offsetY, float radius) {
21
+		this.color = color;
22
+		this.offsetX = offsetX;
23
+		this.offsetY = offsetY;
24
+		this.radius = radius;
25
+	}
26
+}

+ 27
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleClass.java Ver arquivo

@@ -0,0 +1,27 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DStyleClass {
13
+	private static final String[] NO_CLASSES = new String[0];
14
+	public static final DStyleClass EMPTY = new DStyleClass(null, NO_CLASSES);
15
+	
16
+	public static DStyleClass forId(String id) {
17
+		return new DStyleClass(id, NO_CLASSES);
18
+	}
19
+	
20
+	public final String id;
21
+	public final String[] classes;
22
+	
23
+	public DStyleClass(String id, String[] classes) {
24
+		this.id = id;
25
+		this.classes = classes;
26
+	}
27
+}

+ 29
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleDefinition.java Ver arquivo

@@ -0,0 +1,29 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+import java.util.function.Function;
9
+import org.openzen.drawablegui.DFont;
10
+import org.openzen.drawablegui.DUIContext;
11
+import org.openzen.drawablegui.border.DBorder;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public interface DStyleDefinition {
18
+	public int getDimension(String name, DDimension defaultValue);
19
+	
20
+	public float getFloatDimension(String name, DDimension defaultValue);
21
+	
22
+	public int getColor(String name, int defaultValue);
23
+	
24
+	public DShadow getShadow(String name, Function<DUIContext, DShadow> defaultValue);
25
+	
26
+	public DFont getFont(String name, Function<DUIContext, DFont> defaultValue);
27
+	
28
+	public DBorder getBorder(String name, Function<DUIContext, DBorder> defaultValue);
29
+}

+ 14
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePath.java Ver arquivo

@@ -0,0 +1,14 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DStylePath {
13
+	public DStylePath getChild(String element, DStyleClass styleClass);
14
+}

+ 38
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePathRoot.java Ver arquivo

@@ -0,0 +1,38 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public class DStylePathRoot implements DStylePath {
13
+	public static final DStylePathRoot INSTANCE = new DStylePathRoot();
14
+	
15
+	private DStylePathRoot() {}
16
+
17
+	@Override
18
+	public DStylePath getChild(String element, DStyleClass styleClass) {
19
+		return new DStyleChildElement(this, element, styleClass);
20
+	}
21
+	
22
+	private static class DStyleChildElement implements DStylePath {
23
+		private final DStylePath parent;
24
+		private final String element;
25
+		private final DStyleClass styleClass;
26
+		
27
+		public DStyleChildElement(DStylePath parent, String element, DStyleClass styleClass) {
28
+			this.parent = parent;
29
+			this.element = element;
30
+			this.styleClass = styleClass;
31
+		}
32
+
33
+		@Override
34
+		public DStylePath getChild(String element, DStyleClass styleClass) {
35
+			return new DStyleChildElement(this, element, styleClass);
36
+		}
37
+	}
38
+}

+ 16
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleSheets.java Ver arquivo

@@ -0,0 +1,16 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.style;
7
+
8
+import org.openzen.drawablegui.DUIContext;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface DStyleSheets {
15
+	public DStyleDefinition get(DUIContext context, DStylePath path);
16
+}

+ 46
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/JavaClipboard.java Ver arquivo

@@ -0,0 +1,46 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.swing;
7
+
8
+import java.awt.Toolkit;
9
+import java.awt.datatransfer.Clipboard;
10
+import java.awt.datatransfer.DataFlavor;
11
+import java.awt.datatransfer.StringSelection;
12
+import java.awt.datatransfer.Transferable;
13
+import java.awt.datatransfer.UnsupportedFlavorException;
14
+import java.io.IOException;
15
+import org.openzen.drawablegui.DClipboard;
16
+
17
+/**
18
+ *
19
+ * @author Hoofdgebruiker
20
+ */
21
+public class JavaClipboard implements DClipboard {
22
+	private final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
23
+
24
+	@Override
25
+	public void copyAsString(String value) {
26
+		StringSelection stringSelection = new StringSelection(value);
27
+		clipboard.setContents(stringSelection, null);
28
+	}
29
+
30
+	@Override
31
+	public String getAsString() {
32
+		Transferable contents = clipboard.getContents(null);
33
+		if (contents == null)
34
+			return null;
35
+		
36
+		if (!contents.isDataFlavorSupported(DataFlavor.stringFlavor))
37
+			return null;
38
+		
39
+		try {
40
+			return (String)contents.getTransferData(DataFlavor.stringFlavor);
41
+		} catch (UnsupportedFlavorException | IOException ex) {
42
+			ex.printStackTrace();
43
+			return null;
44
+		}
45
+	}
46
+}

+ 209
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingCanvas.java Ver arquivo

@@ -0,0 +1,209 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.swing;
7
+
8
+import java.awt.BasicStroke;
9
+import java.awt.Color;
10
+import java.awt.Font;
11
+import java.awt.Graphics2D;
12
+import java.awt.Rectangle;
13
+import java.awt.RenderingHints;
14
+import java.awt.geom.AffineTransform;
15
+import java.awt.geom.GeneralPath;
16
+import java.awt.image.BufferedImage;
17
+import java.awt.image.ConvolveOp;
18
+import java.awt.image.Kernel;
19
+import java.util.Stack;
20
+import org.openzen.drawablegui.DCanvas;
21
+import org.openzen.drawablegui.DFont;
22
+import org.openzen.drawablegui.DFontFamily;
23
+import org.openzen.drawablegui.DTransform2D;
24
+import org.openzen.drawablegui.DIRectangle;
25
+import org.openzen.drawablegui.DPath;
26
+import org.openzen.drawablegui.DPathBoundsCalculator;
27
+import org.openzen.drawablegui.DUIContext;
28
+import org.openzen.drawablegui.style.DShadow;
29
+
30
+/**
31
+ *
32
+ * @author Hoofdgebruiker
33
+ */
34
+public class SwingCanvas implements DCanvas {
35
+	private final Graphics2D g;
36
+	private final SwingGraphicsContext context;
37
+	private final Stack<Rectangle> bounds = new Stack<>();
38
+	private final Stack<AffineTransform> transformStack = new Stack<>();
39
+	
40
+	public SwingCanvas(Graphics2D g, SwingGraphicsContext context, DIRectangle bounds) {
41
+		this.g = g;
42
+		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
43
+		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
44
+		
45
+		this.context = context;
46
+		
47
+		if (bounds != null)
48
+			pushBounds(new DIRectangle(bounds.x, bounds.y, bounds.width, bounds.height));
49
+	}
50
+	
51
+	@Override
52
+	public void pushBounds(DIRectangle bounds) {
53
+		this.bounds.push(g.getClipBounds());
54
+		g.setClip(bounds.x, bounds.y, bounds.width, bounds.height);
55
+	}
56
+	
57
+	@Override
58
+	public void popBounds() {
59
+		Rectangle bounds = this.bounds.pop();
60
+		g.setClip(bounds.x, bounds.y, bounds.width, bounds.height);
61
+	}
62
+	
63
+	@Override
64
+	public void pushOffset(int x, int y) {
65
+		transformStack.push(g.getTransform());
66
+		g.transform(AffineTransform.getTranslateInstance(x, y));
67
+	}
68
+	
69
+	@Override
70
+	public void popOffset() {
71
+		g.setTransform(transformStack.pop());
72
+	}
73
+	
74
+	@Override
75
+	public DIRectangle getBounds() {
76
+		Rectangle bounds = g.getClipBounds();
77
+		return new DIRectangle(bounds.x, bounds.y, bounds.width, bounds.height);
78
+	}
79
+
80
+	@Override
81
+	public void drawText(DFont font, int color, float x, float y, String text) {
82
+		prepare(font);
83
+		g.setColor(new Color(color, true));
84
+		g.setFont((Font) font.cached);
85
+		g.drawString(text, x, y);
86
+	}
87
+
88
+	@Override
89
+	public DUIContext getContext() {
90
+		return context;
91
+	}
92
+
93
+	@Override
94
+	public void strokePath(DPath path, DTransform2D transform, int color, float lineWidth) {
95
+		if (color == 0)
96
+			return;
97
+		
98
+		AffineTransform old = g.getTransform();
99
+		GeneralPath jPath = context.getPath(path);
100
+		g.setColor(new Color(color, true));
101
+		g.setStroke(new BasicStroke(lineWidth));
102
+		g.transform(getTransform(transform));
103
+		g.draw(jPath);
104
+		g.setTransform(old);
105
+	}
106
+
107
+	@Override
108
+	public void fillPath(DPath path, DTransform2D transform, int color) {
109
+		if (color == 0)
110
+			return;
111
+		
112
+		AffineTransform old = g.getTransform();
113
+		GeneralPath jPath = context.getPath(path);
114
+		g.setColor(new Color(color, true));
115
+		g.transform(getTransform(transform));
116
+		g.fill(jPath);
117
+		g.setTransform(old);
118
+	}
119
+
120
+	@Override
121
+	public void shadowPath(DPath path, DTransform2D transform, DShadow shadow) {
122
+		if (shadow.color == 0)
123
+			return;
124
+		
125
+		if (shadow.radius == 0) {
126
+			fillPath(path, transform, shadow.color);
127
+			return;
128
+		}
129
+		
130
+		DIRectangle bounds = DPathBoundsCalculator.getBounds(path, transform.offset(shadow.offsetX, shadow.offsetY));
131
+		int offset = 2 * (int)Math.ceil(shadow.radius);
132
+		
133
+		GeneralPath jPath = context.getPath(path);
134
+		
135
+		BufferedImage image = new BufferedImage(bounds.width + 2 * offset, bounds.height + 2 * offset, BufferedImage.TYPE_INT_ARGB_PRE);
136
+		Graphics2D imageG = (Graphics2D) image.getGraphics();
137
+		
138
+		imageG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
139
+		imageG.setColor(new Color(shadow.color, true));
140
+		imageG.setTransform(getTransform(transform.offset(offset + shadow.offsetX - bounds.x, offset + shadow.offsetY - bounds.y)));
141
+		imageG.fill(jPath);
142
+		
143
+		image = getGaussianBlurFilter((int)Math.ceil(shadow.radius), true).filter(image, null);
144
+		image = getGaussianBlurFilter((int)Math.ceil(shadow.radius), false).filter(image, null);
145
+		g.drawImage(image, bounds.x - offset, bounds.y - offset, null);
146
+	}
147
+
148
+	@Override
149
+	public void fillRectangle(int x, int y, int width, int height, int color) {
150
+		if (color == 0)
151
+			return;
152
+		
153
+		g.setColor(new Color(color, true));
154
+		g.fillRect(x, y, width, height);
155
+	}
156
+	
157
+	public static void prepare(DFont font) {
158
+		if (font.cached != null && font.cached instanceof Font)
159
+			return;
160
+		
161
+		String baseFontName = font.family == DFontFamily.CODE ? "Consolas" : Font.DIALOG;
162
+		int style = 0;
163
+		if (font.bold)
164
+			style |= Font.BOLD;
165
+		if (font.italic)
166
+			style |= Font.ITALIC;
167
+		
168
+		font.cached = Font.decode(baseFontName).deriveFont(style, font.size);
169
+	}
170
+	
171
+	private AffineTransform getTransform(DTransform2D transform) {
172
+		return new AffineTransform(transform.xx, transform.xy, transform.yx, transform.yy, transform.dx, transform.dy);
173
+	}
174
+    
175
+	
176
+	// taken from http://www.java2s.com/Code/Java/Advanced-Graphics/GaussianBlurDemo.htm
177
+    public static ConvolveOp getGaussianBlurFilter(int radius, boolean horizontal) {
178
+        if (radius < 1) {
179
+            throw new IllegalArgumentException("Radius must be >= 1");
180
+        }
181
+        
182
+        int size = radius * 2 + 1;
183
+        float[] data = new float[size];
184
+        
185
+        float sigma = radius / 3.0f;
186
+        float twoSigmaSquare = 2.0f * sigma * sigma;
187
+        float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
188
+        float total = 0.0f;
189
+        
190
+        for (int i = -radius; i <= radius; i++) {
191
+            float distance = i * i;
192
+            int index = i + radius;
193
+            data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
194
+            total += data[index];
195
+        }
196
+        
197
+        for (int i = 0; i < data.length; i++) {
198
+            data[i] /= total;
199
+        }        
200
+        
201
+        Kernel kernel = null;
202
+        if (horizontal) {
203
+            kernel = new Kernel(size, 1, data);
204
+        } else {
205
+            kernel = new Kernel(1, size, data);
206
+        }
207
+        return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
208
+    }
209
+}

+ 49
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingFontMetrics.java Ver arquivo

@@ -0,0 +1,49 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.swing;
7
+
8
+import java.awt.FontMetrics;
9
+import java.awt.Graphics;
10
+import org.openzen.drawablegui.DFontMetrics;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class SwingFontMetrics implements DFontMetrics {
17
+	private final FontMetrics metrics;
18
+	private final Graphics context;
19
+	
20
+	public SwingFontMetrics(FontMetrics metrics, Graphics context) {
21
+		this.metrics = metrics;
22
+		this.context = context;
23
+	}
24
+
25
+	@Override
26
+	public int getAscent() {
27
+		return metrics.getAscent();
28
+	}
29
+
30
+	@Override
31
+	public int getDescent() {
32
+		return metrics.getDescent();
33
+	}
34
+
35
+	@Override
36
+	public int getLeading() {
37
+		return metrics.getLeading();
38
+	}
39
+
40
+	@Override
41
+	public int getWidth(String str) {
42
+		return (int) metrics.getStringBounds(str, context).getWidth();
43
+	}
44
+
45
+	@Override
46
+	public int getWidth(String str, int offset, int length) {
47
+		return (int) metrics.getStringBounds(str, offset, length, context).getWidth();
48
+	}
49
+}

+ 172
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingGraphicsContext.java Ver arquivo

@@ -0,0 +1,172 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.swing;
7
+
8
+import java.awt.Font;
9
+import java.awt.Graphics;
10
+import java.awt.geom.GeneralPath;
11
+import java.util.WeakHashMap;
12
+import javax.swing.Timer;
13
+import org.openzen.drawablegui.DClipboard;
14
+import org.openzen.drawablegui.DComponent;
15
+import org.openzen.drawablegui.DPath;
16
+import org.openzen.drawablegui.DFont;
17
+import org.openzen.drawablegui.DFontMetrics;
18
+import org.openzen.drawablegui.DPathTracer;
19
+import org.openzen.drawablegui.DTimerHandle;
20
+import org.openzen.drawablegui.DUIContext;
21
+import org.openzen.drawablegui.DUIWindow;
22
+import org.openzen.drawablegui.style.DStyleSheets;
23
+
24
+/**
25
+ *
26
+ * @author Hoofdgebruiker
27
+ */
28
+public class SwingGraphicsContext implements DUIContext {
29
+	private final DStyleSheets stylesheets;
30
+	private final float scale;
31
+	private final WeakHashMap<DPath, GeneralPath> preparedPaths = new WeakHashMap<>();
32
+	private final SwingRoot root;
33
+	private final JavaClipboard clipboard = new JavaClipboard();
34
+	private Graphics graphics;
35
+	private DUIWindow window;
36
+	
37
+	public SwingGraphicsContext(DStyleSheets stylesheets, float scale, SwingRoot root) {
38
+		this.stylesheets = stylesheets;
39
+		this.scale = scale;
40
+		this.root = root;
41
+	}
42
+	
43
+	public GeneralPath getPath(DPath path) {
44
+		GeneralPath generalPath = preparedPaths.get(path);
45
+		if (generalPath == null) {
46
+			generalPath = new GeneralPath();
47
+			path.trace(new PathTracer(generalPath));
48
+			preparedPaths.put(path, generalPath);
49
+		}
50
+		return generalPath;
51
+	}
52
+	
53
+	public void setWindow(DUIWindow window) {
54
+		this.window = window;
55
+	}
56
+	
57
+	@Override
58
+	public DStyleSheets getStylesheets() {
59
+		return stylesheets;
60
+	}
61
+	
62
+	@Override
63
+	public float getScale() {
64
+		return scale;
65
+	}
66
+	
67
+	@Override
68
+	public void repaint(int x, int y, int width, int height) {
69
+		root.repaint(x, y, width, height);
70
+	}
71
+
72
+	@Override
73
+	public void setCursor(Cursor cursor) {
74
+		int translated = java.awt.Cursor.DEFAULT_CURSOR;
75
+		switch (cursor) {
76
+			case NORMAL:
77
+				translated = java.awt.Cursor.DEFAULT_CURSOR;
78
+				break;
79
+			case MOVE:
80
+				translated = java.awt.Cursor.MOVE_CURSOR;
81
+				break;
82
+			case HAND:
83
+				translated = java.awt.Cursor.HAND_CURSOR;
84
+				break;
85
+			case TEXT:
86
+				translated = java.awt.Cursor.TEXT_CURSOR;
87
+				break;
88
+			case E_RESIZE:
89
+				translated = java.awt.Cursor.E_RESIZE_CURSOR;
90
+				break;
91
+			case S_RESIZE:
92
+				translated = java.awt.Cursor.S_RESIZE_CURSOR;
93
+				break;
94
+			case NE_RESIZE:
95
+				translated = java.awt.Cursor.NE_RESIZE_CURSOR;
96
+				break;
97
+			case NW_RESIZE:
98
+				translated = java.awt.Cursor.NW_RESIZE_CURSOR;
99
+				break;
100
+		}
101
+		root.setCursor(java.awt.Cursor.getPredefinedCursor(translated));
102
+	}
103
+
104
+	@Override
105
+	public DFontMetrics getFontMetrics(DFont font) {
106
+		if (graphics == null)
107
+			graphics = root.getGraphics();
108
+		
109
+		SwingCanvas.prepare(font);
110
+		return new SwingFontMetrics(graphics.getFontMetrics((Font) font.cached), graphics);
111
+	}
112
+	
113
+	@Override
114
+	public void focus(DComponent component) {
115
+		this.root.focus(component);
116
+	}
117
+
118
+	@Override
119
+	public void scrollInView(int x, int y, int width, int height) {
120
+		// not in a scrollable context
121
+	}
122
+
123
+	@Override
124
+	public DTimerHandle setTimer(int millis, Runnable target) {
125
+		Timer timer = new Timer(millis, e -> target.run());
126
+		timer.start();
127
+		return () -> timer.stop();
128
+	}
129
+
130
+	@Override
131
+	public DClipboard getClipboard() {
132
+		return clipboard;
133
+	}
134
+
135
+	@Override
136
+	public DUIWindow getWindow() {
137
+		return window;
138
+	}
139
+	
140
+	private class PathTracer implements DPathTracer {
141
+		private final GeneralPath path;
142
+		
143
+		public PathTracer(GeneralPath path) {
144
+			this.path = path;
145
+		}
146
+
147
+		@Override
148
+		public void moveTo(float x, float y) {
149
+			path.moveTo(x, y);
150
+		}
151
+
152
+		@Override
153
+		public void lineTo(float x, float y) {
154
+			path.lineTo(x, y);
155
+		}
156
+
157
+		@Override
158
+		public void bezierCubic(float x1, float y1, float x2, float y2, float x3, float y3) {
159
+			path.curveTo(x1, y1, x2, y2, x3, y3);
160
+		}
161
+
162
+		@Override
163
+		public void bezierQuadratic(float x1, float y1, float x2, float y2) {
164
+			path.quadTo(x1, y1, x2, y2);
165
+		}
166
+
167
+		@Override
168
+		public void close() {
169
+			path.closePath();
170
+		}
171
+	}
172
+}

+ 553
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingRoot.java Ver arquivo

@@ -0,0 +1,553 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.swing;
7
+
8
+import java.awt.Component;
9
+import java.awt.Graphics;
10
+import java.awt.Graphics2D;
11
+import java.awt.Rectangle;
12
+import java.awt.Toolkit;
13
+import java.awt.event.ComponentEvent;
14
+import java.awt.event.ComponentListener;
15
+import java.awt.event.KeyEvent;
16
+import java.awt.event.KeyListener;
17
+import java.awt.event.MouseEvent;
18
+import java.awt.event.MouseListener;
19
+import java.awt.event.MouseMotionListener;
20
+import java.awt.event.MouseWheelEvent;
21
+import java.awt.event.MouseWheelListener;
22
+import org.openzen.drawablegui.DComponent;
23
+import org.openzen.drawablegui.DIRectangle;
24
+import org.openzen.drawablegui.DKeyEvent;
25
+import static org.openzen.drawablegui.DKeyEvent.KeyCode.*;
26
+import org.openzen.drawablegui.DMouseEvent;
27
+import org.openzen.drawablegui.DUIWindow;
28
+import org.openzen.drawablegui.style.DEmptyStylesheets;
29
+import org.openzen.drawablegui.style.DStylePathRoot;
30
+
31
+/**
32
+ *
33
+ * @author Hoofdgebruiker
34
+ */
35
+public final class SwingRoot extends Component implements ComponentListener, MouseListener, MouseMotionListener, MouseWheelListener, KeyListener {
36
+	public final SwingGraphicsContext context;
37
+	public final DComponent component;
38
+	private DComponent focus = null;
39
+	private boolean firstPaint = true;
40
+
41
+	public SwingRoot(DComponent root) {
42
+		this.component = root;
43
+		setFocusable(true);
44
+		setFocusTraversalKeysEnabled(false); // prevent tab from being handled by focus traversal
45
+		
46
+		context = new SwingGraphicsContext(
47
+				DEmptyStylesheets.INSTANCE,
48
+				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
49
+				this);
50
+		component.setBounds(new DIRectangle(0, 0, getWidth(), getHeight()));
51
+		addComponentListener(this);
52
+		addMouseListener(this);
53
+		addMouseMotionListener(this);
54
+		addMouseWheelListener(this);
55
+		addKeyListener(this);
56
+	}
57
+	
58
+	public void setWindow(DUIWindow window) {
59
+		context.setWindow(window);
60
+	}
61
+	
62
+	public void focus(DComponent component) {
63
+		if (component == focus)
64
+			return;
65
+		
66
+		if (focus != null)
67
+			focus.onFocusLost();
68
+		this.focus = component;
69
+		if (focus != null)
70
+			focus.onFocusGained();
71
+	}
72
+
73
+	@Override
74
+	public void paint(Graphics g) {
75
+		if (firstPaint) {
76
+			firstPaint = false;
77
+			component.setContext(DStylePathRoot.INSTANCE, context);
78
+		}
79
+		
80
+		Rectangle clipBounds = g.getClipBounds();
81
+		DIRectangle clipBounds2 = clipBounds == null ? null : new DIRectangle(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
82
+		SwingCanvas canvas = new SwingCanvas((Graphics2D) g, context, clipBounds2);
83
+		component.paint(canvas);
84
+	}
85
+
86
+	@Override
87
+	public void componentResized(ComponentEvent e) {
88
+		component.setBounds(new DIRectangle(0, 0,
89
+				e.getComponent().getWidth(),
90
+				e.getComponent().getHeight()));
91
+
92
+		invalidate();
93
+	}
94
+
95
+	@Override
96
+	public void componentMoved(ComponentEvent e) {
97
+
98
+	}
99
+
100
+	@Override
101
+	public void componentShown(ComponentEvent e) {
102
+
103
+	}
104
+
105
+	@Override
106
+	public void componentHidden(ComponentEvent e) {
107
+
108
+	}
109
+
110
+	@Override
111
+	public void mouseClicked(MouseEvent e) {
112
+		component.onMouseClick(translateMouseEvent(e));
113
+	}
114
+
115
+	@Override
116
+	public void mousePressed(MouseEvent e) {
117
+		component.onMouseDown(translateMouseEvent(e));
118
+	}
119
+
120
+	@Override
121
+	public void mouseReleased(MouseEvent e) {
122
+		component.onMouseRelease(translateMouseEvent(e));
123
+	}
124
+
125
+	@Override
126
+	public void mouseEntered(MouseEvent e) {
127
+		component.onMouseEnter(translateMouseEvent(e));
128
+	}
129
+
130
+	@Override
131
+	public void mouseExited(MouseEvent e) {
132
+		component.onMouseExit(translateMouseEvent(e));
133
+	}
134
+
135
+	@Override
136
+	public void mouseDragged(MouseEvent e) {
137
+		component.onMouseDrag(translateMouseEvent(e));
138
+	}
139
+
140
+	@Override
141
+	public void mouseMoved(MouseEvent e) {
142
+		component.onMouseMove(translateMouseEvent(e));
143
+	}
144
+
145
+	@Override
146
+	public void mouseWheelMoved(MouseWheelEvent e) {
147
+		component.onMouseScroll(translateScrollEvent(e));
148
+	}
149
+
150
+	@Override
151
+	public void keyTyped(KeyEvent e) {
152
+		if (focus == null)
153
+			return;
154
+
155
+		focus.onKeyTyped(translateKeyEvent(e));
156
+	}
157
+
158
+	@Override
159
+	public void keyPressed(KeyEvent e) {
160
+		if (focus == null)
161
+			return;
162
+		
163
+		focus.onKeyPressed(translateKeyEvent(e));
164
+	}
165
+
166
+	@Override
167
+	public void keyReleased(KeyEvent e) {
168
+		if (focus == null)
169
+			return;
170
+		
171
+		focus.onKeyReleased(translateKeyEvent(e));
172
+	}
173
+
174
+	private DMouseEvent translateMouseEvent(MouseEvent e) {
175
+		return new DMouseEvent(e.getX(), e.getY(), getModifiers(e.getModifiersEx()), 0, e.getClickCount());
176
+	}
177
+
178
+	private DMouseEvent translateScrollEvent(MouseWheelEvent e) {
179
+		return new DMouseEvent(e.getX(), e.getY(), getModifiers(e.getModifiersEx()), e.getUnitsToScroll(), e.getClickCount());
180
+	}
181
+	
182
+	private DKeyEvent translateKeyEvent(KeyEvent e) {
183
+		return new DKeyEvent(e.getKeyChar(), getKeyCode(e.getKeyCode()), getModifiers(e.getModifiersEx()));
184
+	}
185
+	
186
+	private DKeyEvent.KeyCode getKeyCode(int code) {
187
+		switch (code) {
188
+			case KeyEvent.VK_ENTER:
189
+				return ENTER;
190
+			case KeyEvent.VK_BACK_SPACE:
191
+				return BACKSPACE;
192
+			case KeyEvent.VK_TAB:
193
+				return TAB;
194
+    		case KeyEvent.VK_CANCEL:
195
+				return DKeyEvent.KeyCode.CANCEL;
196
+    		case KeyEvent.VK_CLEAR:
197
+				return DKeyEvent.KeyCode.CLEAR;
198
+    		case KeyEvent.VK_SHIFT:
199
+				return DKeyEvent.KeyCode.SHIFT;
200
+    		case KeyEvent.VK_CONTROL:
201
+				return DKeyEvent.KeyCode.CONTROL;
202
+    		case KeyEvent.VK_ALT:
203
+				return DKeyEvent.KeyCode.ALT;
204
+    		case KeyEvent.VK_PAUSE:
205
+				return DKeyEvent.KeyCode.PAUSE;
206
+    		case KeyEvent.VK_CAPS_LOCK:
207
+				return DKeyEvent.KeyCode.CAPS_LOCK;
208
+    		case KeyEvent.VK_ESCAPE:
209
+				return DKeyEvent.KeyCode.ESCAPE;
210
+    		case KeyEvent.VK_SPACE:
211
+				return DKeyEvent.KeyCode.SPACE;
212
+    		case KeyEvent.VK_PAGE_UP:
213
+				return DKeyEvent.KeyCode.PAGE_UP;
214
+    		case KeyEvent.VK_PAGE_DOWN:
215
+				return DKeyEvent.KeyCode.PAGE_DOWN;
216
+    		case KeyEvent.VK_END:
217
+				return DKeyEvent.KeyCode.END;
218
+    		case KeyEvent.VK_HOME:
219
+				return DKeyEvent.KeyCode.HOME;
220
+    		case KeyEvent.VK_LEFT:
221
+				return DKeyEvent.KeyCode.LEFT;
222
+    		case KeyEvent.VK_UP:
223
+				return DKeyEvent.KeyCode.UP;
224
+    		case KeyEvent.VK_RIGHT:
225
+				return DKeyEvent.KeyCode.RIGHT;
226
+    		case KeyEvent.VK_DOWN:
227
+				return DKeyEvent.KeyCode.DOWN;
228
+    		case KeyEvent.VK_COMMA:
229
+				return DKeyEvent.KeyCode.COMMA;
230
+    		case KeyEvent.VK_MINUS:
231
+				return DKeyEvent.KeyCode.MINUS;
232
+    		case KeyEvent.VK_PERIOD:
233
+				return DKeyEvent.KeyCode.PERIOD;
234
+    		case KeyEvent.VK_SLASH:
235
+				return DKeyEvent.KeyCode.SLASH;
236
+    		case KeyEvent.VK_0:
237
+				return DKeyEvent.KeyCode.NUM0;
238
+    		case KeyEvent.VK_1:
239
+				return DKeyEvent.KeyCode.NUM1;
240
+    		case KeyEvent.VK_2:
241
+				return DKeyEvent.KeyCode.NUM2;
242
+    		case KeyEvent.VK_3:
243
+				return DKeyEvent.KeyCode.NUM3;
244
+    		case KeyEvent.VK_4:
245
+				return DKeyEvent.KeyCode.NUM4;
246
+    		case KeyEvent.VK_5:
247
+				return DKeyEvent.KeyCode.NUM5;
248
+    		case KeyEvent.VK_6:
249
+				return DKeyEvent.KeyCode.NUM6;
250
+    		case KeyEvent.VK_7:
251
+				return DKeyEvent.KeyCode.NUM7;
252
+    		case KeyEvent.VK_8:
253
+				return DKeyEvent.KeyCode.NUM8;
254
+    		case KeyEvent.VK_9:
255
+				return DKeyEvent.KeyCode.NUM9;
256
+    		case KeyEvent.VK_SEMICOLON:
257
+				return DKeyEvent.KeyCode.SEMICOLON;
258
+    		case KeyEvent.VK_EQUALS:
259
+				return DKeyEvent.KeyCode.EQUALS;
260
+    		case KeyEvent.VK_A:
261
+				return DKeyEvent.KeyCode.A;
262
+    		case KeyEvent.VK_B:
263
+				return DKeyEvent.KeyCode.B;
264
+    		case KeyEvent.VK_C:
265
+				return DKeyEvent.KeyCode.C;
266
+    		case KeyEvent.VK_D:
267
+				return DKeyEvent.KeyCode.D;
268
+    		case KeyEvent.VK_E:
269
+				return DKeyEvent.KeyCode.E;
270
+    		case KeyEvent.VK_F:
271
+				return DKeyEvent.KeyCode.F;
272
+    		case KeyEvent.VK_G:
273
+				return DKeyEvent.KeyCode.G;
274
+    		case KeyEvent.VK_H:
275
+				return DKeyEvent.KeyCode.H;
276
+    		case KeyEvent.VK_I:
277
+				return DKeyEvent.KeyCode.I;
278
+    		case KeyEvent.VK_J:
279
+				return DKeyEvent.KeyCode.J;
280
+    		case KeyEvent.VK_K:
281
+				return DKeyEvent.KeyCode.K;
282
+    		case KeyEvent.VK_L:
283
+				return DKeyEvent.KeyCode.L;
284
+    		case KeyEvent.VK_M:
285
+				return DKeyEvent.KeyCode.M;
286
+    		case KeyEvent.VK_N:
287
+				return DKeyEvent.KeyCode.N;
288
+    		case KeyEvent.VK_O:
289
+				return DKeyEvent.KeyCode.O;
290
+    		case KeyEvent.VK_P:
291
+				return DKeyEvent.KeyCode.P;
292
+    		case KeyEvent.VK_Q:
293
+				return DKeyEvent.KeyCode.Q;
294
+    		case KeyEvent.VK_R:
295
+				return DKeyEvent.KeyCode.R;
296
+    		case KeyEvent.VK_S:
297
+				return DKeyEvent.KeyCode.S;
298
+    		case KeyEvent.VK_T:
299
+				return DKeyEvent.KeyCode.T;
300
+    		case KeyEvent.VK_U:
301
+				return DKeyEvent.KeyCode.U;
302
+    		case KeyEvent.VK_V:
303
+				return DKeyEvent.KeyCode.V;
304
+    		case KeyEvent.VK_W:
305
+				return DKeyEvent.KeyCode.W;
306
+    		case KeyEvent.VK_X:
307
+				return DKeyEvent.KeyCode.X;
308
+    		case KeyEvent.VK_Y:
309
+				return DKeyEvent.KeyCode.Y;
310
+    		case KeyEvent.VK_Z:
311
+				return DKeyEvent.KeyCode.Z;
312
+    		case KeyEvent.VK_OPEN_BRACKET:
313
+				return DKeyEvent.KeyCode.OPEN_BRACKET;
314
+    		case KeyEvent.VK_BACK_SLASH:
315
+				return DKeyEvent.KeyCode.BACKSLASH;
316
+    		case KeyEvent.VK_CLOSE_BRACKET:
317
+				return DKeyEvent.KeyCode.CLOSE_BRACKET;
318
+    		case KeyEvent.VK_NUMPAD0:
319
+				return DKeyEvent.KeyCode.NUMPAD0;
320
+    		case KeyEvent.VK_NUMPAD1:
321
+				return DKeyEvent.KeyCode.NUMPAD1;
322
+    		case KeyEvent.VK_NUMPAD2:
323
+				return DKeyEvent.KeyCode.NUMPAD2;
324
+    		case KeyEvent.VK_NUMPAD3:
325
+				return DKeyEvent.KeyCode.NUMPAD3;
326
+    		case KeyEvent.VK_NUMPAD4:
327
+				return DKeyEvent.KeyCode.NUMPAD4;
328
+    		case KeyEvent.VK_NUMPAD5:
329
+				return DKeyEvent.KeyCode.NUMPAD5;
330
+    		case KeyEvent.VK_NUMPAD6:
331
+				return DKeyEvent.KeyCode.NUMPAD6;
332
+    		case KeyEvent.VK_NUMPAD7:
333
+				return DKeyEvent.KeyCode.NUMPAD7;
334
+    		case KeyEvent.VK_NUMPAD8:
335
+				return DKeyEvent.KeyCode.NUMPAD8;
336
+    		case KeyEvent.VK_NUMPAD9:
337
+				return DKeyEvent.KeyCode.NUMPAD9;
338
+    		case KeyEvent.VK_MULTIPLY:
339
+				return DKeyEvent.KeyCode.MULTIPLY;
340
+    		case KeyEvent.VK_ADD:
341
+				return DKeyEvent.KeyCode.ADD;
342
+			case KeyEvent.VK_SEPARATER:
343
+				return DKeyEvent.KeyCode.SEPARATOR;
344
+    		case KeyEvent.VK_SUBTRACT:
345
+				return DKeyEvent.KeyCode.SUBTRACT;
346
+    		case KeyEvent.VK_DECIMAL:
347
+				return DKeyEvent.KeyCode.DECIMAL;
348
+    		case KeyEvent.VK_DIVIDE:
349
+				return DKeyEvent.KeyCode.DIVIDE;
350
+    		case KeyEvent.VK_DELETE:
351
+				return DKeyEvent.KeyCode.DELETE; /* ASCII DEL */
352
+    		case KeyEvent.VK_NUM_LOCK:
353
+				return DKeyEvent.KeyCode.NUM_LOCK;
354
+    		case KeyEvent.VK_SCROLL_LOCK:
355
+				return DKeyEvent.KeyCode.SCROLL_LOCK;
356
+    		case KeyEvent.VK_F1:
357
+				return DKeyEvent.KeyCode.F1;
358
+    		case KeyEvent.VK_F2:
359
+				return DKeyEvent.KeyCode.F2;
360
+    		case KeyEvent.VK_F3:
361
+				return DKeyEvent.KeyCode.F3;
362
+    		case KeyEvent.VK_F4:
363
+				return DKeyEvent.KeyCode.F4;
364
+    		case KeyEvent.VK_F5:
365
+				return DKeyEvent.KeyCode.F5;
366
+    		case KeyEvent.VK_F6:
367
+				return DKeyEvent.KeyCode.F6;
368
+    		case KeyEvent.VK_F7:
369
+				return DKeyEvent.KeyCode.F7;
370
+    		case KeyEvent.VK_F8:
371
+				return DKeyEvent.KeyCode.F8;
372
+    		case KeyEvent.VK_F9:
373
+				return DKeyEvent.KeyCode.F9;
374
+    		case KeyEvent.VK_F10:
375
+				return DKeyEvent.KeyCode.F10;
376
+    		case KeyEvent.VK_F11:
377
+				return DKeyEvent.KeyCode.F11;
378
+    		case KeyEvent.VK_F12:
379
+				return DKeyEvent.KeyCode.F12;
380
+    		case KeyEvent.VK_F13:
381
+				return DKeyEvent.KeyCode.F13;
382
+    		case KeyEvent.VK_F14:
383
+				return DKeyEvent.KeyCode.F14;
384
+    		case KeyEvent.VK_F15:
385
+				return DKeyEvent.KeyCode.F15;
386
+    		case KeyEvent.VK_F16:
387
+				return DKeyEvent.KeyCode.F16;
388
+    		case KeyEvent.VK_F17:
389
+				return DKeyEvent.KeyCode.F17;
390
+    		case KeyEvent.VK_F18:
391
+				return DKeyEvent.KeyCode.F18;
392
+    		case KeyEvent.VK_F19:
393
+				return DKeyEvent.KeyCode.F19;
394
+    		case KeyEvent.VK_F20:
395
+				return DKeyEvent.KeyCode.F20;
396
+    		case KeyEvent.VK_F21:
397
+				return DKeyEvent.KeyCode.F21;
398
+    		case KeyEvent.VK_F22:
399
+				return DKeyEvent.KeyCode.F22;
400
+    		case KeyEvent.VK_F23:
401
+				return DKeyEvent.KeyCode.F23;
402
+    		case KeyEvent.VK_F24:
403
+				return DKeyEvent.KeyCode.F24;
404
+    		case KeyEvent.VK_PRINTSCREEN:
405
+				return DKeyEvent.KeyCode.PRINTSCREEN;
406
+    		case KeyEvent.VK_INSERT:
407
+				return DKeyEvent.KeyCode.INSERT;
408
+    		case KeyEvent.VK_HELP:
409
+				return DKeyEvent.KeyCode.HELP;
410
+    		case KeyEvent.VK_META:
411
+				return DKeyEvent.KeyCode.META;
412
+    		case KeyEvent.VK_BACK_QUOTE:
413
+				return DKeyEvent.KeyCode.BACKQUOTE;
414
+    		case KeyEvent.VK_QUOTE:
415
+				return DKeyEvent.KeyCode.QUOTE;
416
+    		case KeyEvent.VK_KP_UP:
417
+				return DKeyEvent.KeyCode.KEYPAD_UP;
418
+    		case KeyEvent.VK_KP_DOWN:
419
+				return DKeyEvent.KeyCode.KEYPAD_DOWN;
420
+    		case KeyEvent.VK_KP_LEFT:
421
+				return DKeyEvent.KeyCode.KEYPAD_LEFT;
422
+    		case KeyEvent.VK_KP_RIGHT:
423
+				return DKeyEvent.KeyCode.KEYPAD_RIGHT;
424
+    		case KeyEvent.VK_AMPERSAND:
425
+				return DKeyEvent.KeyCode.AMPERSAND;
426
+    		case KeyEvent.VK_ASTERISK:
427
+				return DKeyEvent.KeyCode.ASTERISK;
428
+    		case KeyEvent.VK_QUOTEDBL:
429
+				return DKeyEvent.KeyCode.QUOTEDBL;
430
+    		case KeyEvent.VK_LESS:
431
+				return DKeyEvent.KeyCode.LESS;
432
+			case KeyEvent.VK_GREATER:
433
+				return DKeyEvent.KeyCode.GREATER;
434
+			case KeyEvent.VK_BRACELEFT:
435
+				return DKeyEvent.KeyCode.BRACELEFT;
436
+			case KeyEvent.VK_BRACERIGHT:
437
+				return DKeyEvent.KeyCode.BRACERIGHT;
438
+    		case KeyEvent.VK_AT:
439
+				return DKeyEvent.KeyCode.AT;
440
+    		case KeyEvent.VK_COLON:
441
+				return DKeyEvent.KeyCode.COLON;
442
+    		case KeyEvent.VK_CIRCUMFLEX:
443
+				return DKeyEvent.KeyCode.CIRCUMFLEX;
444
+    		case KeyEvent.VK_DOLLAR:
445
+				return DKeyEvent.KeyCode.DOLLAR;
446
+    		case KeyEvent.VK_EURO_SIGN:
447
+				return DKeyEvent.KeyCode.EURO_SIGN;
448
+    		case KeyEvent.VK_EXCLAMATION_MARK:
449
+				return DKeyEvent.KeyCode.EXCLAMATION_MARK;
450
+    		case KeyEvent.VK_INVERTED_EXCLAMATION_MARK:
451
+				return DKeyEvent.KeyCode.INVERTED_EXCLAMATION_MARK;
452
+    		case KeyEvent.VK_LEFT_PARENTHESIS:
453
+				return DKeyEvent.KeyCode.LEFT_PARENTHESIS;
454
+    		case KeyEvent.VK_NUMBER_SIGN:
455
+				return DKeyEvent.KeyCode.NUMBER_SIGN;
456
+    		case KeyEvent.VK_PLUS:
457
+				return DKeyEvent.KeyCode.PLUS;
458
+    		case KeyEvent.VK_RIGHT_PARENTHESIS:
459
+				return DKeyEvent.KeyCode.RIGHT_PARENTHESIS;
460
+    		case KeyEvent.VK_UNDERSCORE:
461
+				return DKeyEvent.KeyCode.UNDERSCORE;
462
+    		case KeyEvent.VK_WINDOWS:
463
+				return DKeyEvent.KeyCode.WINDOWS;
464
+    		case KeyEvent.VK_CONTEXT_MENU:
465
+				return DKeyEvent.KeyCode.CONTEXT_MENU;
466
+    		case KeyEvent.VK_FINAL:
467
+				return DKeyEvent.KeyCode.FINAL;
468
+    		case KeyEvent.VK_CONVERT:
469
+				return DKeyEvent.KeyCode.CONVERT;
470
+    		case KeyEvent.VK_NONCONVERT:
471
+				return DKeyEvent.KeyCode.NONCONVERT;
472
+    		case KeyEvent.VK_ACCEPT:
473
+				return DKeyEvent.KeyCode.ACCEPT;
474
+    		case KeyEvent.VK_KANA:
475
+				return DKeyEvent.KeyCode.KANA;
476
+    		case KeyEvent.VK_KANJI:
477
+				return DKeyEvent.KeyCode.KANJI;
478
+    		case KeyEvent.VK_ALPHANUMERIC:
479
+				return DKeyEvent.KeyCode.ALPHANUMERIC;
480
+    		case KeyEvent.VK_KATAKANA:
481
+				return DKeyEvent.KeyCode.KATAKANA;
482
+    		case KeyEvent.VK_HIRAGANA:
483
+				return DKeyEvent.KeyCode.HIRAGANA;
484
+    		case KeyEvent.VK_FULL_WIDTH:
485
+				return DKeyEvent.KeyCode.FULL_WIDTH;
486
+    		case KeyEvent.VK_HALF_WIDTH:
487
+				return DKeyEvent.KeyCode.HALF_WIDTH;
488
+    		case KeyEvent.VK_ROMAN_CHARACTERS:
489
+				return DKeyEvent.KeyCode.ROMAN_CHARACTERS;
490
+    		case KeyEvent.VK_ALL_CANDIDATES:
491
+				return DKeyEvent.KeyCode.ALL_CANDIDATES;
492
+    		case KeyEvent.VK_PREVIOUS_CANDIDATE:
493
+				return DKeyEvent.KeyCode.PREVIOUS_CANDIDATE;
494
+    		case KeyEvent.VK_CODE_INPUT:
495
+				return DKeyEvent.KeyCode.CODE_INPUT;
496
+    		case KeyEvent.VK_JAPANESE_KATAKANA:
497
+				return DKeyEvent.KeyCode.JAPANESE_KATAKANA;
498
+    		case KeyEvent.VK_JAPANESE_HIRAGANA:
499
+				return DKeyEvent.KeyCode.JAPANESE_HIRAGANA;
500
+    		case KeyEvent.VK_JAPANESE_ROMAN:
501
+				return DKeyEvent.KeyCode.JAPANESE_ROMAN;
502
+			case KeyEvent.VK_KANA_LOCK:
503
+				return DKeyEvent.KeyCode.KANA_LOCK;
504
+    		case KeyEvent.VK_INPUT_METHOD_ON_OFF:
505
+				return DKeyEvent.KeyCode.INPUT_METHOD_ON_OFF;
506
+    		case KeyEvent.VK_CUT:
507
+				return DKeyEvent.KeyCode.CUT;
508
+    		case KeyEvent.VK_COPY:
509
+				return DKeyEvent.KeyCode.COPY;
510
+    		case KeyEvent.VK_PASTE:
511
+				return DKeyEvent.KeyCode.PASTE;
512
+    		case KeyEvent.VK_UNDO:
513
+				return DKeyEvent.KeyCode.UNDO;
514
+    		case KeyEvent.VK_AGAIN:
515
+				return DKeyEvent.KeyCode.AGAIN;
516
+    		case KeyEvent.VK_FIND:
517
+				return DKeyEvent.KeyCode.FIND;
518
+    		case KeyEvent.VK_PROPS:
519
+				return DKeyEvent.KeyCode.PROPS;
520
+    		case KeyEvent.VK_STOP:
521
+				return DKeyEvent.KeyCode.STOP;
522
+    		case KeyEvent.VK_COMPOSE:
523
+				return DKeyEvent.KeyCode.COMPOSE;
524
+    		case KeyEvent.VK_ALT_GRAPH:
525
+				return DKeyEvent.KeyCode.ALT_GRAPH;
526
+    		case KeyEvent.VK_BEGIN:
527
+				return DKeyEvent.KeyCode.BEGIN;
528
+			default:
529
+				return DKeyEvent.KeyCode.UNKNOWN;
530
+		}
531
+	}
532
+
533
+	private int getModifiers(int swingModifiers) {
534
+		int result = 0;
535
+		if ((swingModifiers & MouseEvent.BUTTON1_DOWN_MASK) > 0)
536
+			result |= DMouseEvent.BUTTON1;
537
+		if ((swingModifiers & MouseEvent.BUTTON2_DOWN_MASK) > 0)
538
+			result |= DMouseEvent.BUTTON2;
539
+		if ((swingModifiers & MouseEvent.BUTTON3_DOWN_MASK) > 0)
540
+			result |= DMouseEvent.BUTTON3;
541
+		if ((swingModifiers & MouseEvent.SHIFT_DOWN_MASK) > 0)
542
+			result |= DMouseEvent.SHIFT;
543
+		if ((swingModifiers & MouseEvent.CTRL_DOWN_MASK) > 0)
544
+			result |= DMouseEvent.CTRL;
545
+		if ((swingModifiers & MouseEvent.ALT_DOWN_MASK) > 0)
546
+			result |= DMouseEvent.ALT;
547
+		if ((swingModifiers & MouseEvent.ALT_GRAPH_DOWN_MASK) > 0)
548
+			result |= DMouseEvent.ALT_GRAPH;
549
+		if ((swingModifiers & MouseEvent.META_DOWN_MASK) > 0)
550
+			result |= DMouseEvent.META;
551
+		return result;
552
+	}
553
+}

+ 145
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingWindow.java Ver arquivo

@@ -0,0 +1,145 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.swing;
7
+
8
+import java.awt.BorderLayout;
9
+import java.awt.Color;
10
+import java.awt.event.WindowEvent;
11
+import java.awt.event.WindowListener;
12
+import java.awt.event.WindowStateListener;
13
+import javax.swing.JFrame;
14
+import org.openzen.drawablegui.DComponent;
15
+import org.openzen.drawablegui.DUIContext;
16
+import org.openzen.drawablegui.DUIWindow;
17
+import org.openzen.drawablegui.border.DCustomWindowBorder;
18
+import org.openzen.drawablegui.live.LiveBool;
19
+import org.openzen.drawablegui.live.LiveObject;
20
+import org.openzen.drawablegui.live.SimpleLiveBool;
21
+import org.openzen.drawablegui.live.SimpleLiveObject;
22
+import org.openzen.drawablegui.style.DStyleClass;
23
+
24
+/**
25
+ *
26
+ * @author Hoofdgebruiker
27
+ */
28
+public final class SwingWindow extends JFrame implements WindowListener, WindowStateListener, DUIWindow {
29
+	private final SwingRoot swingComponent;
30
+	private final boolean noTitleBar;
31
+	private final SimpleLiveObject<State> state = new SimpleLiveObject<>(State.NORMAL);
32
+	private final SimpleLiveBool active = new SimpleLiveBool(true);
33
+	
34
+	public SwingWindow(String title, DComponent root, boolean noTitleBar) {
35
+		super(title);
36
+		this.noTitleBar = noTitleBar;
37
+		
38
+		if (noTitleBar) {
39
+		    setUndecorated(true);
40
+			root = new DCustomWindowBorder(DStyleClass.EMPTY, root);
41
+			setBackground(new Color(0, 0, 0, 0));
42
+		}
43
+		
44
+		addWindowListener(this);
45
+		addWindowStateListener(this);
46
+		
47
+		getContentPane().add(swingComponent = new SwingRoot(root), BorderLayout.CENTER);
48
+		swingComponent.setWindow(this);
49
+		swingComponent.requestFocusInWindow();
50
+	}
51
+	
52
+	public DUIContext getContext() {
53
+		return swingComponent.context;
54
+	}
55
+
56
+	@Override
57
+	public boolean hasTitleBar() {
58
+		return !noTitleBar;
59
+	}
60
+
61
+	@Override
62
+	public void close() {
63
+		System.exit(0);
64
+	}
65
+
66
+	@Override
67
+	public void maximize() {
68
+		setExtendedState(JFrame.MAXIMIZED_BOTH);
69
+	}
70
+
71
+	@Override
72
+	public void restore() {
73
+		setExtendedState(JFrame.NORMAL);
74
+	}
75
+
76
+	@Override
77
+	public void minimize() {
78
+		setExtendedState(JFrame.ICONIFIED);
79
+	}
80
+
81
+	@Override
82
+	public LiveObject<State> getWindowState() {
83
+		return state;
84
+	}
85
+	
86
+	@Override
87
+	public LiveBool getActive() {
88
+		return active;
89
+	}
90
+
91
+	@Override
92
+	public void windowOpened(WindowEvent e) {
93
+		
94
+	}
95
+
96
+	@Override
97
+	public void windowClosing(WindowEvent e) {
98
+		
99
+	}
100
+
101
+	@Override
102
+	public void windowClosed(WindowEvent e) {
103
+		
104
+	}
105
+
106
+	@Override
107
+	public void windowIconified(WindowEvent e) {
108
+		
109
+	}
110
+
111
+	@Override
112
+	public void windowDeiconified(WindowEvent e) {
113
+		
114
+	}
115
+
116
+	@Override
117
+	public void windowActivated(WindowEvent e) {
118
+		active.setValue(true);
119
+	}
120
+
121
+	@Override
122
+	public void windowDeactivated(WindowEvent e) {
123
+		active.setValue(false);
124
+	}
125
+
126
+	@Override
127
+	public void windowStateChanged(WindowEvent e) {
128
+		state.setValue(getStateFromWindowState());
129
+	}
130
+	
131
+	private State getStateFromWindowState() {
132
+		switch (getExtendedState()) {
133
+			case NORMAL:
134
+				return State.NORMAL;
135
+			case ICONIFIED:
136
+				return State.MINIMIZED;
137
+			case MAXIMIZED_HORIZ:
138
+			case MAXIMIZED_VERT:
139
+			case MAXIMIZED_BOTH:
140
+				return State.MAXIMIZED;
141
+			default:
142
+				return State.NORMAL;
143
+		}
144
+	}
145
+}

+ 35
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/CollapsedArrow.java Ver arquivo

@@ -0,0 +1,35 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.tree;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DDrawable;
10
+import org.openzen.drawablegui.DTransform2D;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class CollapsedArrow implements DDrawable {
17
+	public static final CollapsedArrow INSTANCE = new CollapsedArrow();
18
+	
19
+	private CollapsedArrow() {}
20
+
21
+	@Override
22
+	public void draw(DCanvas canvas, DTransform2D transform) {
23
+		ColoredCollapsedArrow.INSTANCE.draw(canvas, transform, 0xFF000000);
24
+	}
25
+
26
+	@Override
27
+	public float getNominalWidth() {
28
+		return 24;
29
+	}
30
+
31
+	@Override
32
+	public float getNominalHeight() {
33
+		return 24;
34
+	}
35
+}

+ 39
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/ColoredCollapsedArrow.java Ver arquivo

@@ -0,0 +1,39 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.tree;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DPath;
10
+import org.openzen.drawablegui.DTransform2D;
11
+import org.openzen.drawablegui.DColorableIcon;
12
+
13
+public class ColoredCollapsedArrow implements DColorableIcon {
14
+	public static final ColoredCollapsedArrow INSTANCE = new ColoredCollapsedArrow();
15
+	
16
+	private ColoredCollapsedArrow() {}
17
+	
18
+	private static final DPath PATH_0 = tracer -> {
19
+		tracer.moveTo(10, 19);
20
+		tracer.lineTo(17, 12);
21
+		tracer.lineTo(10, 5);
22
+		tracer.close();
23
+	};
24
+	
25
+	@Override
26
+	public void draw(DCanvas canvas, DTransform2D transform, int color) {
27
+		canvas.fillPath(PATH_0, transform, color);
28
+	}
29
+
30
+	@Override
31
+	public float getNominalWidth() {
32
+		return 24;
33
+	}
34
+
35
+	@Override
36
+	public float getNominalHeight() {
37
+		return 24;
38
+	}
39
+}

+ 29
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeNode.java Ver arquivo

@@ -0,0 +1,29 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.tree;
7
+
8
+import org.openzen.drawablegui.DColorableIcon;
9
+import org.openzen.drawablegui.DMouseEvent;
10
+import org.openzen.drawablegui.live.LiveBool;
11
+import org.openzen.drawablegui.live.LiveList;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public interface DTreeNode<N extends DTreeNode<N>> {
18
+	DColorableIcon getIcon();
19
+	
20
+	String getTitle();
21
+	
22
+	LiveList<N> getChildren();
23
+	
24
+	LiveBool isCollapsed();
25
+	
26
+	boolean isLeaf();
27
+	
28
+	default void onMouseClick(DMouseEvent e) {}
29
+}

+ 237
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeView.java Ver arquivo

@@ -0,0 +1,237 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.tree;
7
+
8
+import java.io.Closeable;
9
+import java.util.ArrayList;
10
+import java.util.List;
11
+import org.openzen.drawablegui.DCanvas;
12
+import org.openzen.drawablegui.DComponent;
13
+import org.openzen.drawablegui.DDimensionPreferences;
14
+import org.openzen.drawablegui.DDrawable;
15
+import org.openzen.drawablegui.DFontMetrics;
16
+import org.openzen.drawablegui.DMouseEvent;
17
+import org.openzen.drawablegui.DTransform2D;
18
+import org.openzen.drawablegui.DIRectangle;
19
+import org.openzen.drawablegui.listeners.ListenerHandle;
20
+import org.openzen.drawablegui.live.LiveBool;
21
+import org.openzen.drawablegui.live.LiveObject;
22
+import org.openzen.drawablegui.live.SimpleLiveObject;
23
+import org.openzen.drawablegui.DUIContext;
24
+import org.openzen.drawablegui.style.DStylePath;
25
+
26
+/**
27
+ *
28
+ * @author Hoofdgebruiker
29
+ */
30
+public class DTreeView<N extends DTreeNode<N>> implements DComponent {
31
+	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
32
+	private DIRectangle bounds;
33
+	
34
+	private int selectedRow = -1;
35
+	private N selectedNode = null;
36
+	
37
+	private final DTreeViewStyle styleDefinition;
38
+	private DTreeViewStyle.Calculated style;
39
+	private DFontMetrics fontMetrics;
40
+	
41
+	private DUIContext context;
42
+	private final N root;
43
+	private final boolean showRoot;
44
+	private final List<Row> rows = new ArrayList<>();
45
+	
46
+	public DTreeView(DTreeViewStyle style, N root, boolean showRoot) {
47
+		this.styleDefinition = style;
48
+		this.root = root;
49
+		this.showRoot = showRoot;
50
+	}
51
+
52
+	@Override
53
+	public void setContext(DStylePath parent, DUIContext context) {
54
+		this.context = context;
55
+		style = styleDefinition.forContext(context);
56
+		fontMetrics = context.getFontMetrics(style.font);
57
+		
58
+		updateLayout();
59
+	}
60
+
61
+	@Override
62
+	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
63
+		return dimensionPreferences;
64
+	}
65
+	
66
+	@Override
67
+	public DIRectangle getBounds() {
68
+		return bounds;
69
+	}
70
+
71
+	@Override
72
+	public void setBounds(DIRectangle bounds) {
73
+		this.bounds = bounds;
74
+	}
75
+
76
+	@Override
77
+	public void paint(DCanvas canvas) {
78
+		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, styleDefinition.backgroundColor);
79
+		
80
+		int drawX = bounds.x + style.padding;
81
+		int drawY = bounds.y + style.padding;
82
+		if (showRoot) {
83
+			paintNode(canvas, root, drawX, drawY);
84
+		} else {
85
+			for (N child : root.getChildren()) {
86
+				drawY = paintNode(canvas, child, drawX, drawY);
87
+				drawY += style.rowSpacing;
88
+			}
89
+		}
90
+	}
91
+	
92
+	@Override
93
+	public void onMouseClick(DMouseEvent e) {
94
+		int row = yToRow(e.y);
95
+		if (row >= 0 && row < rows.size()) {
96
+			Row rowEntry = rows.get(row);
97
+			if (e.x >= rowEntry.x && e.x < (rowEntry.x + styleDefinition.nodeOpenedIcon.getNominalWidth())) {
98
+				if (!rowEntry.node.isLeaf())
99
+					rowEntry.node.isCollapsed().toggle();
100
+				return;
101
+			}
102
+			
103
+			rowEntry.node.onMouseClick(e);
104
+			
105
+			if (e.isSingleClick()) {
106
+				int oldRow = selectedRow;
107
+				selectedRow = row;
108
+				selectedNode = rows.get(row).node;
109
+
110
+				if (oldRow >= 0)
111
+					context.repaint(
112
+							bounds.x,
113
+							rowToY(oldRow) - style.selectedPaddingTop,
114
+							bounds.width,
115
+							fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom);
116
+				context.repaint(
117
+						bounds.x,
118
+						rowToY(row) - style.selectedPaddingTop,
119
+						bounds.width,
120
+						fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom);
121
+			}
122
+		}
123
+	}
124
+	
125
+	private int rowToY(int row) {
126
+		return row * (style.rowSpacing + fontMetrics.getAscent() + fontMetrics.getDescent()) + style.padding;
127
+	}
128
+	
129
+	private int yToRow(int y) {
130
+		return (y - bounds.y - style.padding) / (style.rowSpacing + fontMetrics.getAscent() + fontMetrics.getDescent());
131
+	}
132
+	
133
+	private int paintNode(DCanvas canvas, N node, int drawX, int drawY) {
134
+		int textColor = styleDefinition.nodeTextColor;
135
+		if (node == selectedNode) {
136
+			textColor = styleDefinition.selectedNodeTextColor;
137
+			canvas.fillRectangle(
138
+					bounds.x,
139
+					drawY - style.selectedPaddingTop,
140
+					bounds.width,
141
+					fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom,
142
+					styleDefinition.selectedBackgroundColor);
143
+		}
144
+		
145
+		int drawingX = drawX;
146
+		if (!node.isLeaf()) {
147
+			DDrawable icon = node.isCollapsed().getValue() ? style.nodeClosedIcon : style.nodeOpenedIcon;
148
+			icon.draw(canvas, DTransform2D.translate(drawingX, drawY + fontMetrics.getAscent() + fontMetrics.getDescent() - icon.getNominalHeight()));
149
+			drawingX += style.iconTextSpacing + icon.getNominalWidth();
150
+		} else {
151
+			drawingX += style.iconTextSpacing + style.nodeClosedIcon.getNominalWidth();
152
+		}
153
+		node.getIcon().draw(canvas, DTransform2D.translate(drawingX, drawY + fontMetrics.getAscent() + fontMetrics.getDescent() - node.getIcon().getNominalHeight()), textColor);
154
+		drawingX += style.iconTextSpacing + node.getIcon().getNominalWidth();
155
+		canvas.drawText(style.font, textColor, drawingX, drawY + fontMetrics.getAscent(), node.getTitle());
156
+		drawY += fontMetrics.getAscent() + fontMetrics.getDescent();
157
+		
158
+		if (!node.isCollapsed().getValue()) {
159
+			for (N child : node.getChildren()) {
160
+				drawY += style.rowSpacing;
161
+				drawY = paintNode(canvas, child, drawX + style.indent, drawY);
162
+			}
163
+		}
164
+		
165
+		return drawY;
166
+	}
167
+	
168
+	private void updateLayout() {
169
+		int oldRowCount = rows.size();
170
+		
171
+		for (Row row : rows)
172
+			row.close();
173
+		
174
+		rows.clear();
175
+		
176
+		if (showRoot) {
177
+			updateLayout(root, 0);
178
+		} else {
179
+			for (N child : root.getChildren()) {
180
+				updateLayout(child, 0);
181
+			}
182
+		}
183
+		
184
+		if (rows.size() != oldRowCount) {
185
+			DDimensionPreferences preferences = dimensionPreferences.getValue();
186
+			dimensionPreferences.setValue(
187
+					new DDimensionPreferences(
188
+							preferences.minimumWidth,
189
+							preferences.minimumHeight,
190
+							preferences.preferredWidth,
191
+							rowToY(rows.size()),
192
+							preferences.maximumWidth,
193
+							1000000));
194
+		}
195
+		
196
+		System.out.println("Rows after updateLayout: " + rows.size());
197
+		System.out.println("Height: " + rowToY(rows.size()));
198
+	}
199
+	
200
+	private void updateLayout(N node, int x) {
201
+		rows.add(new Row(x, node));
202
+		
203
+		if (!node.isCollapsed().getValue()) {
204
+			for (N child : node.getChildren()) {
205
+				updateLayout(child, x + style.indent);
206
+			}
207
+		}
208
+	}
209
+
210
+	@Override
211
+	public void close() {
212
+		// nothing to clean up
213
+	}
214
+	
215
+	private class Row implements Closeable, LiveBool.Listener {
216
+		private final int x;
217
+		private final N node;
218
+		private final ListenerHandle<LiveBool.Listener> collapseListener;
219
+		
220
+		public Row(int x, N node) {
221
+			this.x = x;
222
+			this.node = node;
223
+			this.collapseListener = node.isCollapsed().addListener(this);
224
+		}
225
+
226
+		@Override
227
+		public void onChanged(boolean oldValue, boolean newValue) {
228
+			updateLayout();
229
+			context.repaint(bounds);
230
+		}
231
+		
232
+		@Override
233
+		public void close() {
234
+			collapseListener.close();
235
+		}
236
+	}
237
+}

+ 91
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeViewStyle.java Ver arquivo

@@ -0,0 +1,91 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.tree;
7
+
8
+import org.openzen.drawablegui.DDrawable;
9
+import org.openzen.drawablegui.DFont;
10
+import org.openzen.drawablegui.DFontFamily;
11
+import org.openzen.drawablegui.style.DDimension;
12
+import org.openzen.drawablegui.style.DDpDimension;
13
+import org.openzen.drawablegui.DUIContext;
14
+
15
+/**
16
+ *
17
+ * @author Hoofdgebruiker
18
+ */
19
+public class DTreeViewStyle {
20
+	public static DTreeViewStyle DEFAULT = new DTreeViewStyle();
21
+	
22
+	public final DDrawable nodeOpenedIcon;
23
+	public final DDrawable nodeClosedIcon;
24
+	public final int backgroundColor;
25
+	public final int borderColor;
26
+	public final DDimension padding;
27
+	public final DDimension rowSpacing;
28
+	public final DDimension fontSize;
29
+	public final DDimension indent;
30
+	public final DDimension iconTextSpacing;
31
+	public final int nodeTextColor;
32
+	public final int selectedNodeTextColor;
33
+	public final int selectedBackgroundColor;
34
+	public final DDimension selectedPaddingTop;
35
+	public final DDimension selectedPaddingBottom;
36
+	
37
+	private DTreeViewStyle() {
38
+		nodeOpenedIcon = ExpandedArrow.INSTANCE;
39
+		nodeClosedIcon = CollapsedArrow.INSTANCE;
40
+		backgroundColor = 0xFFFFFFFF;
41
+		borderColor = 0xFF888888;
42
+		padding = new DDpDimension(3);
43
+		rowSpacing = new DDpDimension(2);
44
+		fontSize = new DDpDimension(12.5f);  
45
+		indent = new DDpDimension(12);
46
+		iconTextSpacing = new DDpDimension(2);
47
+		nodeTextColor = 0xFF000000;
48
+		selectedNodeTextColor = 0xFFFFFFFF;
49
+		selectedBackgroundColor = 0xFF007ACC;
50
+		selectedPaddingTop = new DDpDimension(1);
51
+		selectedPaddingBottom = new DDpDimension(1);
52
+	}
53
+	
54
+	public Calculated forContext(DUIContext context) {
55
+		return new Calculated(this, context);
56
+	}
57
+	
58
+	public static class Calculated {
59
+		public final DDrawable nodeOpenedIcon;
60
+		public final DDrawable nodeClosedIcon;
61
+		public final int backgroundColor;
62
+		public final int borderColor;
63
+		public final int padding;
64
+		public final int rowSpacing;
65
+		public final DFont font;
66
+		public final int indent;
67
+		public final int iconTextSpacing;
68
+		public final int nodeTextColor;
69
+		public final int selectedNodeTextColor;
70
+		public final int selectedBackgroundColor;
71
+		public final int selectedPaddingTop;
72
+		public final int selectedPaddingBottom;
73
+		
74
+		private Calculated(DTreeViewStyle style, DUIContext context) {
75
+			nodeOpenedIcon = style.nodeOpenedIcon;
76
+			nodeClosedIcon = style.nodeClosedIcon;
77
+			backgroundColor = style.backgroundColor;
78
+			borderColor = style.borderColor;
79
+			padding = style.padding.evalInt(context);
80
+			rowSpacing = style.rowSpacing.evalInt(context);
81
+			font = new DFont(DFontFamily.UI, false, false, false, style.fontSize.evalInt(context));
82
+			indent = style.indent.evalInt(context);
83
+			iconTextSpacing = style.iconTextSpacing.evalInt(context);
84
+			nodeTextColor = style.nodeTextColor;
85
+			selectedNodeTextColor = style.selectedNodeTextColor;
86
+			selectedBackgroundColor = style.selectedBackgroundColor;
87
+			selectedPaddingTop = style.selectedPaddingTop.evalInt(context);
88
+			selectedPaddingBottom = style.selectedPaddingBottom.evalInt(context);
89
+		}
90
+	}
91
+}

+ 35
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedArrow.java Ver arquivo

@@ -0,0 +1,35 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.tree;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DDrawable;
10
+import org.openzen.drawablegui.DTransform2D;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class ExpandedArrow implements DDrawable {
17
+	public static final ExpandedArrow INSTANCE = new ExpandedArrow();
18
+	
19
+	private ExpandedArrow() {}
20
+
21
+	@Override
22
+	public void draw(DCanvas canvas, DTransform2D transform) {
23
+		ExpandedColoredArrow.INSTANCE.draw(canvas, transform, 0xFF000000);
24
+	}
25
+
26
+	@Override
27
+	public float getNominalWidth() {
28
+		return 24;
29
+	}
30
+
31
+	@Override
32
+	public float getNominalHeight() {
33
+		return 24;
34
+	}
35
+}

+ 39
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedColoredArrow.java Ver arquivo

@@ -0,0 +1,39 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.tree;
7
+
8
+import org.openzen.drawablegui.DCanvas;
9
+import org.openzen.drawablegui.DPath;
10
+import org.openzen.drawablegui.DTransform2D;
11
+import org.openzen.drawablegui.DColorableIcon;
12
+
13
+public class ExpandedColoredArrow implements DColorableIcon {
14
+	public static final ExpandedColoredArrow INSTANCE = new ExpandedColoredArrow();
15
+	
16
+	private ExpandedColoredArrow() {}
17
+	
18
+	private static final DPath PATH_0 = tracer -> {
19
+		tracer.moveTo(17, 7);
20
+		tracer.lineTo(17, 17);
21
+		tracer.lineTo(7, 17);
22
+		tracer.close();
23
+	};
24
+	
25
+	@Override
26
+	public void draw(DCanvas canvas, DTransform2D transform, int color) {
27
+		canvas.fillPath(PATH_0, transform, color);
28
+	}
29
+
30
+	@Override
31
+	public float getNominalWidth() {
32
+		return 24;
33
+	}
34
+
35
+	@Override
36
+	public float getNominalHeight() {
37
+		return 24;
38
+	}
39
+}

+ 24
- 0
DrawableGuiIconConverter/build.gradle Ver arquivo

@@ -0,0 +1,24 @@
1
+// Note: "common.gradle" in the root project contains additional initialization
2
+//   for this project. This initialization is applied in the "build.gradle"
3
+//   of the root project.
4
+
5
+// NetBeans will automatically add "run" and "debug" tasks relying on the
6
+// "mainClass" property. You may however define the property prior executing
7
+// tasks by passing a "-PmainClass=<QUALIFIED_CLASS_NAME>" argument.
8
+//
9
+// Note however, that you may define your own "run" and "debug" task if you
10
+// prefer. In this case NetBeans will not add these tasks but you may rely on
11
+// your own implementation.
12
+if (!hasProperty('mainClass')) {
13
+    ext.mainClass = 'org.openzen.drawablegui.iconconverter.Main'
14
+}
15
+
16
+dependencies {
17
+    // TODO: Add dependencies here
18
+    //   but note that JUnit should have already been added in parent.gradle.
19
+    //   By default, only the Maven Central Repository is specified in
20
+    //   parent.gradle.
21
+    //
22
+    // You can read more about how to add dependency here:
23
+    //   http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
24
+}

+ 323
- 0
DrawableGuiIconConverter/src/main/java/org/openzen/drawablegui/iconconverter/Main.java Ver arquivo

@@ -0,0 +1,323 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.iconconverter;
7
+
8
+import java.io.File;
9
+import java.util.ArrayList;
10
+import java.util.List;
11
+import javax.xml.parsers.DocumentBuilder;
12
+import javax.xml.parsers.DocumentBuilderFactory;
13
+import org.w3c.dom.Document;
14
+import org.w3c.dom.Element;
15
+import org.w3c.dom.Node;
16
+import org.w3c.dom.NodeList;
17
+
18
+/**
19
+ *
20
+ * @author Hoofdgebruiker
21
+ */
22
+public class Main {
23
+	public static void main(String[] args) throws Exception {
24
+		String filename = "baseline-build-24px.svg"; //args[0];
25
+		//String filename = "baseline-dashboard-24px.svg";
26
+		String className = "BuildIcon";
27
+		File file = new File(filename);
28
+		if (!file.exists()) {
29
+			System.out.println("No such file: " + filename);
30
+			return;
31
+		}
32
+		
33
+		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
34
+		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
35
+		Document doc = dBuilder.parse(file);
36
+		doc.getDocumentElement().normalize();
37
+		
38
+		List<String> pathNames = new ArrayList<>();
39
+		
40
+		Element rootElement = doc.getDocumentElement();
41
+		String width = rootElement.getAttribute("width");
42
+		String height = rootElement.getAttribute("height");
43
+		StringBuilder output = new StringBuilder();
44
+		output.append("import org.openzen.drawablegui.DCanvas;\n");
45
+		output.append("import org.openzen.drawablegui.DPath;\n");
46
+		output.append("import org.openzen.drawablegui.DTransform2D;\n");
47
+		output.append("import org.openzen.drawablegui.DColorableIcon;\n");
48
+		output.append("\n");
49
+		output.append("public class ").append(className).append(" implements DColorableIcon {\n");
50
+		output.append("\tpublic static final ").append(className).append(" INSTANCE = new ").append(className).append("();\n");
51
+		output.append("\t\n");
52
+		output.append("\tprivate ").append(className).append("() {}\n");
53
+		output.append("\t\n");
54
+		
55
+		NodeList childNodes = rootElement.getChildNodes();
56
+		for (int i = 0; i < childNodes.getLength(); i++) {
57
+			Node node = childNodes.item(i);
58
+			if (node.getNodeName().equals("path")) {
59
+				Element pathElement = (Element)node;
60
+				String pathName = "PATH_" + pathNames.size();
61
+				output.append("\tprivate static final DPath ").append(pathName).append(" = tracer -> {\n");
62
+				convertPath(pathElement.getAttribute("d"), output, "\t\t");
63
+				output.append("\t};\n");
64
+				pathNames.add(pathName);
65
+			} else if (node.getNodeName().equals("#text")) {
66
+				// skip
67
+			} else {
68
+				System.out.println("Warning: " + node.getNodeName() + " not supported");
69
+			}
70
+		}
71
+		
72
+		output.append("\t\n");
73
+		output.append("\t@Override\n");
74
+		output.append("\tpublic void draw(DCanvas canvas, DTransform2D transform, int color) {\n");
75
+		for (String pathName : pathNames) {
76
+			output.append("\t\tcanvas.fillPath(").append(pathName).append(", transform, color);\n");
77
+		}
78
+		output.append("\t}\n");
79
+		output.append("\n");
80
+		output.append("\t@Override\n");
81
+		output.append("\tpublic float getNominalWidth() {\n");
82
+		output.append("\t\treturn ").append(width).append(";\n");
83
+		output.append("\t}\n");
84
+		output.append("\n");
85
+		output.append("\t@Override\n");
86
+		output.append("\tpublic float getNominalHeight() {\n");
87
+		output.append("\t\treturn ").append(height).append(";\n");
88
+		output.append("\t}\n");
89
+		output.append("}\n");
90
+		System.out.println(output.toString());
91
+	}
92
+	
93
+	private static void convertPath(String path, StringBuilder output, String indent) {
94
+		CharStream stream = new CharStream(path);
95
+		float x = 0;
96
+		float y = 0;
97
+		float guideX = 0;
98
+		float guideY = 0;
99
+		char instruction = stream.next();
100
+		while (stream.hasMore()) {
101
+			if (!stream.nextIsNumber())
102
+				instruction = stream.next();
103
+			
104
+			switch (instruction) {
105
+				case 'M': {
106
+					String sx = stream.nextFloat();
107
+					String sy = stream.nextFloat();
108
+					output.append(indent).append("tracer.moveTo(")
109
+							.append(sx).append("f, ")
110
+							.append(sy).append("f);\n");
111
+					x = Float.parseFloat(sx);
112
+					y = Float.parseFloat(sy);
113
+					break;
114
+				}
115
+				case 'm': {
116
+					x += stream.parseFloat();
117
+					y += stream.parseFloat();
118
+					output.append(indent)
119
+							.append("tracer.moveTo(")
120
+							.append(x).append("f, ")
121
+							.append(y).append("f);\n");
122
+					break;
123
+				}
124
+				case 'L': {
125
+					String sx = stream.nextFloat();
126
+					String sy = stream.nextFloat();
127
+					output.append(indent).append("tracer.lineTo(")
128
+							.append(sx).append("f, ")
129
+							.append(sy).append("f);\n");
130
+					x = Float.parseFloat(sx);
131
+					y = Float.parseFloat(sy);
132
+					break;
133
+				}
134
+				case 'l': {
135
+					x += stream.parseFloat();
136
+					y += stream.parseFloat();
137
+					output.append(indent)
138
+							.append("tracer.lineTo(")
139
+							.append(x).append("f, ")
140
+							.append(y).append("f);\n");
141
+					break;
142
+				}
143
+				case 'H': {
144
+					x = stream.parseFloat();
145
+					output.append(indent)
146
+							.append("tracer.lineTo(")
147
+							.append(x).append("f, ")
148
+							.append(y).append("f);\n");
149
+					break;
150
+				}
151
+				case 'h': {
152
+					x += stream.parseFloat();
153
+					output.append(indent)
154
+							.append("tracer.lineTo(")
155
+							.append(x).append("f, ")
156
+							.append(y).append("f);\n");
157
+					break;
158
+				}
159
+				case 'V': {
160
+					y = stream.parseFloat();
161
+					output.append(indent)
162
+							.append("tracer.lineTo(")
163
+							.append(x).append("f, ")
164
+							.append(y).append("f);\n");
165
+					break;
166
+				}
167
+				case 'v': {
168
+					y += stream.parseFloat();
169
+					output.append(indent)
170
+							.append("tracer.lineTo(")
171
+							.append(x).append("f, ")
172
+							.append(y).append("f);\n");
173
+					break;
174
+				}
175
+				case 'C': {
176
+					float x1 = stream.parseFloat();
177
+					float y1 = stream.parseFloat();
178
+					float x2 = stream.parseFloat();
179
+					float y2 = stream.parseFloat();
180
+					float x3 = stream.parseFloat();
181
+					float y3 = stream.parseFloat();
182
+					output.append(indent)
183
+							.append("tracer.bezierCubic(")
184
+							.append(x1).append("f, ")
185
+							.append(y1).append("f, ")
186
+							.append(x2).append("f, ")
187
+							.append(y2).append("f, ")
188
+							.append(x3).append("f, ")
189
+							.append(y3).append("f);\n");
190
+					x = x3;
191
+					y = y3;
192
+					guideX = x2;
193
+					guideY = y2;
194
+					break;
195
+				}
196
+				case 'c': {
197
+					float x1 = x + stream.parseFloat();
198
+					float y1 = y + stream.parseFloat();
199
+					float x2 = x + stream.parseFloat();
200
+					float y2 = y + stream.parseFloat();
201
+					float x3 = x + stream.parseFloat();
202
+					float y3 = y + stream.parseFloat();
203
+					x = x3;
204
+					y = y3;
205
+					guideX = x2;
206
+					guideY = y2;
207
+					output.append(indent)
208
+							.append("tracer.bezierCubic(")
209
+							.append(x1).append("f, ")
210
+							.append(y1).append("f, ")
211
+							.append(x2).append("f, ")
212
+							.append(y2).append("f, ")
213
+							.append(x3).append("f, ")
214
+							.append(y3).append("f);\n");
215
+					break;
216
+				}
217
+				case 'S': {
218
+					float x1 = x + (x - guideX);
219
+					float y1 = y + (y - guideY);
220
+					float x2 = stream.parseFloat();
221
+					float y2 = stream.parseFloat();
222
+					float x3 = stream.parseFloat();
223
+					float y3 = stream.parseFloat();
224
+					output.append(indent)
225
+							.append("tracer.bezierCubic(")
226
+							.append(x1).append("f, ")
227
+							.append(y1).append("f, ")
228
+							.append(x2).append("f, ")
229
+							.append(y2).append("f, ")
230
+							.append(x3).append("f, ")
231
+							.append(y3).append("f);\n");
232
+					x = x3;
233
+					y = y3;
234
+					guideX = x2;
235
+					guideY = y2;
236
+					break;
237
+				}
238
+				case 's': {
239
+					float x1 = x + (x - guideX);
240
+					float y1 = y + (y - guideY);
241
+					float x2 = x + stream.parseFloat();
242
+					float y2 = y + stream.parseFloat();
243
+					float x3 = x + stream.parseFloat();
244
+					float y3 = y + stream.parseFloat();
245
+					x = x3;
246
+					y = y3;
247
+					guideX = x2;
248
+					guideY = y2;
249
+					output.append(indent)
250
+							.append("tracer.bezierCubic(")
251
+							.append(x1).append("f, ")
252
+							.append(y1).append("f, ")
253
+							.append(x2).append("f, ")
254
+							.append(y2).append("f, ")
255
+							.append(x3).append("f, ")
256
+							.append(y3).append("f);\n");
257
+					break;
258
+				}
259
+				case 'Z':
260
+				case 'z':
261
+					output.append(indent).append("tracer.close();\n");
262
+					break;
263
+				default:
264
+					System.out.println("Error: path instruction " + instruction + " not supported");
265
+					return;
266
+			}
267
+		}
268
+	}
269
+	
270
+	private static class CharStream {
271
+		private int index;
272
+		private final String value;
273
+		
274
+		public CharStream(String value) {
275
+			this.index = 0;
276
+			this.value = value;
277
+		}
278
+		
279
+		public char next() {
280
+			skipWhitespace();
281
+			return value.charAt(index++);
282
+		}
283
+		
284
+		public boolean hasMore() {
285
+			return index < value.length();
286
+		}
287
+		
288
+		public boolean nextIsNumber() {
289
+			skipWhitespace();
290
+			char c = value.charAt(index);
291
+			return c == '-' || (c >= '0' && c <= '9');
292
+		}
293
+		
294
+		public String nextFloat() {
295
+			skipWhitespace();
296
+			int from = index;
297
+			if (value.charAt(index) == '-')
298
+				index++;
299
+			
300
+			char next = value.charAt(index);
301
+			while (next >= '0' && next <= '9')
302
+				next = value.charAt(++index);
303
+			if (value.charAt(index) == '.') {
304
+				index++;
305
+				next = value.charAt(index);
306
+				while (next >= '0' && next <= '9')
307
+					next = value.charAt(++index);
308
+			}
309
+			
310
+			return value.substring(from, index);
311
+		}
312
+		
313
+		public float parseFloat() {
314
+			return Float.parseFloat(nextFloat());
315
+		}
316
+		
317
+		public void skipWhitespace() {
318
+			char next = value.charAt(index);
319
+			while (next == ' ' || next == '\t' || next == '\r' || next == '\n' || next == ',')
320
+				next = value.charAt(++index);
321
+		}
322
+	}
323
+}

+ 19
- 0
IDE/build.gradle Ver arquivo

@@ -0,0 +1,19 @@
1
+// Note: "common.gradle" in the root project contains additional initialization
2
+//   for this project. This initialization is applied in the "build.gradle"
3
+//   of the root project.
4
+
5
+// NetBeans will automatically add "run" and "debug" tasks relying on the
6
+// "mainClass" property. You may however define the property prior executing
7
+// tasks by passing a "-PmainClass=<QUALIFIED_CLASS_NAME>" argument.
8
+//
9
+// Note however, that you may define your own "run" and "debug" task if you
10
+// prefer. In this case NetBeans will not add these tasks but you may rely on
11
+// your own implementation.
12
+if (!hasProperty('mainClass')) {
13
+    ext.mainClass = 'org.openzen.zenscript.ide.Main'
14
+}
15
+
16
+dependencies {
17
+	compile project(':DrawableGui')
18
+	compile project(':Constructor')
19
+}

+ 35
- 0
IDE/src/main/java/org/openzen/zenscript/ide/Main.java Ver arquivo

@@ -0,0 +1,35 @@
1
+package org.openzen.zenscript.ide;
2
+
3
+import java.io.File;
4
+import java.io.IOException;
5
+import javax.swing.JFrame;
6
+import org.openzen.zenscript.ide.host.DevelopmentHost;
7
+import org.openzen.zenscript.ide.host.local.LocalProjectDevelopmentHost;
8
+import org.openzen.drawablegui.swing.SwingWindow;
9
+import org.openzen.zenscript.constructor.ModuleLoader;
10
+import org.openzen.zenscript.constructor.Project;
11
+import org.openzen.zenscript.ide.ui.IDEWindow;
12
+import org.openzen.zenscript.ide.ui.view.WindowView;
13
+
14
+public class Main {
15
+    /**
16
+     * @param args the command line arguments
17
+     */
18
+    public static void main(String[] args) throws IOException {
19
+		File directory = new File("../../ZenCode");
20
+		ModuleLoader loader = new ModuleLoader();
21
+		Project project = new Project(loader, directory);
22
+		
23
+		DevelopmentHost host = new LocalProjectDevelopmentHost(project);
24
+		
25
+		int pixelPerInch = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();
26
+		
27
+		IDEWindow window = new IDEWindow();
28
+		WindowView root = new WindowView(window, host);
29
+		
30
+		SwingWindow swingWindow = new SwingWindow("ZenCode IDE - " + host.getName(), root, false);
31
+		swingWindow.setSize(800 * pixelPerInch / 96, 600 * pixelPerInch / 96);
32
+		swingWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
33
+		swingWindow.setVisible(true);
34
+    }
35
+}

+ 20
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/DevelopmentHost.java Ver arquivo

@@ -0,0 +1,20 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host;
7
+
8
+import org.openzen.drawablegui.live.LiveList;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface DevelopmentHost {
15
+	public String getName();
16
+	
17
+	public LiveList<IDEModule> getModules();
18
+	
19
+	public LiveList<IDELibrary> getLibraries();
20
+}

+ 18
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/IDELibrary.java Ver arquivo

@@ -0,0 +1,18 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host;
7
+
8
+import org.openzen.drawablegui.live.LiveList;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface IDELibrary {
15
+	public String getName();
16
+	
17
+	public LiveList<IDEModule> getModules();
18
+}

+ 16
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/IDEModule.java Ver arquivo

@@ -0,0 +1,16 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface IDEModule {
13
+	public String getName();
14
+	
15
+	public IDEPackage getRootPackage();
16
+}

+ 20
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/IDEPackage.java Ver arquivo

@@ -0,0 +1,20 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host;
7
+
8
+import org.openzen.drawablegui.live.LiveList;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface IDEPackage {
15
+	public String getName();
16
+	
17
+	public LiveList<IDEPackage> getSubPackages();
18
+	
19
+	public LiveList<IDESourceFile> getSourceFiles();
20
+}

+ 21
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/IDESourceFile.java Ver arquivo

@@ -0,0 +1,21 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host;
7
+
8
+import java.io.IOException;
9
+import java.io.Reader;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface IDESourceFile {
16
+	public String getName();
17
+	
18
+	public Reader read() throws IOException;
19
+	
20
+	public void update(String content);
21
+}

+ 39
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalLibrary.java Ver arquivo

@@ -0,0 +1,39 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host.local;
7
+
8
+import org.openzen.drawablegui.live.LiveArrayList;
9
+import org.openzen.drawablegui.live.LiveList;
10
+import org.openzen.zenscript.constructor.Library;
11
+import org.openzen.zenscript.constructor.module.ModuleReference;
12
+import org.openzen.zenscript.ide.host.IDELibrary;
13
+import org.openzen.zenscript.ide.host.IDEModule;
14
+
15
+/**
16
+ *
17
+ * @author Hoofdgebruiker
18
+ */
19
+public class LocalLibrary implements IDELibrary {
20
+	private final Library library;
21
+	private final LiveList<IDEModule> modules;
22
+	
23
+	public LocalLibrary(Library library) {
24
+		this.library = library;
25
+		modules = new LiveArrayList<>();
26
+		for (ModuleReference module : library.modules)
27
+			modules.add(new LocalModule(module));
28
+	}
29
+
30
+	@Override
31
+	public String getName() {
32
+		return library.name;
33
+	}
34
+
35
+	@Override
36
+	public LiveList<IDEModule> getModules() {
37
+		return modules;
38
+	}
39
+}

+ 32
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalModule.java Ver arquivo

@@ -0,0 +1,32 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host.local;
7
+
8
+import org.openzen.zenscript.constructor.module.ModuleReference;
9
+import org.openzen.zenscript.ide.host.IDEModule;
10
+import org.openzen.zenscript.ide.host.IDEPackage;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class LocalModule implements IDEModule {
17
+	private final ModuleReference module;
18
+	
19
+	public LocalModule(ModuleReference module) {
20
+		this.module = module;
21
+	}
22
+
23
+	@Override
24
+	public String getName() {
25
+		return module.getName();
26
+	}
27
+
28
+	@Override
29
+	public IDEPackage getRootPackage() {
30
+		return new LocalPackage(module.getRootPackage());
31
+	}
32
+}

+ 57
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalPackage.java Ver arquivo

@@ -0,0 +1,57 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host.local;
7
+
8
+import java.util.Arrays;
9
+import org.openzen.drawablegui.live.LiveArrayList;
10
+import org.openzen.drawablegui.live.LiveList;
11
+import org.openzen.zenscript.constructor.module.SourcePackage;
12
+import org.openzen.zenscript.ide.host.IDEPackage;
13
+import org.openzen.zenscript.ide.host.IDESourceFile;
14
+
15
+/**
16
+ *
17
+ * @author Hoofdgebruiker
18
+ */
19
+public class LocalPackage implements IDEPackage {
20
+	private final SourcePackage pkg;
21
+	private final LiveList<IDEPackage> subPackages = new LiveArrayList<>();
22
+	private final LiveList<IDESourceFile> sourceFiles = new LiveArrayList<>();
23
+	
24
+	public LocalPackage(SourcePackage pkg) {
25
+		this.pkg = pkg;
26
+		
27
+		String[] subPackageKeys = pkg.subPackages.keySet()
28
+				.toArray(new String[pkg.subPackages.size()]);
29
+		Arrays.sort(subPackageKeys);
30
+		
31
+		String[] sourceFileKeys = pkg.sourceFiles.keySet()
32
+				.toArray(new String[pkg.sourceFiles.size()]);
33
+		Arrays.sort(sourceFileKeys);
34
+		
35
+		for (String subKey : subPackageKeys) {
36
+			subPackages.add(new LocalPackage(pkg.subPackages.get(subKey)));
37
+		}
38
+		for (String sourceFileKey : sourceFileKeys) {
39
+			sourceFiles.add(new LocalSourceFile(pkg.sourceFiles.get(sourceFileKey)));
40
+		}
41
+	}
42
+	
43
+	@Override
44
+	public String getName() {
45
+		return pkg.name;
46
+	}
47
+
48
+	@Override
49
+	public LiveList<IDEPackage> getSubPackages() {
50
+		return subPackages;
51
+	}
52
+
53
+	@Override
54
+	public LiveList<IDESourceFile> getSourceFiles() {
55
+		return sourceFiles;
56
+	}
57
+}

+ 53
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalProjectDevelopmentHost.java Ver arquivo

@@ -0,0 +1,53 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host.local;
7
+
8
+import java.util.List;
9
+import org.openzen.drawablegui.live.LiveArrayList;
10
+import org.openzen.drawablegui.live.LiveList;
11
+import org.openzen.zenscript.constructor.Library;
12
+import org.openzen.zenscript.constructor.Project;
13
+import org.openzen.zenscript.constructor.module.ModuleReference;
14
+import org.openzen.zenscript.ide.host.DevelopmentHost;
15
+import org.openzen.zenscript.ide.host.IDEModule;
16
+import org.openzen.zenscript.ide.host.IDELibrary;
17
+
18
+/**
19
+ *
20
+ * @author Hoofdgebruiker
21
+ */
22
+public class LocalProjectDevelopmentHost implements DevelopmentHost {
23
+	private final Project project;
24
+	private final LiveList<IDEModule> modules;
25
+	private final LiveList<IDELibrary> libraries;
26
+	
27
+	public LocalProjectDevelopmentHost(Project project) {
28
+		this.project = project;
29
+		
30
+		modules = new LiveArrayList<>();
31
+		for (ModuleReference module : project.modules)
32
+			modules.add(new LocalModule(module));
33
+		
34
+		libraries = new LiveArrayList<>();
35
+		for (Library library : project.libraries)
36
+			libraries.add(new LocalLibrary(library));
37
+	}
38
+	
39
+	@Override
40
+	public String getName() {
41
+		return project.name;
42
+	}
43
+
44
+	@Override
45
+	public LiveList<IDEModule> getModules() {
46
+		return modules;
47
+	}
48
+
49
+	@Override
50
+	public LiveList<IDELibrary> getLibraries() {
51
+		return libraries;
52
+	}
53
+}

+ 54
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalSourceFile.java Ver arquivo

@@ -0,0 +1,54 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.host.local;
7
+
8
+import java.io.BufferedInputStream;
9
+import java.io.BufferedOutputStream;
10
+import java.io.FileInputStream;
11
+import java.io.FileOutputStream;
12
+import java.io.IOException;
13
+import java.io.InputStreamReader;
14
+import java.io.OutputStreamWriter;
15
+import java.io.Reader;
16
+import java.io.Writer;
17
+import java.nio.charset.StandardCharsets;
18
+import org.openzen.zenscript.constructor.module.SourceFile;
19
+import org.openzen.zenscript.ide.host.IDESourceFile;
20
+
21
+/**
22
+ *
23
+ * @author Hoofdgebruiker
24
+ */
25
+public class LocalSourceFile implements IDESourceFile {
26
+	private final SourceFile file;
27
+	
28
+	public LocalSourceFile(SourceFile file) {
29
+		this.file = file;
30
+	}
31
+
32
+	@Override
33
+	public String getName() {
34
+		return file.name;
35
+	}
36
+
37
+	@Override
38
+	public Reader read() throws IOException {
39
+		return new InputStreamReader(
40
+				new BufferedInputStream(new FileInputStream(file.file)),
41
+				StandardCharsets.UTF_8);
42
+	}
43
+
44
+	@Override
45
+	public void update(String content) {
46
+		try {
47
+			Writer writer = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(file.file)), StandardCharsets.UTF_8);
48
+			writer.write(content);
49
+			writer.close();
50
+		} catch (IOException ex) {
51
+			ex.printStackTrace();
52
+		}
53
+	}
54
+}

+ 20
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectBar.java Ver arquivo

@@ -0,0 +1,20 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.ui;
7
+
8
+import org.openzen.drawablegui.live.LiveArrayList;
9
+import org.openzen.drawablegui.live.LiveList;
10
+import org.openzen.drawablegui.live.LiveObject;
11
+import org.openzen.drawablegui.live.SimpleLiveObject;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class IDEAspectBar {
18
+	public final LiveList<IDEAspectToolbar> toolbars = new LiveArrayList<>(); // TODO: only expose read-only variant
19
+	public final LiveObject<IDEAspectToolbar> active = new SimpleLiveObject<>(null);
20
+}

+ 0
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectBarControl.java Ver arquivo


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff

Carregando…
Cancelar
Salvar