Browse Source

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

kindlich 6 years ago
parent
commit
1ae12a4538
No known key found for this signature in database
100 changed files with 3180 additions and 1442 deletions
  1. 3
    2
      CompilerShared/src/main/java/org/openzen/zenscript/compiler/SemanticModule.java
  2. 3
    3
      Constructor/src/main/java/org/openzen/zenscript/constructor/Library.java
  3. 10
    5
      Constructor/src/main/java/org/openzen/zenscript/constructor/Main.java
  4. 10
    6
      Constructor/src/main/java/org/openzen/zenscript/constructor/Module.java
  5. 6
    2
      Constructor/src/main/java/org/openzen/zenscript/constructor/ModuleLoader.java
  6. 7
    5
      Constructor/src/main/java/org/openzen/zenscript/constructor/Project.java
  7. 7
    7
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleReference.java
  8. 4
    1
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/ModuleReference.java
  9. 87
    37
      DrawableGui/src/main/java/org/openzen/drawablegui/DButton.java
  10. 0
    67
      DrawableGui/src/main/java/org/openzen/drawablegui/DCanvas.java
  11. 3
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIcon.java
  12. 104
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIconInstance.java
  13. 5
    8
      DrawableGui/src/main/java/org/openzen/drawablegui/DComponent.java
  14. 6
    4
      DrawableGui/src/main/java/org/openzen/drawablegui/DCompositeIcon.java
  15. 3
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/DDrawable.java
  16. 94
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DDrawableInstance.java
  17. 7
    6
      DrawableGui/src/main/java/org/openzen/drawablegui/DEmptyView.java
  18. 4
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DFontMetrics.java
  19. 0
    273
      DrawableGui/src/main/java/org/openzen/drawablegui/DHorizontalLayout.java
  20. 0
    31
      DrawableGui/src/main/java/org/openzen/drawablegui/DHorizontalLayoutStyle.java
  21. 40
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DIRectangle.java
  22. 98
    49
      DrawableGui/src/main/java/org/openzen/drawablegui/DInputField.java
  23. 6
    19
      DrawableGui/src/main/java/org/openzen/drawablegui/DInputFieldStyle.java
  24. 38
    12
      DrawableGui/src/main/java/org/openzen/drawablegui/DLabel.java
  25. 49
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DPath.java
  26. 24
    48
      DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltip.java
  27. 128
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltipComponent.java
  28. 3
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltipStyle.java
  29. 0
    26
      DrawableGui/src/main/java/org/openzen/drawablegui/DTooltip.java
  30. 0
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/DUIContext.java
  31. 1
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/DUIWindow.java
  32. 0
    274
      DrawableGui/src/main/java/org/openzen/drawablegui/DVerticalLayout.java
  33. 0
    31
      DrawableGui/src/main/java/org/openzen/drawablegui/DVerticalLayoutStyle.java
  34. 22
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/Destructible.java
  35. 15
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DBorder.java
  36. 9
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCompositeBorder.java
  37. 63
    42
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java
  38. 9
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java
  39. 15
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java
  40. 11
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DPaddedBorder.java
  41. 107
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DSideBorder.java
  42. 22
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawSurface.java
  43. 37
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawTarget.java
  44. 14
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnColorableElement.java
  45. 20
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnElement.java
  46. 16
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnRectangle.java
  47. 3
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnShape.java
  48. 21
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnText.java
  49. 24
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DSubSurface.java
  50. 42
    25
      DrawableGui/src/main/java/org/openzen/drawablegui/form/DForm.java
  51. 463
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/layout/DLinearLayout.java
  52. 24
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/layout/DLinearLayoutStyle.java
  53. 40
    20
      DrawableGui/src/main/java/org/openzen/drawablegui/layout/DSideLayout.java
  54. 20
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/layout/DSideLayoutStyle.java
  55. 30
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/InverseLiveBool.java
  56. 2
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveConcatList.java
  57. 5
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveMappedList.java
  58. 2
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePredicateBool.java
  59. 8
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveInt.java
  60. 3
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveObject.java
  61. 3
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveString.java
  62. 49
    24
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java
  63. 56
    127
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java
  64. 3
    6
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPaneStyle.java
  65. 45
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DBaseStyle.java
  66. 22
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DBorderElement.java
  67. 23
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DColorElement.java
  68. 6
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DDimension.java
  69. 16
    7
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStyleDefinition.java
  70. 23
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStylesheet.java
  71. 1
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStylesheets.java
  72. 23
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DFontElement.java
  73. 49
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DMargin.java
  74. 20
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DMarginElement.java
  75. 2
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DPxDimension.java
  76. 23
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DRectangleShape.java
  77. 36
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DRoundedRectangleShape.java
  78. 1
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DShadow.java
  79. 21
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DShadowElement.java
  80. 17
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DShape.java
  81. 22
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DShapeElement.java
  82. 100
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DSimpleStylesheet.java
  83. 13
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleClass.java
  84. 7
    5
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleDefinition.java
  85. 45
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleElement.java
  86. 4
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePath.java
  87. 12
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePathRoot.java
  88. 16
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylesheet.java
  89. 66
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylesheetBuilder.java
  90. 0
    209
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingCanvas.java
  91. 22
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDialog.java
  92. 202
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawSurface.java
  93. 35
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnElement.java
  94. 57
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnRectangle.java
  95. 68
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnText.java
  96. 75
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingFilledPath.java
  97. 29
    19
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingGraphicsContext.java
  98. 156
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingInlineWindow.java
  99. 15
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingRoot.java
  100. 0
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingShadowedPath.java

+ 3
- 2
CompilerShared/src/main/java/org/openzen/zenscript/compiler/SemanticModule.java View File

9
 import java.util.HashMap;
9
 import java.util.HashMap;
10
 import java.util.List;
10
 import java.util.List;
11
 import java.util.Map;
11
 import java.util.Map;
12
+import java.util.function.Consumer;
12
 import org.openzen.zenscript.codemodel.annotations.AnnotationDefinition;
13
 import org.openzen.zenscript.codemodel.annotations.AnnotationDefinition;
13
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
14
 import org.openzen.zenscript.codemodel.HighLevelDefinition;
14
 import org.openzen.zenscript.codemodel.PackageDefinitions;
15
 import org.openzen.zenscript.codemodel.PackageDefinitions;
93
 				annotations);
94
 				annotations);
94
 	}
95
 	}
95
 	
96
 	
96
-	public boolean validate() {
97
+	public boolean validate(Consumer<ValidationLogEntry> logger) {
97
 		if (state != State.NORMALIZED)
98
 		if (state != State.NORMALIZED)
98
 			throw new IllegalStateException("Module is not yet normalized");
99
 			throw new IllegalStateException("Module is not yet normalized");
99
 		
100
 		
106
 		}
107
 		}
107
 		
108
 		
108
 		for (ValidationLogEntry entry : validator.getLog()) {
109
 		for (ValidationLogEntry entry : validator.getLog()) {
109
-			System.out.println(entry.kind + " " + entry.position.toString() + ": " + entry.message);
110
+			logger.accept(entry);
110
 		}
111
 		}
111
 		state = validator.hasErrors() ? State.INVALID : State.VALIDATED;
112
 		state = validator.hasErrors() ? State.INVALID : State.VALIDATED;
112
 		return !validator.hasErrors();
113
 		return !validator.hasErrors();

+ 3
- 3
Constructor/src/main/java/org/openzen/zenscript/constructor/Library.java View File

8
 import java.io.File;
8
 import java.io.File;
9
 import org.json.JSONArray;
9
 import org.json.JSONArray;
10
 import org.json.JSONObject;
10
 import org.json.JSONObject;
11
-import org.openzen.zenscript.constructor.module.DirectoryModuleLoader;
11
+import org.openzen.zenscript.constructor.module.DirectoryModuleReference;
12
 import org.openzen.zenscript.constructor.module.ModuleReference;
12
 import org.openzen.zenscript.constructor.module.ModuleReference;
13
 
13
 
14
 /**
14
 /**
20
 	public final File directory;
20
 	public final File directory;
21
 	public final ModuleReference[] modules;
21
 	public final ModuleReference[] modules;
22
 	
22
 	
23
-	public Library(ModuleLoader loader, File directory, String name, JSONObject json) {
23
+	public Library(File directory, String name, JSONObject json) {
24
 		this.name = name;
24
 		this.name = name;
25
 		this.directory = new File(directory, json.getString("directory"));
25
 		this.directory = new File(directory, json.getString("directory"));
26
 		
26
 		
28
 		modules = new ModuleReference[modulesJson.length()];
28
 		modules = new ModuleReference[modulesJson.length()];
29
 		for (int i = 0; i < modulesJson.length(); i++) {
29
 		for (int i = 0; i < modulesJson.length(); i++) {
30
 			String moduleName = modulesJson.getString(i);
30
 			String moduleName = modulesJson.getString(i);
31
-			modules[i] = new DirectoryModuleLoader(loader, moduleName, new File(this.directory, moduleName), false);
31
+			modules[i] = new DirectoryModuleReference(moduleName, new File(this.directory, moduleName), false);
32
 		}
32
 		}
33
 	}
33
 	}
34
 }
34
 }

+ 10
- 5
Constructor/src/main/java/org/openzen/zenscript/constructor/Main.java View File

1
 package org.openzen.zenscript.constructor;
1
 package org.openzen.zenscript.constructor;
2
 
2
 
3
-import org.openzen.zenscript.compiler.CompilationUnit;
4
 import java.io.File;
3
 import java.io.File;
4
+import org.openzen.zenscript.compiler.CompilationUnit;
5
 import java.io.IOException;
5
 import java.io.IOException;
6
-import org.openzen.zenscript.constructor.module.DirectoryModuleLoader;
6
+import java.util.function.Consumer;
7
+import org.openzen.zencode.shared.CompileException;
8
+import org.openzen.zenscript.constructor.module.DirectoryModuleReference;
7
 import org.openzen.zenscript.constructor.module.ModuleReference;
9
 import org.openzen.zenscript.constructor.module.ModuleReference;
8
 
10
 
9
 public class Main {
11
 public class Main {
18
 			return;
20
 			return;
19
 		}
21
 		}
20
 		
22
 		
23
+		Consumer<CompileException> exceptionLogger = exception -> System.err.println(exception.toString());
24
+		
21
 		File currentDirectory = new File(arguments.directory);
25
 		File currentDirectory = new File(arguments.directory);
22
 		CompilationUnit compilationUnit = new CompilationUnit();
26
 		CompilationUnit compilationUnit = new CompilationUnit();
23
-		ModuleLoader moduleLoader = new ModuleLoader(compilationUnit);
24
-		moduleLoader.register("stdlib", new DirectoryModuleLoader(moduleLoader, "stdlib", new File("../../StdLibs/stdlib"), true));
25
 		
27
 		
26
-		Project project = new Project(moduleLoader, currentDirectory);
28
+		ModuleLoader moduleLoader = new ModuleLoader(compilationUnit, exceptionLogger);
29
+		moduleLoader.register("stdlib", new DirectoryModuleReference("stdlib", new File("../../StdLibs/stdlib"), true));
30
+		
31
+		Project project = new Project(currentDirectory);
27
 		for (Library library : project.libraries) {
32
 		for (Library library : project.libraries) {
28
 			for (ModuleReference module : library.modules)
33
 			for (ModuleReference module : library.modules)
29
 				moduleLoader.register(module.getName(), module);
34
 				moduleLoader.register(module.getName(), module);

+ 10
- 6
Constructor/src/main/java/org/openzen/zenscript/constructor/Module.java View File

13
 import java.util.Collections;
13
 import java.util.Collections;
14
 import java.util.List;
14
 import java.util.List;
15
 import java.util.Map;
15
 import java.util.Map;
16
+import java.util.function.Consumer;
16
 import org.json.JSONArray;
17
 import org.json.JSONArray;
17
 import org.json.JSONObject;
18
 import org.json.JSONObject;
18
 import org.json.JSONTokener;
19
 import org.json.JSONTokener;
36
 	public final File sourceDirectory;
37
 	public final File sourceDirectory;
37
 	public final String packageName;
38
 	public final String packageName;
38
 	public final String host;
39
 	public final String host;
40
+	private final Consumer<CompileException> exceptionLogger;
39
 	
41
 	
40
-	public Module(String name, File directory, File moduleFile) throws IOException {
42
+	public Module(String name, File directory, File moduleFile, Consumer<CompileException> exceptionLogger) throws IOException {
41
 		this.name = name;
43
 		this.name = name;
42
 		this.sourceDirectory = new File(directory, "src");
44
 		this.sourceDirectory = new File(directory, "src");
45
+		this.exceptionLogger = exceptionLogger;
43
 		
46
 		
44
 		BufferedInputStream input = new BufferedInputStream(new FileInputStream(moduleFile));
47
 		BufferedInputStream input = new BufferedInputStream(new FileInputStream(moduleFile));
45
 		JSONObject json = new JSONObject(new JSONTokener(input));
48
 		JSONObject json = new JSONObject(new JSONTokener(input));
67
 				try {
70
 				try {
68
 					files.add(ParsedFile.parse(pkg, file));
71
 					files.add(ParsedFile.parse(pkg, file));
69
 				} catch (CompileException ex) {
72
 				} catch (CompileException ex) {
70
-					System.out.println(ex.getMessage());
73
+					exceptionLogger.accept(ex);
71
 				}
74
 				}
72
 			} else if (file.isDirectory()) {
75
 			} else if (file.isDirectory()) {
73
 				parse(files, pkg.getOrCreatePackage(file.getName()), file);
76
 				parse(files, pkg.getOrCreatePackage(file.getName()), file);
80
 			String[] dependencies,
83
 			String[] dependencies,
81
 			ZSPackage pkg,
84
 			ZSPackage pkg,
82
 			ParsedFile[] files,
85
 			ParsedFile[] files,
83
-			ModuleSpace registry) {
86
+			ModuleSpace registry,
87
+			Consumer<CompileException> exceptionLogger) {
84
 		// We are considering all these files to be in the same package, so make
88
 		// We are considering all these files to be in the same package, so make
85
 		// a single PackageDefinition instance. If these files were in multiple
89
 		// a single PackageDefinition instance. If these files were in multiple
86
 		// packages, we'd need an instance for every package.
90
 		// packages, we'd need an instance for every package.
106
 			try {
110
 			try {
107
 				file.compileTypes(rootPackage, pkg, definitions, registry.compilationUnit.globalTypeRegistry, expansions, globals, registry.getAnnotations());
111
 				file.compileTypes(rootPackage, pkg, definitions, registry.compilationUnit.globalTypeRegistry, expansions, globals, registry.getAnnotations());
108
 			} catch (CompileException ex) {
112
 			} catch (CompileException ex) {
109
-				System.out.println(ex.getMessage());
113
+				exceptionLogger.accept(ex);
110
 				failed = true;
114
 				failed = true;
111
 			}
115
 			}
112
 		}
116
 		}
121
 			try {
125
 			try {
122
 				file.compileMembers(rootPackage, pkg, definitions, registry.compilationUnit.globalTypeRegistry, expansions, globals, registry.getAnnotations());
126
 				file.compileMembers(rootPackage, pkg, definitions, registry.compilationUnit.globalTypeRegistry, expansions, globals, registry.getAnnotations());
123
 			} catch (CompileException ex) {
127
 			} catch (CompileException ex) {
124
-				System.out.println(ex.getMessage());
128
+				exceptionLogger.accept(ex);
125
 				failed = true;
129
 				failed = true;
126
 			}
130
 			}
127
 		}
131
 		}
138
 			try {
142
 			try {
139
 				file.compileCode(rootPackage, pkg, definitions, registry.compilationUnit.globalTypeRegistry, expansions, scripts, globals, registry.getAnnotations());
143
 				file.compileCode(rootPackage, pkg, definitions, registry.compilationUnit.globalTypeRegistry, expansions, scripts, globals, registry.getAnnotations());
140
 			} catch (CompileException ex) {
144
 			} catch (CompileException ex) {
141
-				System.out.println(ex.getMessage());
145
+				exceptionLogger.accept(ex);
142
 				failed = true;
146
 				failed = true;
143
 			}
147
 			}
144
 		}
148
 		}

+ 6
- 2
Constructor/src/main/java/org/openzen/zenscript/constructor/ModuleLoader.java View File

10
 import java.util.HashSet;
10
 import java.util.HashSet;
11
 import java.util.Map;
11
 import java.util.Map;
12
 import java.util.Stack;
12
 import java.util.Stack;
13
+import java.util.function.Consumer;
14
+import org.openzen.zencode.shared.CompileException;
13
 import org.openzen.zenscript.constructor.module.ModuleReference;
15
 import org.openzen.zenscript.constructor.module.ModuleReference;
14
 import org.openzen.zenscript.compiler.SemanticModule;
16
 import org.openzen.zenscript.compiler.SemanticModule;
15
 
17
 
25
 	private final Stack<String> compilingModulesStack = new Stack<>();
27
 	private final Stack<String> compilingModulesStack = new Stack<>();
26
 	
28
 	
27
 	private final CompilationUnit compilationUnit;
29
 	private final CompilationUnit compilationUnit;
30
+	private final Consumer<CompileException> exceptionLogger;
28
 	
31
 	
29
-	public ModuleLoader(CompilationUnit compilationUnit) {
32
+	public ModuleLoader(CompilationUnit compilationUnit, Consumer<CompileException> exceptionLogger) {
30
 		this.compilationUnit = compilationUnit;
33
 		this.compilationUnit = compilationUnit;
34
+		this.exceptionLogger = exceptionLogger;
31
 	}
35
 	}
32
 	
36
 	
33
 	public SemanticModule getModule(String name) {
37
 	public SemanticModule getModule(String name) {
49
 		compilingModulesSet.add(name);
53
 		compilingModulesSet.add(name);
50
 		compilingModulesStack.add(name);
54
 		compilingModulesStack.add(name);
51
 		
55
 		
52
-		SemanticModule module = modules.get(name).load(compilationUnit);
56
+		SemanticModule module = modules.get(name).load(this, compilationUnit, exceptionLogger);
53
 		moduleCache.put(name, module);
57
 		moduleCache.put(name, module);
54
 		
58
 		
55
 		compilingModulesSet.remove(name);
59
 		compilingModulesSet.remove(name);

+ 7
- 5
Constructor/src/main/java/org/openzen/zenscript/constructor/Project.java View File

9
 import java.io.IOException;
9
 import java.io.IOException;
10
 import java.util.ArrayList;
10
 import java.util.ArrayList;
11
 import java.util.List;
11
 import java.util.List;
12
+import java.util.function.Consumer;
12
 import org.json.JSONArray;
13
 import org.json.JSONArray;
13
 import org.json.JSONObject;
14
 import org.json.JSONObject;
14
-import org.openzen.zenscript.constructor.module.DirectoryModuleLoader;
15
+import org.openzen.zencode.shared.CompileException;
16
+import org.openzen.zenscript.constructor.module.DirectoryModuleReference;
15
 import org.openzen.zenscript.constructor.module.ModuleReference;
17
 import org.openzen.zenscript.constructor.module.ModuleReference;
16
 import org.openzen.zenscript.compiler.Target;
18
 import org.openzen.zenscript.compiler.Target;
17
 import org.openzen.zenscript.compiler.TargetType;
19
 import org.openzen.zenscript.compiler.TargetType;
27
 	public final Library[] libraries;
29
 	public final Library[] libraries;
28
 	public final Target[] targets;
30
 	public final Target[] targets;
29
 	
31
 	
30
-	public Project(ModuleLoader loader, File directory) throws IOException {
32
+	public Project(File directory) throws IOException {
31
 		this.directory = directory;
33
 		this.directory = directory;
32
 		name = directory.getName();
34
 		name = directory.getName();
33
 		
35
 		
46
 		libraries = new Library[jsonLibraries.length()];
48
 		libraries = new Library[jsonLibraries.length()];
47
 		int k = 0;
49
 		int k = 0;
48
 		for (String key : jsonLibraries.keySet()) {
50
 		for (String key : jsonLibraries.keySet()) {
49
-			libraries[k] = new Library(loader, directory, key, jsonLibraries.getJSONObject(key));
51
+			libraries[k] = new Library(directory, key, jsonLibraries.getJSONObject(key));
50
 			k++;
52
 			k++;
51
 		}
53
 		}
52
 		
54
 		
55
 		for (int i = 0; i < jsonModules.length(); i++) {
57
 		for (int i = 0; i < jsonModules.length(); i++) {
56
 			Object module = jsonModules.get(i);
58
 			Object module = jsonModules.get(i);
57
 			if (module instanceof String) {
59
 			if (module instanceof String) {
58
-				modules[i] = new DirectoryModuleLoader(loader, module.toString(), new File(directory, module.toString()), false);
60
+				modules[i] = new DirectoryModuleReference(module.toString(), new File(directory, module.toString()), false);
59
 			} else if (module instanceof JSONObject) {
61
 			} else if (module instanceof JSONObject) {
60
 				JSONObject jsonModule = (JSONObject) module;
62
 				JSONObject jsonModule = (JSONObject) module;
61
 				String name = jsonModule.getString("name");
63
 				String name = jsonModule.getString("name");
62
 				switch (jsonModule.getString("type")) {
64
 				switch (jsonModule.getString("type")) {
63
 					case "directory":
65
 					case "directory":
64
-						modules[i] = new DirectoryModuleLoader(loader, name, new File(directory, jsonModule.getString("directory")), false);
66
+						modules[i] = new DirectoryModuleReference(name, new File(directory, jsonModule.getString("directory")), false);
65
 						break;
67
 						break;
66
 					default:
68
 					default:
67
 						throw new ConstructorException("Invalid module type: " + jsonModule.getString("type"));
69
 						throw new ConstructorException("Invalid module type: " + jsonModule.getString("type"));

Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java → Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleReference.java View File

10
 import java.io.IOException;
10
 import java.io.IOException;
11
 import java.util.ArrayList;
11
 import java.util.ArrayList;
12
 import java.util.List;
12
 import java.util.List;
13
+import java.util.function.Consumer;
13
 import org.json.JSONArray;
14
 import org.json.JSONArray;
14
 import org.json.JSONObject;
15
 import org.json.JSONObject;
16
+import org.openzen.zencode.shared.CompileException;
15
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
17
 import org.openzen.zenscript.codemodel.definition.ZSPackage;
16
 import org.openzen.zenscript.compiler.CompilationUnit;
18
 import org.openzen.zenscript.compiler.CompilationUnit;
17
 import org.openzen.zenscript.constructor.ConstructorException;
19
 import org.openzen.zenscript.constructor.ConstructorException;
25
  *
27
  *
26
  * @author Hoofdgebruiker
28
  * @author Hoofdgebruiker
27
  */
29
  */
28
-public class DirectoryModuleLoader implements ModuleReference {
29
-	private final ModuleLoader loader;
30
+public class DirectoryModuleReference implements ModuleReference {
30
 	private final String moduleName;
31
 	private final String moduleName;
31
 	private final File directory;
32
 	private final File directory;
32
 	private final boolean isStdlib;
33
 	private final boolean isStdlib;
33
 	private SourcePackage rootPackage = null;
34
 	private SourcePackage rootPackage = null;
34
 	
35
 	
35
-	public DirectoryModuleLoader(ModuleLoader loader, String moduleName, File directory, boolean isStdlib) {
36
-		this.loader = loader;
36
+	public DirectoryModuleReference(String moduleName, File directory, boolean isStdlib) {
37
 		this.moduleName = moduleName;
37
 		this.moduleName = moduleName;
38
 		this.directory = directory;
38
 		this.directory = directory;
39
 		this.isStdlib = isStdlib;
39
 		this.isStdlib = isStdlib;
45
 	}
45
 	}
46
 
46
 
47
 	@Override
47
 	@Override
48
-	public SemanticModule load(CompilationUnit unit) {
48
+	public SemanticModule load(ModuleLoader loader, CompilationUnit unit, Consumer<CompileException> exceptionLogger) {
49
 		if (!directory.exists())
49
 		if (!directory.exists())
50
 			throw new ConstructorException("Error: module directory not found: " + directory);
50
 			throw new ConstructorException("Error: module directory not found: " + directory);
51
 		
51
 		
71
 			for (String dependencyName : dependencyNames)
71
 			for (String dependencyName : dependencyNames)
72
 				space.addModule(dependencyName, loader.getModule(dependencyName));
72
 				space.addModule(dependencyName, loader.getModule(dependencyName));
73
 
73
 
74
-			Module module = new Module(moduleName, directory, jsonFile);
74
+			Module module = new Module(moduleName, directory, jsonFile, exceptionLogger);
75
 			ZSPackage pkg = isStdlib ? unit.globalTypeRegistry.stdlib : new ZSPackage(null, module.packageName);
75
 			ZSPackage pkg = isStdlib ? unit.globalTypeRegistry.stdlib : new ZSPackage(null, module.packageName);
76
 
76
 
77
 			ParsedFile[] parsedFiles = module.parse(pkg);
77
 			ParsedFile[] parsedFiles = module.parse(pkg);
78
-			SemanticModule result = Module.compileSyntaxToSemantic(module.name, module.dependencies, pkg, parsedFiles, space);
78
+			SemanticModule result = Module.compileSyntaxToSemantic(module.name, module.dependencies, pkg, parsedFiles, space, exceptionLogger);
79
 			
79
 			
80
 			JSONObject globals = json.optJSONObject("globals");
80
 			JSONObject globals = json.optJSONObject("globals");
81
 			if (globals != null) {
81
 			if (globals != null) {

+ 4
- 1
Constructor/src/main/java/org/openzen/zenscript/constructor/module/ModuleReference.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.constructor.module;
6
 package org.openzen.zenscript.constructor.module;
7
 
7
 
8
+import java.util.function.Consumer;
9
+import org.openzen.zencode.shared.CompileException;
8
 import org.openzen.zenscript.compiler.SemanticModule;
10
 import org.openzen.zenscript.compiler.SemanticModule;
9
 import org.openzen.zenscript.compiler.CompilationUnit;
11
 import org.openzen.zenscript.compiler.CompilationUnit;
12
+import org.openzen.zenscript.constructor.ModuleLoader;
10
 
13
 
11
 /**
14
 /**
12
  *
15
  *
15
 public interface ModuleReference {
18
 public interface ModuleReference {
16
 	public String getName();
19
 	public String getName();
17
 	
20
 	
18
-	public SemanticModule load(CompilationUnit unit);
21
+	public SemanticModule load(ModuleLoader loader, CompilationUnit unit, Consumer<CompileException> exceptionLogger);
19
 	
22
 	
20
 	public SourcePackage getRootPackage();
23
 	public SourcePackage getRootPackage();
21
 }
24
 }

+ 87
- 37
DrawableGui/src/main/java/org/openzen/drawablegui/DButton.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawSurface;
9
+import org.openzen.drawablegui.draw.DDrawnShape;
10
+import org.openzen.drawablegui.draw.DDrawnText;
8
 import org.openzen.drawablegui.live.LiveBool;
11
 import org.openzen.drawablegui.live.LiveBool;
9
 import org.openzen.drawablegui.live.LiveObject;
12
 import org.openzen.drawablegui.live.LiveObject;
10
 import org.openzen.drawablegui.live.LiveString;
13
 import org.openzen.drawablegui.live.LiveString;
24
 	private final LiveBool disabled;
27
 	private final LiveBool disabled;
25
 	private final Runnable action;
28
 	private final Runnable action;
26
 	
29
 	
27
-	private DUIContext context;
30
+	private DDrawSurface surface;
31
+	private int z;
28
 	private DIRectangle bounds;
32
 	private DIRectangle bounds;
29
 	
33
 	
30
 	private DButtonStyle style;
34
 	private DButtonStyle style;
33
 	private boolean hovering = false;
37
 	private boolean hovering = false;
34
 	private boolean pressing = false;
38
 	private boolean pressing = false;
35
 	
39
 	
40
+	private DDrawnShape shape;
41
+	private DDrawnText text;
42
+	private DShadow currentShadow;
43
+	
36
 	public DButton(DStyleClass styleClass, LiveString label, LiveBool disabled, Runnable action) {
44
 	public DButton(DStyleClass styleClass, LiveString label, LiveBool disabled, Runnable action) {
37
 		this.styleClass = styleClass;
45
 		this.styleClass = styleClass;
38
 		this.label = label;
46
 		this.label = label;
39
 		this.disabled = disabled;
47
 		this.disabled = disabled;
40
 		this.action = action;
48
 		this.action = action;
41
 	}
49
 	}
42
-
50
+	
43
 	@Override
51
 	@Override
44
-	public void setContext(DStylePath parent, DUIContext context) {
45
-		this.context = context;
52
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
53
+		this.surface = surface;
54
+		this.z = z;
46
 		
55
 		
47
 		DStylePath path = parent.getChild("Button", styleClass);
56
 		DStylePath path = parent.getChild("Button", styleClass);
48
-		this.style = new DButtonStyle(context.getStylesheets().get(context, path));
49
-		fontMetrics = context.getFontMetrics(style.font);
57
+		this.style = new DButtonStyle(surface.getStylesheet(path));
58
+		fontMetrics = surface.getFontMetrics(style.font);
50
 		
59
 		
51
 		sizing.setValue(new DSizing(
60
 		sizing.setValue(new DSizing(
52
 				style.paddingLeft + style.paddingRight + fontMetrics.getWidth(label.getValue()),
61
 				style.paddingLeft + style.paddingRight + fontMetrics.getWidth(label.getValue()),
53
 				style.paddingTop + style.paddingBottom + fontMetrics.getAscent() + fontMetrics.getDescent()));
62
 				style.paddingTop + style.paddingBottom + fontMetrics.getAscent() + fontMetrics.getDescent()));
63
+		currentShadow = getShadow();
64
+	}
65
+	
66
+	@Override
67
+	public void unmount() {
68
+		surface = null;
69
+		
70
+		if (shape != null)
71
+			shape.close();
72
+		if (text != null)
73
+			text.close();
54
 	}
74
 	}
55
 
75
 
56
 	@Override
76
 	@Override
71
 	@Override
91
 	@Override
72
 	public void setBounds(DIRectangle bounds) {
92
 	public void setBounds(DIRectangle bounds) {
73
 		this.bounds = bounds;
93
 		this.bounds = bounds;
74
-	}
75
-
76
-	@Override
77
-	public void paint(DCanvas canvas) {
78
-		int backgroundColor = style.backgroundColorNormal;
79
-		DShadow shadow = style.shadowNormal;
80
-		if (hovering) {
81
-			backgroundColor = style.backgroundColorHover;
82
-			shadow = style.shadowNormal;
83
-		}
84
-		if (pressing) {
85
-			backgroundColor = style.backgroundColorPress;
86
-			shadow = style.shadowPress;
87
-		}
88
-		if (disabled.getValue()) {
89
-			backgroundColor = style.backgroundColorDisabled;
90
-			shadow = style.shadowDisabled;
91
-		}
92
 		
94
 		
93
-		DPath shape = DPath.roundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, 2 * context.getScale());
94
-		canvas.shadowPath(shape, DTransform2D.IDENTITY, shadow);
95
-		canvas.fillPath(shape, DTransform2D.IDENTITY, backgroundColor);
96
-		canvas.drawText(style.font, style.textColor, bounds.x + style.paddingLeft, bounds.y + style.paddingTop + fontMetrics.getAscent(), label.getValue());
95
+		if (shape != null)
96
+			shape.close();
97
+		if (text != null)
98
+			text.close();
99
+		
100
+		shape = surface.shadowPath(
101
+				z,
102
+				DPath.roundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, 2 * surface.getScale()),
103
+				DTransform2D.IDENTITY,
104
+				getBackgroundColor(),
105
+				currentShadow);
106
+		text = surface.drawText(
107
+				z +  1, 
108
+				style.font,
109
+				style.textColor,
110
+				bounds.x + style.paddingLeft,
111
+				bounds.y + style.paddingTop + fontMetrics.getAscent(),
112
+				label.getValue());
97
 	}
113
 	}
98
 
114
 
99
 	@Override
115
 	@Override
100
 	public void close() {
116
 	public void close() {
101
-		
117
+		unmount();
102
 	}
118
 	}
103
 	
119
 	
104
 	@Override
120
 	@Override
105
 	public void onMouseEnter(DMouseEvent e) {
121
 	public void onMouseEnter(DMouseEvent e) {
106
 		hovering = true;
122
 		hovering = true;
107
-		repaint();
123
+		update();
108
 	}
124
 	}
109
 	
125
 	
110
 	@Override
126
 	@Override
111
 	public void onMouseExit(DMouseEvent e) {
127
 	public void onMouseExit(DMouseEvent e) {
112
 		hovering = false;
128
 		hovering = false;
113
 		pressing = false;
129
 		pressing = false;
114
-		repaint();
130
+		update();
115
 	}
131
 	}
116
 	
132
 	
117
 	@Override
133
 	@Override
118
 	public void onMouseDown(DMouseEvent e) {
134
 	public void onMouseDown(DMouseEvent e) {
119
 		pressing = true;
135
 		pressing = true;
120
-		repaint();
136
+		update();
121
 	}
137
 	}
122
 	
138
 	
123
 	@Override
139
 	@Override
128
 			action.run();
144
 			action.run();
129
 		}
145
 		}
130
 		
146
 		
131
-		repaint();
147
+		update();
148
+	}
149
+	
150
+	private void update() {
151
+		DShadow newShadow = getShadow();
152
+		if (newShadow != currentShadow) {
153
+			currentShadow = newShadow;
154
+			
155
+			if (shape != null)
156
+				shape.close();
157
+			
158
+			shape = surface.shadowPath(
159
+				z,
160
+				DPath.roundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, 2 * surface.getScale()),
161
+				DTransform2D.IDENTITY,
162
+				getBackgroundColor(),
163
+				currentShadow);
164
+		} else {
165
+			shape.setColor(getBackgroundColor());
166
+		}
167
+	}
168
+	
169
+	private DShadow getShadow() {
170
+		if (disabled.getValue())
171
+			return style.shadowDisabled;
172
+		if (pressing)
173
+			return style.shadowPress;
174
+		if (hovering)
175
+			return style.shadowHover;
176
+		
177
+		return style.shadowNormal;
132
 	}
178
 	}
133
 	
179
 	
134
-	private void repaint() {
135
-		if (context == null || bounds == null)
136
-			return;
180
+	private int getBackgroundColor() {
181
+		if (disabled.getValue())
182
+			return style.backgroundColorDisabled;
183
+		if (pressing)
184
+			return style.backgroundColorPress;
185
+		if (hovering)
186
+			return style.backgroundColorHover;
137
 		
187
 		
138
-		context.repaint(bounds);
188
+		return style.backgroundColorNormal;
139
 	}
189
 	}
140
 }
190
 }

+ 0
- 67
DrawableGui/src/main/java/org/openzen/drawablegui/DCanvas.java View File

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
-}

+ 3
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIcon.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawTarget;
9
+
8
 /**
10
 /**
9
  *
11
  *
10
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
11
  */
13
  */
12
 public interface DColorableIcon {
14
 public interface DColorableIcon {
13
-	void draw(DCanvas canvas, DTransform2D transform, int color);
15
+	void draw(DDrawTarget target, int z, DTransform2D transform, int color);
14
 	
16
 	
15
 	float getNominalWidth();
17
 	float getNominalWidth();
16
 	
18
 	

+ 104
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIconInstance.java View File

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 org.openzen.drawablegui.draw.DDrawSurface;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
13
+import org.openzen.drawablegui.draw.DDrawnColorableElement;
14
+import org.openzen.drawablegui.draw.DDrawnElement;
15
+import org.openzen.drawablegui.draw.DDrawnRectangle;
16
+import org.openzen.drawablegui.draw.DDrawnShape;
17
+import org.openzen.drawablegui.draw.DDrawnText;
18
+import org.openzen.drawablegui.style.DShadow;
19
+
20
+/**
21
+ *
22
+ * @author Hoofdgebruiker
23
+ */
24
+public final class DColorableIconInstance implements Closeable {
25
+	private final List<DDrawnElement> elements = new ArrayList<>();
26
+	private final List<DDrawnColorableElement> colorables = new ArrayList<>();
27
+	
28
+	public DColorableIconInstance(DDrawSurface surface, int z, DColorableIcon icon, DTransform2D transform, int color) {
29
+		icon.draw(new DrawTarget(surface), z, transform, DDrawTarget.INSTANCE_COLOR);
30
+		setColor(color);
31
+	}
32
+	
33
+	public void setColor(int color) {
34
+		for (DDrawnColorableElement colorable : colorables)
35
+			colorable.setColor(color);
36
+	}
37
+	
38
+	public void setTransform(DTransform2D transform) {
39
+		for (DDrawnElement element : elements)
40
+			element.setTransform(transform);
41
+	}
42
+	
43
+	@Override
44
+	public void close() {
45
+		for (DDrawnElement element : elements)
46
+			element.close();
47
+	}
48
+	
49
+	private class DrawTarget implements DDrawTarget {
50
+		private final DDrawSurface surface;
51
+		
52
+		public DrawTarget(DDrawSurface surface) {
53
+			this.surface = surface;
54
+		}
55
+
56
+		@Override
57
+		public DFontMetrics getFontMetrics(DFont font) {
58
+			return surface.getFontMetrics(font);
59
+		}
60
+
61
+		@Override
62
+		public float getScale() {
63
+			return surface.getScale();
64
+		}
65
+
66
+		@Override
67
+		public float getTextScale() {
68
+			return surface.getTextScale();
69
+		}
70
+
71
+		@Override
72
+		public DDrawnText drawText(int z, DFont font, int color, float x, float y, String text) {
73
+			return addColorable(surface.drawText(z, font, color, x, y, text), color);
74
+		}
75
+
76
+		@Override
77
+		public DDrawnRectangle fillRect(int z, DIRectangle rectangle, int color) {
78
+			return addColorable(surface.fillRect(z, rectangle, color), color);
79
+		}
80
+
81
+		@Override
82
+		public DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth) {
83
+			return addColorable(surface.strokePath(z, path, transform, color, lineWidth), color);
84
+		}
85
+
86
+		@Override
87
+		public DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color) {
88
+			return addColorable(surface.fillPath(z, path, transform, color), color);
89
+		}
90
+
91
+		@Override
92
+		public DDrawnShape shadowPath(int z, DPath path, DTransform2D transform, int color, DShadow shadow) {
93
+			return addColorable(surface.shadowPath(z, path, transform, color, shadow), color);
94
+		}
95
+		
96
+		private <T extends DDrawnColorableElement> T addColorable(T colorable, int color) {
97
+			if (color == DDrawTarget.INSTANCE_COLOR)
98
+				colorables.add(colorable);
99
+			
100
+			elements.add(colorable);
101
+			return colorable;
102
+		}
103
+	}
104
+}

+ 5
- 8
DrawableGui/src/main/java/org/openzen/drawablegui/DComponent.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
-import java.io.Closeable;
8
+import org.openzen.drawablegui.draw.DDrawSurface;
9
 import org.openzen.drawablegui.live.LiveObject;
9
 import org.openzen.drawablegui.live.LiveObject;
10
 import org.openzen.drawablegui.style.DStylePath;
10
 import org.openzen.drawablegui.style.DStylePath;
11
 
11
 
13
  *
13
  *
14
  * @author Hoofdgebruiker
14
  * @author Hoofdgebruiker
15
  */
15
  */
16
-public interface DComponent extends Closeable {
17
-	void setContext(DStylePath parent, DUIContext context);
16
+public interface DComponent extends Destructible {
17
+	void mount(DStylePath parent, int z, DDrawSurface surface);
18
+	
19
+	void unmount();
18
 	
20
 	
19
 	LiveObject<DSizing> getSizing();
21
 	LiveObject<DSizing> getSizing();
20
 	
22
 	
24
 	
26
 	
25
 	void setBounds(DIRectangle bounds);
27
 	void setBounds(DIRectangle bounds);
26
 	
28
 	
27
-	void paint(DCanvas canvas);
28
-	
29
 	default void onMounted() {}
29
 	default void onMounted() {}
30
 	
30
 	
31
 	default void onUnmounted() {}
31
 	default void onUnmounted() {}
55
 	default void onKeyPressed(DKeyEvent e) {}
55
 	default void onKeyPressed(DKeyEvent e) {}
56
 	
56
 	
57
 	default void onKeyReleased(DKeyEvent e) {}
57
 	default void onKeyReleased(DKeyEvent e) {}
58
-	
59
-	@Override
60
-	void close();
61
 }
58
 }

+ 6
- 4
DrawableGui/src/main/java/org/openzen/drawablegui/DCompositeIcon.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawTarget;
9
+
8
 /**
10
 /**
9
  *
11
  *
10
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
19
 		this.addition = addition;
21
 		this.addition = addition;
20
 		this.additionTransform = additionTransform;
22
 		this.additionTransform = additionTransform;
21
 	}
23
 	}
22
-
24
+	
23
 	@Override
25
 	@Override
24
-	public void draw(DCanvas canvas, DTransform2D transform, int color) {
25
-		base.draw(canvas, transform, color);
26
-		addition.draw(canvas, transform.mul(additionTransform), color);
26
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
27
+		base.draw(target, z, transform, color);
28
+		addition.draw(target, z + 1, transform.mul(additionTransform), color);
27
 	}
29
 	}
28
 
30
 
29
 	@Override
31
 	@Override

+ 3
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/DDrawable.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawTarget;
9
+
8
 /**
10
 /**
9
  *
11
  *
10
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
11
  */
13
  */
12
 public interface DDrawable {
14
 public interface DDrawable {
13
-	void draw(DCanvas canvas, DTransform2D transform);
15
+	void draw(DDrawTarget target, int z, DTransform2D transform);
14
 	
16
 	
15
 	float getNominalWidth();
17
 	float getNominalWidth();
16
 	
18
 	

+ 94
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DDrawableInstance.java View File

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 org.openzen.drawablegui.draw.DDrawSurface;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
13
+import org.openzen.drawablegui.draw.DDrawnColorableElement;
14
+import org.openzen.drawablegui.draw.DDrawnElement;
15
+import org.openzen.drawablegui.draw.DDrawnRectangle;
16
+import org.openzen.drawablegui.draw.DDrawnShape;
17
+import org.openzen.drawablegui.draw.DDrawnText;
18
+import org.openzen.drawablegui.style.DShadow;
19
+
20
+/**
21
+ *
22
+ * @author Hoofdgebruiker
23
+ */
24
+public class DDrawableInstance implements Closeable {
25
+	private final List<DDrawnElement> elements = new ArrayList<>();
26
+	
27
+	public DDrawableInstance(DDrawSurface surface, int z, DDrawable icon, DTransform2D transform) {
28
+		icon.draw(new DrawTarget(surface), z, transform);
29
+	}
30
+	
31
+	public void setTransform(DTransform2D transform) {
32
+		for (DDrawnElement element : elements)
33
+			element.setTransform(transform);
34
+	}
35
+	
36
+	@Override
37
+	public void close() {
38
+		for (DDrawnElement element : elements)
39
+			element.close();
40
+	}
41
+	
42
+	private class DrawTarget implements DDrawTarget {
43
+		private final DDrawSurface surface;
44
+		
45
+		public DrawTarget(DDrawSurface surface) {
46
+			this.surface = surface;
47
+		}
48
+
49
+		@Override
50
+		public DFontMetrics getFontMetrics(DFont font) {
51
+			return surface.getFontMetrics(font);
52
+		}
53
+
54
+		@Override
55
+		public float getScale() {
56
+			return surface.getScale();
57
+		}
58
+
59
+		@Override
60
+		public float getTextScale() {
61
+			return surface.getTextScale();
62
+		}
63
+
64
+		@Override
65
+		public DDrawnText drawText(int z, DFont font, int color, float x, float y, String text) {
66
+			return addElement(surface.drawText(z, font, color, x, y, text));
67
+		}
68
+
69
+		@Override
70
+		public DDrawnRectangle fillRect(int z, DIRectangle rectangle, int color) {
71
+			return addElement(surface.fillRect(z, rectangle, color));
72
+		}
73
+
74
+		@Override
75
+		public DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth) {
76
+			return addElement(surface.strokePath(z, path, transform, color, lineWidth));
77
+		}
78
+
79
+		@Override
80
+		public DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color) {
81
+			return addElement(surface.fillPath(z, path, transform, color));
82
+		}
83
+
84
+		@Override
85
+		public DDrawnShape shadowPath(int z, DPath path, DTransform2D transform, int color, DShadow shadow) {
86
+			return addElement(surface.shadowPath(z, path, transform, color, shadow));
87
+		}
88
+		
89
+		private <T extends DDrawnColorableElement> T addElement(T colorable) {
90
+			elements.add(colorable);
91
+			return colorable;
92
+		}
93
+	}
94
+}

+ 7
- 6
DrawableGui/src/main/java/org/openzen/drawablegui/DEmptyView.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawSurface;
8
 import org.openzen.drawablegui.live.ImmutableLiveObject;
9
 import org.openzen.drawablegui.live.ImmutableLiveObject;
9
 import org.openzen.drawablegui.live.LiveObject;
10
 import org.openzen.drawablegui.live.LiveObject;
10
 import org.openzen.drawablegui.style.DStylePath;
11
 import org.openzen.drawablegui.style.DStylePath;
21
 	private DEmptyView() {}
22
 	private DEmptyView() {}
22
 
23
 
23
 	@Override
24
 	@Override
24
-	public void setContext(DStylePath parent, DUIContext context) {
25
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
26
+		
27
+	}
28
+	
29
+	@Override
30
+	public void unmount() {
25
 		
31
 		
26
 	}
32
 	}
27
 	
33
 	
45
 		
51
 		
46
 	}
52
 	}
47
 
53
 
48
-	@Override
49
-	public void paint(DCanvas canvas) {
50
-		
51
-	}
52
-
53
 	@Override
54
 	@Override
54
 	public void close() {
55
 	public void close() {
55
 		// nothing to clean up
56
 		// nothing to clean up

+ 4
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DFontMetrics.java View File

19
 	int getWidth(String str);
19
 	int getWidth(String str);
20
 	
20
 	
21
 	int getWidth(String str, int offset, int length);
21
 	int getWidth(String str, int offset, int length);
22
+	
23
+	default int getLineHeight() {
24
+		return getAscent() + getDescent();
25
+	}
22
 }
26
 }

+ 0
- 273
DrawableGui/src/main/java/org/openzen/drawablegui/DHorizontalLayout.java View File

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
-import org.openzen.drawablegui.listeners.ListenerHandle;
11
-import org.openzen.drawablegui.live.LiveObject;
12
-import org.openzen.drawablegui.live.MutableLiveObject;
13
-import org.openzen.drawablegui.live.SimpleLiveObject;
14
-import org.openzen.drawablegui.style.DStyleClass;
15
-import org.openzen.drawablegui.style.DStylePath;
16
-
17
-/**
18
- *
19
- * @author Hoofdgebruiker
20
- */
21
-public class DHorizontalLayout extends BaseComponentGroup {
22
-	private final DStyleClass styleClass;
23
-	private final Alignment alignment;
24
-	private final Element[] components;
25
-	private final ListenerHandle<LiveObject.Listener<DSizing>>[] componentSizeListeners;
26
-	private final MutableLiveObject<DSizing> sizing = DSizing.create();
27
-	
28
-	private DUIContext context;
29
-	private DHorizontalLayoutStyle style;
30
-	private DIRectangle bounds;
31
-	private float totalGrow;
32
-	private float totalShrink;
33
-	
34
-	public DHorizontalLayout(DStyleClass styleClass, Alignment alignment, Element... components) {
35
-		this.styleClass = styleClass;
36
-		this.alignment = alignment;
37
-		this.components = components;
38
-		
39
-		componentSizeListeners = new ListenerHandle[components.length];
40
-		totalGrow = 0;
41
-		totalShrink = 0;
42
-		
43
-		for (int i = 0; i < componentSizeListeners.length; i++) {
44
-			componentSizeListeners[i] = components[i].component.getSizing().addListener((oldValue, newValue) -> updateDimensionPreferences());
45
-			
46
-			totalGrow += components[i].grow;
47
-			totalShrink += components[i].shrink;
48
-		}
49
-	}
50
-
51
-	@Override
52
-	protected void forEachChild(Consumer<DComponent> children) {
53
-		for (Element element : components)
54
-			children.accept(element.component);
55
-	}
56
-
57
-	@Override
58
-	protected DComponent findChild(Predicate<DComponent> predicate) {
59
-		for (Element element : components)
60
-			if (predicate.test(element.component))
61
-				return element.component;
62
-		
63
-		return null;
64
-	}
65
-
66
-	@Override
67
-	public void setContext(DStylePath parent, DUIContext context) {
68
-		this.context = context;
69
-		
70
-		DStylePath path = parent.getChild("horizontalLayout", styleClass);
71
-		style = new DHorizontalLayoutStyle(context.getStylesheets().get(context, path));
72
-		
73
-		for (Element element : components)
74
-			element.component.setContext(parent, context);
75
-		
76
-		layout();
77
-	}
78
-
79
-	@Override
80
-	public LiveObject<DSizing> getSizing() {
81
-		return sizing;
82
-	}
83
-
84
-	@Override
85
-	public DIRectangle getBounds() {
86
-		return bounds;
87
-	}
88
-
89
-	@Override
90
-	public int getBaselineY() {
91
-		return components[0].component.getBaselineY();
92
-	}
93
-
94
-	@Override
95
-	public void setBounds(DIRectangle bounds) {
96
-		this.bounds = bounds;
97
-		layout();
98
-	}
99
-
100
-	@Override
101
-	public void paint(DCanvas canvas) {
102
-		for (Element element : components) {
103
-			element.component.paint(canvas);
104
-		}
105
-	}
106
-
107
-	@Override
108
-	public void close() {
109
-		for (int i = 0; i < componentSizeListeners.length; i++) {
110
-			componentSizeListeners[i].close();
111
-		}
112
-	}
113
-	
114
-	public static enum Alignment {
115
-		LEFT(0),
116
-		CENTER(0.5f),
117
-		RIGHT(1);
118
-		
119
-		public final float align;
120
-		
121
-		Alignment(float align) {
122
-			this.align = align;
123
-		}
124
-	}
125
-	
126
-	public static enum ElementAlignment {
127
-		TOP,
128
-		MIDDLE,
129
-		BOTTOM,
130
-		STRETCH
131
-	}
132
-	
133
-	public static class Element {
134
-		public final DComponent component;
135
-		public final float grow;
136
-		public final float shrink;
137
-		public final ElementAlignment alignment;
138
-		
139
-		public Element(DComponent component, float grow, float shrink, ElementAlignment alignment) {
140
-			this.component = component;
141
-			this.grow = grow;
142
-			this.shrink = shrink;
143
-			this.alignment = alignment;
144
-		}
145
-	}
146
-	
147
-	private void layout() {
148
-		if (bounds == null || context == null)
149
-			return;
150
-		
151
-		DSizing myPreferences = sizing.getValue();
152
-		if (bounds.width < myPreferences.preferredWidth) {
153
-			layoutShrinked();
154
-		} else {
155
-			layoutGrown();
156
-		}
157
-	}
158
-	
159
-	private void layoutShrinked() {
160
-		DSizing myPreferences = sizing.getValue();
161
-		if (totalShrink == 0) {
162
-			// now what?
163
-			// shrink proportionally, we have to shrink...
164
-			float scale = (float)(bounds.width - (components.length - 1) * style.spacing) / (myPreferences.preferredWidth - (components.length - 1) * style.spacing);
165
-			int x = 0;
166
-			
167
-			for (int i = 0; i < components.length; i++) {
168
-				Element element = components[i];
169
-				DSizing preferences = element.component.getSizing().getValue();
170
-				int newX = x + preferences.preferredWidth;
171
-				float idealUnspacedX = newX * scale;
172
-				int idealX = (int)(idealUnspacedX + 0.5f + i * style.spacing);
173
-				layout(element, x, idealX - x);
174
-				x = idealX;
175
-			}
176
-		} else {
177
-			int delta = bounds.width - myPreferences.preferredWidth;
178
-			float deltaScaled = delta / totalShrink;
179
-			int x = 0;
180
-			for (Element element : components) {
181
-				DSizing preferences = element.component.getSizing().getValue();
182
-				float scaledSize = preferences.preferredWidth + deltaScaled * element.shrink;
183
-				float idealUnspacedX = x + scaledSize;
184
-				int newX = (int)(idealUnspacedX + 0.5f);
185
-				layout(element, x, newX - x);
186
-				x = newX + style.spacing;
187
-			}
188
-		}
189
-	}
190
-	
191
-	private void layoutGrown() {
192
-		// resize according to grow values
193
-		DSizing myPreferences = sizing.getValue();
194
-		
195
-		if (totalGrow == 0) {
196
-			int deltaX = (int)(myPreferences.preferredWidth - bounds.width);
197
-			int x = bounds.x + (int)(deltaX * alignment.align);
198
-			for (Element element : components) {
199
-				DSizing preferences = element.component.getSizing().getValue();
200
-				int newX = x + preferences.preferredWidth;
201
-				layout(element, x, newX - x);
202
-				x = newX + style.spacing;
203
-			}
204
-		} else {
205
-			int delta = bounds.width - myPreferences.preferredWidth;
206
-			float deltaScaled = delta / totalGrow;
207
-			int x = 0;
208
-			for (Element element : components) {
209
-				DSizing preferences = element.component.getSizing().getValue();
210
-				float scaledSize = preferences.preferredWidth + deltaScaled * element.grow;
211
-				float idealUnspacedX = x + scaledSize;
212
-				int newX = (int)(idealUnspacedX + 0.5f);
213
-				layout(element, x, newX - x);
214
-				x = newX + style.spacing;
215
-			}
216
-		}
217
-	}
218
-	
219
-	private void layout(Element element, int x, int width) {
220
-		DSizing preferences = element.component.getSizing().getValue();
221
-		int height;
222
-		int y;
223
-		switch (element.alignment) {
224
-			case BOTTOM:
225
-				height = Math.min(preferences.preferredHeight, bounds.height - style.paddingTop - style.paddingBottom);
226
-				y = bounds.y + style.paddingTop;
227
-				break;
228
-			case MIDDLE:
229
-				height = Math.min(preferences.preferredHeight, bounds.height - style.paddingTop - style.paddingBottom);
230
-				y = bounds.y + style.paddingTop + (bounds.height - style.paddingTop - style.paddingBottom - height) / 2;
231
-				break;
232
-			case TOP:
233
-				height = Math.min(preferences.preferredHeight, bounds.height - style.paddingTop - style.paddingBottom);
234
-				y = bounds.y + bounds.height - style.paddingBottom - height;
235
-				break;
236
-			case STRETCH:
237
-			default:
238
-				height = bounds.height - style.paddingTop - style.paddingBottom;
239
-				y = bounds.y + style.paddingTop;
240
-				break;
241
-		}
242
-		element.component.setBounds(new DIRectangle(x, y, width, height));
243
-	}
244
-	
245
-	private void updateDimensionPreferences() {
246
-		int preferredWidth = -style.spacing;
247
-		int preferredHeight = 0;
248
-		int minimumWidth = -style.spacing;
249
-		int minimumHeight = 0;
250
-		int maximumWidth = -style.spacing;
251
-		int maximumHeight = Integer.MAX_VALUE;
252
-		for (Element element : components) {
253
-			DSizing preferences = element.component.getSizing().getValue();
254
-			preferredWidth += preferences.preferredWidth + style.spacing;
255
-			preferredHeight = Math.max(preferredHeight, preferences.preferredHeight);
256
-			
257
-			minimumWidth += preferences.minimumWidth + style.spacing;
258
-			minimumHeight = Math.max(minimumHeight, preferences.minimumHeight);
259
-			
260
-			maximumWidth += preferences.maximumWidth + style.spacing;
261
-			maximumHeight = Math.min(maximumHeight, preferences.maximumHeight);
262
-		}
263
-		
264
-		DSizing preferences = new DSizing(
265
-				minimumWidth + style.paddingLeft + style.paddingRight,
266
-				minimumHeight + style.paddingTop + style.paddingBottom,
267
-				preferredWidth + style.paddingLeft + style.paddingRight,
268
-				preferredHeight + style.paddingTop + style.paddingBottom,
269
-				maximumWidth + style.paddingLeft + style.paddingRight,
270
-				maximumHeight + style.paddingTop + style.paddingBottom);
271
-		sizing.setValue(preferences);
272
-	}
273
-}

+ 0
- 31
DrawableGui/src/main/java/org/openzen/drawablegui/DHorizontalLayoutStyle.java View File

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.DDpDimension;
9
-import org.openzen.drawablegui.style.DStyleDefinition;
10
-
11
-/**
12
- *
13
- * @author Hoofdgebruiker
14
- */
15
-public class DHorizontalLayoutStyle {
16
-	public final int spacing;
17
-	
18
-	public final int paddingTop;
19
-	public final int paddingLeft;
20
-	public final int paddingRight;
21
-	public final int paddingBottom;
22
-	
23
-	public DHorizontalLayoutStyle(DStyleDefinition style) {
24
-		spacing = style.getDimension("spacing", new DDpDimension(8));
25
-		
26
-		paddingTop = style.getDimension("paddingTop", new DDpDimension(8));
27
-		paddingLeft = style.getDimension("paddingLeft", new DDpDimension(8));
28
-		paddingRight = style.getDimension("paddingRight", new DDpDimension(8));
29
-		paddingBottom = style.getDimension("paddingBottom", new DDpDimension(8));
30
-	}
31
-}

+ 40
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DIRectangle.java View File

42
 				&& y >= this.y && y < (this.y + this.height);
42
 				&& y >= this.y && y < (this.y + this.height);
43
 	}
43
 	}
44
 	
44
 	
45
+	public boolean overlaps(DIRectangle other) {
46
+		if (x + width < other.x)
47
+			return false;
48
+		if (y + height < other.y)
49
+			return false;
50
+		if (other.x + other.width < x)
51
+			return false;
52
+		if (other.y + other.height < y)
53
+			return false;
54
+		
55
+		return true;
56
+	}
57
+	
58
+	public DIRectangle offset(int x, int y) {
59
+		return new DIRectangle(this.x + x, this.y + y, width, height);
60
+	}
61
+	
62
+	public DIRectangle expand(int edge) {
63
+		return new DIRectangle(x - edge, y - edge, width + 2 * edge, height + 2 * edge);
64
+	}
65
+	
66
+	public DIRectangle union(DIRectangle other) {
67
+		int left = Math.min(x, other.x);
68
+		int top = Math.min(y, other.y);
69
+		int right = Math.max(x + width, other.x + other.width);
70
+		int bottom = Math.max(y + height, other.y + other.height);
71
+		return new DIRectangle(left, top, right - left, bottom - top);
72
+	}
73
+	
74
+	public DIRectangle intersect(DIRectangle other) {
75
+		int left = Math.max(x, other.x);
76
+		int top = Math.max(y, other.y);
77
+		int right = Math.min(x + width, other.x + other.width);
78
+		int bottom = Math.min(y + height, other.y + other.height);
79
+		if (right < left || bottom < top)
80
+			return EMPTY;
81
+		
82
+		return new DIRectangle(left, top, right - left, bottom - top);
83
+	}
84
+	
45
 	@Override
85
 	@Override
46
 	public String toString() {
86
 	public String toString() {
47
 		return "(x = " + x + ", y = " + y + ", width = " + width + ", height = " + height + ")";
87
 		return "(x = " + x + ", y = " + y + ", width = " + width + ", height = " + height + ")";

+ 98
- 49
DrawableGui/src/main/java/org/openzen/drawablegui/DInputField.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawSurface;
9
+import org.openzen.drawablegui.draw.DDrawnRectangle;
10
+import org.openzen.drawablegui.draw.DDrawnShape;
11
+import org.openzen.drawablegui.draw.DDrawnText;
8
 import org.openzen.drawablegui.listeners.ListenerHandle;
12
 import org.openzen.drawablegui.listeners.ListenerHandle;
9
 import org.openzen.drawablegui.live.LiveObject;
13
 import org.openzen.drawablegui.live.LiveObject;
10
 import org.openzen.drawablegui.live.LiveString;
14
 import org.openzen.drawablegui.live.LiveString;
27
 	private DIRectangle bounds = DIRectangle.EMPTY;
31
 	private DIRectangle bounds = DIRectangle.EMPTY;
28
 	private final DDimension preferredWidth;
32
 	private final DDimension preferredWidth;
29
 	
33
 	
30
-	private DUIContext context;
34
+	private DDrawSurface surface;
35
+	private int z;
31
 	private DInputFieldStyle style;
36
 	private DInputFieldStyle style;
32
 	private DFontMetrics fontMetrics;
37
 	private DFontMetrics fontMetrics;
33
 	private int cursorFrom = -1;
38
 	private int cursorFrom = -1;
39
 	private boolean cursorBlink = true;
44
 	private boolean cursorBlink = true;
40
 	private DTimerHandle blinkTimer;
45
 	private DTimerHandle blinkTimer;
41
 	
46
 	
47
+	private DDrawnShape shape;
48
+	private DDrawnText text;
49
+	private DDrawnRectangle cursor;
50
+	private DDrawnRectangle selection;
51
+	
42
 	public DInputField(DStyleClass styleClass, MutableLiveString value, DDimension preferredWidth) {
52
 	public DInputField(DStyleClass styleClass, MutableLiveString value, DDimension preferredWidth) {
43
 		this.styleClass = styleClass;
53
 		this.styleClass = styleClass;
44
 		this.value = value;
54
 		this.value = value;
60
 	@Override
70
 	@Override
61
 	public void close() {
71
 	public void close() {
62
 		valueListener.close();
72
 		valueListener.close();
63
-		blinkTimer.close();
73
+		unmount();
64
 	}
74
 	}
65
 
75
 
66
 	@Override
76
 	@Override
67
-	public void setContext(DStylePath parent, DUIContext context) {
68
-		this.context = context;
77
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
78
+		this.surface = surface;
79
+		this.z = z;
69
 		
80
 		
70
 		DStylePath path = parent.getChild("input", styleClass);
81
 		DStylePath path = parent.getChild("input", styleClass);
71
-		style = new DInputFieldStyle(context.getStylesheets().get(context, path));
72
-		fontMetrics = context.getFontMetrics(style.font);
82
+		style = new DInputFieldStyle(surface.getStylesheet(path));
83
+		fontMetrics = surface.getFontMetrics(style.font);
84
+		
73
 		sizing.setValue(new DSizing(
85
 		sizing.setValue(new DSizing(
74
-				preferredWidth.evalInt(context) + style.paddingLeft + style.paddingRight + 2 * style.borderWidth,
75
-				fontMetrics.getAscent() + fontMetrics.getDescent() + style.paddingTop + style.paddingBottom + 2 * style.borderWidth));
86
+				preferredWidth.evalInt(surface.getContext()) + style.margin.getHorizontal() + style.border.getPaddingHorizontal(),
87
+				fontMetrics.getAscent() + fontMetrics.getDescent() + style.margin.getVertical() + style.border.getPaddingVertical()));
76
 		
88
 		
77
 		if (blinkTimer != null)
89
 		if (blinkTimer != null)
78
 			blinkTimer.close();
90
 			blinkTimer.close();
79
-		blinkTimer = context.setTimer(300, this::blink);
91
+		blinkTimer = surface.getContext().setTimer(300, this::blink);
92
+		
93
+		if (text != null)
94
+			text.close();
95
+		text = surface.drawText(
96
+				z + 2,
97
+				style.font,
98
+				style.color,
99
+				bounds.x + style.margin.left + style.border.getPaddingLeft(),
100
+				bounds.y + style.margin.top + style.border.getPaddingTop() + fontMetrics.getAscent(),
101
+				value.getValue());
102
+		
103
+		if (cursor != null)
104
+			cursor.close();
105
+		cursor = surface.fillRect(z + 2, DIRectangle.EMPTY, cursorBlink ? style.cursorColor : 0);
106
+		
107
+		if (selection != null)
108
+			selection.close();
109
+		selection = surface.fillRect(z + 1, DIRectangle.EMPTY, 0);
110
+		
111
+		setCursor(cursorFrom, cursorTo);
112
+	}
113
+	
114
+	@Override
115
+	public void unmount() {
116
+		blinkTimer.close();
117
+		
118
+		if (style != null)
119
+			style.border.close();
120
+		if (shape != null)
121
+			shape.close();
122
+		if (text != null)
123
+			text.close();
124
+		if (cursor != null)
125
+			cursor.close();
126
+		if (selection != null)
127
+			selection.close();
80
 	}
128
 	}
81
 	
129
 	
82
 	private void blink() {
130
 	private void blink() {
83
 		cursorBlink = !cursorBlink;
131
 		cursorBlink = !cursorBlink;
84
-		context.repaint(bounds);
132
+		cursor.setColor(cursorBlink ? style.cursorColor : 0);
85
 	}
133
 	}
86
 
134
 
87
 	@Override
135
 	@Override
96
 	
144
 	
97
 	@Override
145
 	@Override
98
 	public int getBaselineY() {
146
 	public int getBaselineY() {
99
-		return style.borderWidth + style.paddingTop + fontMetrics.getAscent();
147
+		return style.margin.top + style.border.getPaddingTop() + fontMetrics.getAscent();
100
 	}
148
 	}
101
 
149
 
102
 	@Override
150
 	@Override
103
 	public void setBounds(DIRectangle bounds) {
151
 	public void setBounds(DIRectangle bounds) {
104
 		this.bounds = bounds;
152
 		this.bounds = bounds;
105
-	}
106
-
107
-	@Override
108
-	public void paint(DCanvas canvas) {
109
-		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.backgroundColor);
110
-		if (style.borderWidth > 0) {
111
-			canvas.strokePath(
112
-					DPath.rectangle(bounds.x, bounds.y, bounds.width - style.borderWidth, bounds.height - style.borderWidth),
113
-					DTransform2D.IDENTITY,
114
-					style.borderColor,
115
-					style.borderWidth);
116
-		}
153
+		setCursor(cursorFrom, cursorTo);
117
 		
154
 		
118
-		int cursorXFrom = fontMetrics.getWidth(value.getValue(), 0, Math.min(cursorFrom, cursorTo));
119
-		int cursorXTo = fontMetrics.getWidth(value.getValue(), 0, Math.max(cursorFrom, cursorTo));
120
-		if (cursorFrom != cursorTo) {
121
-			canvas.fillRectangle(
122
-					bounds.x + style.paddingLeft + cursorXFrom,
123
-					bounds.y + style.paddingTop,
124
-					cursorXTo - cursorXFrom,
125
-					fontMetrics.getAscent() + fontMetrics.getDescent(),
126
-					style.selectionColor);
127
-		}
128
-		
129
-		canvas.drawText(style.font, style.color, bounds.x + style.paddingLeft + style.borderWidth, bounds.y + style.paddingBottom + style.borderWidth + fontMetrics.getAscent(), value.getValue());
130
-		
131
-		if (cursorBlink) {
132
-			canvas.fillRectangle(
133
-					bounds.x + style.paddingLeft + cursorXTo,
134
-					bounds.y + style.paddingTop,
135
-					style.cursorWidth,
136
-					fontMetrics.getAscent() + fontMetrics.getDescent(),
137
-					style.cursorColor);
138
-		}
155
+		if (shape != null)
156
+			shape.close();
157
+		shape = surface.fillPath(z, style.shape.instance(style.margin.apply(bounds)), DTransform2D.IDENTITY, style.backgroundColor);
158
+		text.setPosition(
159
+				bounds.x + style.margin.left + style.border.getPaddingLeft(),
160
+				bounds.y + style.margin.top + style.border.getPaddingTop() + fontMetrics.getAscent());
161
+		style.border.update(surface, z, bounds);
139
 	}
162
 	}
140
 	
163
 	
141
 	@Override
164
 	@Override
142
 	public void onMouseEnter(DMouseEvent e) {
165
 	public void onMouseEnter(DMouseEvent e) {
143
-		context.setCursor(DUIContext.Cursor.TEXT);
166
+		surface.getContext().setCursor(DUIContext.Cursor.TEXT);
144
 	}
167
 	}
145
 	
168
 	
146
 	@Override
169
 	@Override
147
 	public void onMouseExit(DMouseEvent e) {
170
 	public void onMouseExit(DMouseEvent e) {
148
-		context.setCursor(DUIContext.Cursor.NORMAL);
171
+		surface.getContext().setCursor(DUIContext.Cursor.NORMAL);
149
 	}
172
 	}
150
 	
173
 	
151
 	@Override
174
 	@Override
152
 	public void onMouseClick(DMouseEvent e) {
175
 	public void onMouseClick(DMouseEvent e) {
153
-		context.getWindow().focus(this);
176
+		surface.getContext().getWindow().focus(this);
154
 	}
177
 	}
155
 	
178
 	
156
 	@Override
179
 	@Override
197
 	private void setCursor(int from, int to) {
220
 	private void setCursor(int from, int to) {
198
 		cursorFrom = from;
221
 		cursorFrom = from;
199
 		cursorTo = to;
222
 		cursorTo = to;
200
-		context.repaint(bounds);
223
+		
224
+		int cursorXFrom = fontMetrics.getWidth(value.getValue(), 0, Math.min(cursorFrom, cursorTo));
225
+		int cursorXTo = fontMetrics.getWidth(value.getValue(), 0, Math.max(cursorFrom, cursorTo));
226
+		if (cursorFrom != cursorTo) {
227
+			selection.setRectangle(new DIRectangle(
228
+					bounds.x + style.margin.left + style.border.getPaddingLeft() + cursorXFrom,
229
+					bounds.y + style.margin.top + style.border.getPaddingTop(),
230
+					cursorXTo - cursorXFrom,
231
+					fontMetrics.getAscent() + fontMetrics.getDescent()));
232
+			selection.setColor(style.selectionColor);
233
+		} else {
234
+			selection.setColor(0);
235
+		}
236
+		
237
+		cursor.setRectangle(new DIRectangle(
238
+				bounds.x + style.margin.left + style.border.getPaddingLeft() + cursorXTo,
239
+				bounds.y + style.margin.top + style.border.getPaddingTop(),
240
+				style.cursorWidth,
241
+				fontMetrics.getAscent() + fontMetrics.getDescent()));
201
 	}
242
 	}
202
 	
243
 	
203
 	private void handleValueUpdated(String newValue) {
244
 	private void handleValueUpdated(String newValue) {
204
-		context.repaint(bounds);
245
+		if (text != null)
246
+			text.close();
247
+		text = surface.drawText(
248
+				z + 2,
249
+				style.font,
250
+				style.color,
251
+				bounds.x + style.margin.left + style.border.getPaddingLeft(),
252
+				bounds.y + style.margin.top + style.border.getPaddingTop() + fontMetrics.getAscent(),
253
+				value.getValue());
205
 	}
254
 	}
206
 	
255
 	
207
 	private void backspace() {
256
 	private void backspace() {

+ 6
- 19
DrawableGui/src/main/java/org/openzen/drawablegui/DInputFieldStyle.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.border.DCompositeBorder;
9
+import org.openzen.drawablegui.border.DLineBorder;
10
+import org.openzen.drawablegui.border.DPaddedBorder;
11
+import org.openzen.drawablegui.style.DBaseStyle;
8
 import org.openzen.drawablegui.style.DDpDimension;
12
 import org.openzen.drawablegui.style.DDpDimension;
9
-import org.openzen.drawablegui.style.DPxDimension;
10
 import org.openzen.drawablegui.style.DStyleDefinition;
13
 import org.openzen.drawablegui.style.DStyleDefinition;
11
 
14
 
12
 /**
15
 /**
13
  *
16
  *
14
  * @author Hoofdgebruiker
17
  * @author Hoofdgebruiker
15
  */
18
  */
16
-public class DInputFieldStyle {
17
-	public final int backgroundColor;
18
-	public final int paddingTop;
19
-	public final int paddingLeft;
20
-	public final int paddingRight;
21
-	public final int paddingBottom;
22
-	
23
-	public final int borderWidth;
24
-	public final int borderColor;
25
-	
19
+public class DInputFieldStyle extends DBaseStyle {
26
 	public final int color;
20
 	public final int color;
27
 	public final DFont font;
21
 	public final DFont font;
28
 	
22
 	
32
 	public final int selectionColor;
26
 	public final int selectionColor;
33
 	
27
 	
34
 	public DInputFieldStyle(DStyleDefinition style) {
28
 	public DInputFieldStyle(DStyleDefinition style) {
35
-		backgroundColor = style.getColor("backgroundColor", 0xFFFFFFFF);
36
-		paddingTop = style.getDimension("paddingTop", new DDpDimension(2));
37
-		paddingBottom = style.getDimension("paddingBottom", new DDpDimension(2));
38
-		paddingLeft = style.getDimension("paddingLeft", new DDpDimension(2));
39
-		paddingRight = style.getDimension("paddingRight", new DDpDimension(2));
40
-		
41
-		borderWidth = style.getDimension("borderWidth", new DPxDimension(1));
42
-		borderColor = style.getColor("borderColor", 0xFFABADB3);
29
+		super(style, context -> new DCompositeBorder(new DLineBorder(0xFFABADB3, 1), new DPaddedBorder(context.dp(2))), 0xFFFFFFFF);
43
 		
30
 		
44
 		color = style.getColor("color", 0xFF000000);
31
 		color = style.getColor("color", 0xFF000000);
45
 		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, (int)(14 * context.getScale())));
32
 		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, (int)(14 * context.getScale())));

+ 38
- 12
DrawableGui/src/main/java/org/openzen/drawablegui/DLabel.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawSurface;
9
+import org.openzen.drawablegui.draw.DDrawnText;
8
 import org.openzen.drawablegui.listeners.ListenerHandle;
10
 import org.openzen.drawablegui.listeners.ListenerHandle;
9
 import org.openzen.drawablegui.live.LiveObject;
11
 import org.openzen.drawablegui.live.LiveObject;
10
 import org.openzen.drawablegui.live.LiveString;
12
 import org.openzen.drawablegui.live.LiveString;
22
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
24
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
23
 	private final ListenerHandle<LiveString.Listener> labelListener;
25
 	private final ListenerHandle<LiveString.Listener> labelListener;
24
 	
26
 	
25
-	private DUIContext context;
27
+	private DDrawSurface surface;
28
+	private int z;
26
 	private DIRectangle bounds;
29
 	private DIRectangle bounds;
27
 	private DLabelStyle style;
30
 	private DLabelStyle style;
28
 	private DFontMetrics fontMetrics;
31
 	private DFontMetrics fontMetrics;
29
 	
32
 	
33
+	private DDrawnText text;
34
+	
30
 	public DLabel(DStyleClass styleClass, LiveString label) {
35
 	public DLabel(DStyleClass styleClass, LiveString label) {
31
 		this.styleClass = styleClass;
36
 		this.styleClass = styleClass;
32
 		this.label = label;
37
 		this.label = label;
35
 	}
40
 	}
36
 
41
 
37
 	@Override
42
 	@Override
38
-	public void setContext(DStylePath parent, DUIContext context) {
39
-		this.context = context;
43
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
44
+		this.surface = surface;
45
+		this.z = z;
40
 		
46
 		
41
 		DStylePath path = parent.getChild("label", styleClass);
47
 		DStylePath path = parent.getChild("label", styleClass);
42
-		style = new DLabelStyle(context.getStylesheets().get(context, path));
48
+		style = new DLabelStyle(surface.getStylesheet(path));
43
 		
49
 		
44
-		fontMetrics = context.getFontMetrics(style.font);
50
+		fontMetrics = surface.getFontMetrics(style.font);
45
 		calculateDimension();
51
 		calculateDimension();
52
+		
53
+		if (text != null)
54
+			text.close();
55
+		text = surface.drawText(z, style.font, style.color, 0, 0, label.getValue());
56
+	}
57
+	
58
+	@Override
59
+	public void unmount() {
60
+		if (style != null)
61
+			style.border.close();
62
+		if (text != null)
63
+			text.close();
46
 	}
64
 	}
47
 
65
 
48
 	@Override
66
 	@Override
63
 	@Override
81
 	@Override
64
 	public void setBounds(DIRectangle bounds) {
82
 	public void setBounds(DIRectangle bounds) {
65
 		this.bounds = bounds;
83
 		this.bounds = bounds;
66
-	}
67
-
68
-	@Override
69
-	public void paint(DCanvas canvas) {
70
-		style.border.paint(canvas, bounds);
71
-		canvas.drawText(style.font, style.color, bounds.x + style.border.getPaddingLeft(), bounds.y + style.border.getPaddingTop() + fontMetrics.getAscent(), label.getValue());
84
+		style.border.update(surface, z + 1, bounds);
85
+		text.setPosition(
86
+				bounds.x + style.border.getPaddingLeft(),
87
+				bounds.y + style.border.getPaddingTop() + fontMetrics.getAscent());
72
 	}
88
 	}
73
 
89
 
74
 	@Override
90
 	@Override
75
 	public void close() {
91
 	public void close() {
76
 		labelListener.close();
92
 		labelListener.close();
93
+		unmount();
77
 	}
94
 	}
78
 	
95
 	
79
 	private void onLabelChanged(String oldValue, String newValue) {
96
 	private void onLabelChanged(String oldValue, String newValue) {
80
 		calculateDimension();
97
 		calculateDimension();
81
-		context.repaint(bounds);
98
+		
99
+		if (text != null)
100
+			text.close();
101
+		text = surface.drawText(
102
+				z,
103
+				style.font,
104
+				style.color,
105
+				bounds.x + style.border.getPaddingLeft(),
106
+				bounds.y + style.border.getPaddingTop() + fontMetrics.getAscent(),
107
+				newValue);
82
 	}
108
 	}
83
 	
109
 	
84
 	private void calculateDimension() {
110
 	private void calculateDimension() {

+ 49
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DPath.java View File

10
  * @author Hoofdgebruiker
10
  * @author Hoofdgebruiker
11
  */
11
  */
12
 public interface DPath {
12
 public interface DPath {
13
+	public static DPath line(float x1, float y1, float x2, float y2) {
14
+		return tracer -> {
15
+			tracer.moveTo(x1, y1);
16
+			tracer.lineTo(x2, y2);
17
+		};
18
+	}
19
+	
13
 	public static DPath circle(float x, float y, float radius) {
20
 	public static DPath circle(float x, float y, float radius) {
14
 		// see http://spencermortensen.com/articles/bezier-circle/
21
 		// see http://spencermortensen.com/articles/bezier-circle/
15
 		return tracer -> {
22
 		return tracer -> {
45
 	}
52
 	}
46
 	
53
 	
47
 	public static DPath roundedRectangle(float x, float y, float width, float height, float radius) {
54
 	public static DPath roundedRectangle(float x, float y, float width, float height, float radius) {
55
+		if (radius < 0.01f)
56
+			return rectangle(x, y, width, height);
57
+		
48
 		return tracer -> {
58
 		return tracer -> {
49
 			float c = radius - radius * 0.551915024494f;
59
 			float c = radius - radius * 0.551915024494f;
50
 			tracer.moveTo(x + width - radius, y + height);
60
 			tracer.moveTo(x + width - radius, y + height);
71
 		};
81
 		};
72
 	}
82
 	}
73
 	
83
 	
84
+	public static DPath roundedRectangle(float x, float y, float width, float height, float radiusTopLeft, float radiusTopRight, float radiusBottomLeft, float radiusBottomRight) {
85
+		return tracer -> {
86
+			float cTopLeft = radiusTopLeft - radiusTopLeft * 0.551915024494f;
87
+			float cTopRight = radiusTopRight - radiusTopRight * 0.551915024494f;
88
+			float cBottomLeft = radiusBottomLeft - radiusBottomLeft * 0.551915024494f;
89
+			float cBottomRight = radiusBottomRight - radiusBottomRight * 0.551915024494f;
90
+			
91
+			tracer.moveTo(x + width - radiusBottomRight, y + height);
92
+			if (radiusBottomRight > 0.01f) {
93
+				tracer.bezierCubic(
94
+						x + width - cBottomRight, y + height,
95
+						x + width, y + height - cBottomRight,
96
+						x + width, y + height - radiusBottomRight);
97
+			}
98
+			tracer.lineTo(x + width, y + radiusTopRight);
99
+			if (radiusTopRight > 0.01f) {
100
+				tracer.bezierCubic(
101
+						x + width, y + cTopRight,
102
+						x + width - cTopRight, y,
103
+						x + width - radiusTopRight, y);
104
+			}
105
+			tracer.lineTo(x + radiusTopLeft, y);
106
+			if (radiusTopLeft > 0.01f) {
107
+				tracer.bezierCubic(
108
+						x + cTopLeft, y,
109
+						x, y + cTopLeft,
110
+						x, y + radiusTopLeft);
111
+			}
112
+			tracer.lineTo(x, y + height - radiusBottomLeft);
113
+			if (radiusBottomLeft > 0.01f) {
114
+				tracer.bezierCubic(
115
+						x, y + height - cBottomLeft,
116
+						x + cBottomLeft, y + height,
117
+						x + radiusBottomLeft, y + height);
118
+			}
119
+			tracer.close();
120
+		};
121
+	}
122
+	
74
 	void trace(DPathTracer tracer);
123
 	void trace(DPathTracer tracer);
75
 }
124
 }

+ 24
- 48
DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltip.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
-import org.openzen.drawablegui.listeners.ListenerHandle;
9
 import org.openzen.drawablegui.live.LiveString;
8
 import org.openzen.drawablegui.live.LiveString;
10
 import org.openzen.drawablegui.style.DStyleClass;
9
 import org.openzen.drawablegui.style.DStyleClass;
11
-import org.openzen.drawablegui.style.DStylePath;
12
 
10
 
13
 /**
11
 /**
14
  *
12
  *
17
 public class DSimpleTooltip {
15
 public class DSimpleTooltip {
18
 	private final DStyleClass styleClass;
16
 	private final DStyleClass styleClass;
19
 	private final LiveString tooltip;
17
 	private final LiveString tooltip;
20
-	private final ListenerHandle<LiveString.Listener> tooltipListener;
21
 	
18
 	
22
 	private DUIContext context;
19
 	private DUIContext context;
23
-	private DIRectangle bounds;
24
-	private DFontMetrics fontMetrics;
25
-	private DTooltipStyle style;
26
-	private boolean visible = false;
20
+	private DSimpleTooltipStyle style;
27
 	private DTimerHandle timerHandle = null;
21
 	private DTimerHandle timerHandle = null;
28
 	
22
 	
23
+	private int enterMouseX;
24
+	private int enterMouseY;
25
+	private DUIWindow window;
26
+	
29
 	public DSimpleTooltip(DStyleClass styleClass, LiveString tooltip) {
27
 	public DSimpleTooltip(DStyleClass styleClass, LiveString tooltip) {
30
 		this.styleClass = styleClass;
28
 		this.styleClass = styleClass;
31
 		this.tooltip = tooltip;
29
 		this.tooltip = tooltip;
32
-		tooltipListener = tooltip.addListener(this::onTooltipChanged);
33
 	}
30
 	}
34
 	
31
 	
35
-	private void onTooltipChanged(String oldValue, String newValue) {
36
-		if (context == null || bounds == null)
37
-			return;
38
-		
39
-		bounds = new DIRectangle(
40
-				bounds.x,
41
-				bounds.y,
42
-				style.border.getPaddingLeft() + fontMetrics.getWidth(tooltip.getValue()) + style.border.getPaddingRight(),
43
-				style.border.getPaddingTop() + fontMetrics.getAscent() + fontMetrics.getDescent() + style.border.getPaddingBottom());
44
-		context.repaint(bounds);
32
+	public void setContext(DUIContext context) {
33
+		this.context = context;
45
 	}
34
 	}
46
 	
35
 	
47
 	public void onTargetMouseEnter(DMouseEvent e) {
36
 	public void onTargetMouseEnter(DMouseEvent e) {
49
 			timerHandle.close();
38
 			timerHandle.close();
50
 		
39
 		
51
 		timerHandle = context.setTimer(1000, this::show);
40
 		timerHandle = context.setTimer(1000, this::show);
52
-		bounds = new DIRectangle(
53
-				e.x,
54
-				e.y,
55
-				style.border.getPaddingLeft() + fontMetrics.getWidth(tooltip.getValue()) + style.border.getPaddingRight(),
56
-				style.border.getPaddingTop() + fontMetrics.getAscent() + fontMetrics.getDescent() + style.border.getPaddingBottom());
41
+		enterMouseX = e.x;
42
+		enterMouseY = e.y;
43
+	}
44
+	
45
+	public void onTargetMouseMove(DMouseEvent e) {
46
+		enterMouseX = e.x;
47
+		enterMouseY = e.y;
57
 	}
48
 	}
58
 	
49
 	
59
 	public void onTargetMouseExit(DMouseEvent e) {
50
 	public void onTargetMouseExit(DMouseEvent e) {
66
 	}
57
 	}
67
 	
58
 	
68
 	private void show() {
59
 	private void show() {
69
-		System.out.println("Show tooltip");
70
-		visible = true;
71
-		context.repaint(bounds);
60
+		DSimpleTooltipComponent view = new DSimpleTooltipComponent(styleClass, tooltip);
61
+		window = context.openView(enterMouseX, enterMouseY + context.dp(8), DAnchor.TOP_LEFT, view);
72
 		
62
 		
73
 		if (timerHandle != null) {
63
 		if (timerHandle != null) {
74
 			timerHandle.close();
64
 			timerHandle.close();
77
 	}
67
 	}
78
 	
68
 	
79
 	private void hide() {
69
 	private void hide() {
80
-		System.out.println("Hide tooltip");
81
-		visible = false;
82
-		context.repaint(bounds);
83
-	}
84
-	
85
-	public void setContext(DStylePath parent, DUIContext context) {
86
-		this.context = context;
87
-		
88
-		DStylePath path = parent.getChild("tooltip", styleClass);
89
-		style = new DTooltipStyle(context.getStylesheets().get(context, path));
90
-		fontMetrics = context.getFontMetrics(style.font);
91
-	}
92
-	
93
-	public void paint(DCanvas canvas) {
94
-		if (!visible)
95
-			return;
96
-		
97
-		System.out.println("Actually paint tooltip");
98
-		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.backgroundColor);
99
-		style.border.paint(canvas, bounds);
100
-		canvas.drawText(style.font, style.textColor, bounds.x + style.border.getPaddingLeft(), bounds.y + style.border.getPaddingTop(), tooltip.getValue());
70
+		if (window != null) {
71
+			window.close();
72
+			window = null;
73
+		}
101
 	}
74
 	}
102
 	
75
 	
103
 	public void close() {
76
 	public void close() {
104
-		tooltipListener.close();
77
+		if (window != null) {
78
+			window.close();
79
+			window = null;
80
+		}
105
 	}
81
 	}
106
 }
82
 }

+ 128
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltipComponent.java View File

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.draw.DDrawSurface;
9
+import org.openzen.drawablegui.draw.DDrawnRectangle;
10
+import org.openzen.drawablegui.draw.DDrawnText;
11
+import org.openzen.drawablegui.listeners.ListenerHandle;
12
+import org.openzen.drawablegui.live.LiveObject;
13
+import org.openzen.drawablegui.live.LiveString;
14
+import org.openzen.drawablegui.live.MutableLiveObject;
15
+import org.openzen.drawablegui.style.DStyleClass;
16
+import org.openzen.drawablegui.style.DStylePath;
17
+
18
+/**
19
+ *
20
+ * @author Hoofdgebruiker
21
+ */
22
+public class DSimpleTooltipComponent implements DComponent {
23
+	private final DStyleClass styleClass;
24
+	private final LiveString tooltip;
25
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
26
+	private final ListenerHandle<LiveString.Listener> tooltipListener;
27
+	
28
+	private DDrawSurface surface;
29
+	private int z;
30
+	private DIRectangle bounds;
31
+	private DFontMetrics fontMetrics;
32
+	private DSimpleTooltipStyle style;
33
+	
34
+	private DDrawnRectangle background;
35
+	private DDrawnText text;
36
+	
37
+	public DSimpleTooltipComponent(DStyleClass styleClass, LiveString tooltip) {
38
+		this.styleClass = styleClass;
39
+		this.tooltip = tooltip;
40
+		tooltipListener = tooltip.addListener(this::onTooltipChanged);
41
+	}
42
+	
43
+	private void onTooltipChanged(String oldValue, String newValue) {
44
+		if (surface == null || bounds == null)
45
+			return;
46
+		
47
+		calculateSize();
48
+		bounds = new DIRectangle(
49
+				bounds.x,
50
+				bounds.y,
51
+				style.border.getPaddingLeft() + fontMetrics.getWidth(tooltip.getValue()) + style.border.getPaddingRight(),
52
+				style.border.getPaddingTop() + fontMetrics.getAscent() + fontMetrics.getDescent() + style.border.getPaddingBottom());
53
+		
54
+		if (text != null)
55
+			text.close();
56
+		
57
+		text = surface.drawText(
58
+				z,
59
+				style.font,
60
+				style.textColor,
61
+				bounds.x + style.border.getPaddingLeft(),
62
+				bounds.y + style.border.getPaddingTop() + fontMetrics.getAscent(),
63
+				newValue);
64
+	}
65
+	
66
+	@Override
67
+	public void setBounds(DIRectangle bounds) {
68
+		this.bounds = bounds;
69
+		style.border.update(surface, z + 1, bounds);
70
+		
71
+		if (background != null)
72
+			background.close();
73
+		background = surface.fillRect(z, bounds, style.backgroundColor);
74
+		text.setPosition(
75
+				bounds.x + style.border.getPaddingLeft(),
76
+				bounds.y + style.border.getPaddingTop() + fontMetrics.getAscent());
77
+	}
78
+	
79
+	@Override
80
+	public DIRectangle getBounds() {
81
+		return bounds;
82
+	}
83
+	
84
+	@Override
85
+	public int getBaselineY() {
86
+		return style.border.getPaddingTop() + fontMetrics.getAscent();
87
+	}
88
+	
89
+	@Override
90
+	public LiveObject<DSizing> getSizing() {
91
+		return sizing;
92
+	}
93
+	
94
+	@Override
95
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
96
+		this.surface = surface;
97
+		this.z = z;
98
+		
99
+		DStylePath path = parent.getChild("tooltip", styleClass);
100
+		style = new DSimpleTooltipStyle(surface.getStylesheet(path));
101
+		fontMetrics = surface.getFontMetrics(style.font);
102
+		calculateSize();
103
+		
104
+		if (text != null)
105
+			text.close();
106
+		text = surface.drawText(z + 1, style.font, style.textColor, 0, 0, tooltip.getValue());
107
+	}
108
+	
109
+	@Override
110
+	public void unmount() {
111
+		if (background != null)
112
+			background.close();
113
+		if (text != null)
114
+			text.close();
115
+	}
116
+	
117
+	@Override
118
+	public void close() {
119
+		tooltipListener.close();
120
+		unmount();
121
+	}
122
+	
123
+	private void calculateSize() {
124
+		sizing.setValue(new DSizing(
125
+				style.border.getPaddingLeft() + fontMetrics.getWidth(tooltip.getValue()) + style.border.getPaddingRight(),
126
+				style.border.getPaddingTop() + fontMetrics.getAscent() + fontMetrics.getDescent() + style.border.getPaddingBottom()));
127
+	}
128
+}

DrawableGui/src/main/java/org/openzen/drawablegui/DTooltipStyle.java → DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltipStyle.java View File

15
  *
15
  *
16
  * @author Hoofdgebruiker
16
  * @author Hoofdgebruiker
17
  */
17
  */
18
-public class DTooltipStyle {
18
+public class DSimpleTooltipStyle {
19
 	public final DBorder border;
19
 	public final DBorder border;
20
 	public final DFont font;
20
 	public final DFont font;
21
 	public final int backgroundColor;
21
 	public final int backgroundColor;
22
 	public final int textColor;
22
 	public final int textColor;
23
 	
23
 	
24
-	public DTooltipStyle(DStyleDefinition style) {
24
+	public DSimpleTooltipStyle(DStyleDefinition style) {
25
 		border = style.getBorder("border", context -> new DCompositeBorder(
25
 		border = style.getBorder("border", context -> new DCompositeBorder(
26
-				new DLineBorder(0xFF, 1),
26
+				new DLineBorder(0xFF000000, 1),
27
 				new DPaddedBorder(context.dp(4), context.dp(4), context.dp(4), context.dp(4))));
27
 				new DPaddedBorder(context.dp(4), context.dp(4), context.dp(4), context.dp(4))));
28
 		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, context.sp(12)));
28
 		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, context.sp(12)));
29
 		backgroundColor = style.getColor("backgroundColor", 0xFFFFFFE1);
29
 		backgroundColor = style.getColor("backgroundColor", 0xFFFFFFE1);

+ 0
- 26
DrawableGui/src/main/java/org/openzen/drawablegui/DTooltip.java View File

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.DStylePath;
9
-
10
-/**
11
- *
12
- * @author Hoofdgebruiker
13
- */
14
-public interface DTooltip {
15
-	void setContext(DUIContext context, DStylePath parent);
16
-	
17
-	int getWidth();
18
-	
19
-	int getHeight();
20
-	
21
-	void setBounds(DIRectangle bounds);
22
-	
23
-	DIRectangle getBounds();
24
-	
25
-	void paint(DCanvas canvas);
26
-}

+ 0
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/DUIContext.java View File

40
 	
40
 	
41
 	DUIWindow openView(int x, int y, DAnchor anchor, DComponent root);
41
 	DUIWindow openView(int x, int y, DAnchor anchor, DComponent root);
42
 	
42
 	
43
-	DTooltipHandle openTooltip(int x, int y, DTooltip tooltip);
44
-	
45
 	default int dp(float dp) {
43
 	default int dp(float dp) {
46
 		return (int)(dp * getScale());
44
 		return (int)(dp * getScale());
47
 	}
45
 	}

+ 1
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/DUIWindow.java View File

13
  * @author Hoofdgebruiker
13
  * @author Hoofdgebruiker
14
  */
14
  */
15
 public interface DUIWindow {
15
 public interface DUIWindow {
16
-	DIRectangle getWindowBounds();
16
+	LiveObject<DIRectangle> getWindowBounds();
17
 	
17
 	
18
 	DUIContext getContext();
18
 	DUIContext getContext();
19
 	
19
 	

+ 0
- 274
DrawableGui/src/main/java/org/openzen/drawablegui/DVerticalLayout.java View File

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
-import org.openzen.drawablegui.listeners.ListenerHandle;
11
-import org.openzen.drawablegui.live.LiveObject;
12
-import org.openzen.drawablegui.live.MutableLiveObject;
13
-import org.openzen.drawablegui.live.SimpleLiveObject;
14
-import org.openzen.drawablegui.style.DStyleClass;
15
-import org.openzen.drawablegui.style.DStylePath;
16
-
17
-/**
18
- *
19
- * @author Hoofdgebruiker
20
- */
21
-public class DVerticalLayout extends BaseComponentGroup {
22
-	private final DStyleClass styleClass;
23
-	private final Alignment alignment;
24
-	private final Element[] components;
25
-	private final ListenerHandle<LiveObject.Listener<DSizing>>[] componentSizeListeners;
26
-	private final MutableLiveObject<DSizing> sizing = DSizing.create();
27
-	
28
-	private DUIContext context;
29
-	private DHorizontalLayoutStyle style;
30
-	private DIRectangle bounds;
31
-	private float totalGrow;
32
-	private float totalShrink;
33
-	
34
-	public DVerticalLayout(DStyleClass styleClass, Alignment alignment, Element... components) {
35
-		this.styleClass = styleClass;
36
-		this.alignment = alignment;
37
-		this.components = components;
38
-		
39
-		componentSizeListeners = new ListenerHandle[components.length];
40
-		totalGrow = 0;
41
-		totalShrink = 0;
42
-		
43
-		for (int i = 0; i < componentSizeListeners.length; i++) {
44
-			componentSizeListeners[i] = components[i].component.getSizing().addListener((oldValue, newValue) -> updateDimensionPreferences());
45
-			
46
-			totalGrow += components[i].grow;
47
-			totalShrink += components[i].shrink;
48
-		}
49
-	}
50
-
51
-	@Override
52
-	protected void forEachChild(Consumer<DComponent> children) {
53
-		for (Element element : components)
54
-			children.accept(element.component);
55
-	}
56
-
57
-	@Override
58
-	protected DComponent findChild(Predicate<DComponent> predicate) {
59
-		for (Element element : components)
60
-			if (predicate.test(element.component))
61
-				return element.component;
62
-		
63
-		return null;
64
-	}
65
-
66
-	@Override
67
-	public void setContext(DStylePath parent, DUIContext context) {
68
-		this.context = context;
69
-		
70
-		DStylePath path = parent.getChild("verticalLayout", styleClass);
71
-		style = new DHorizontalLayoutStyle(context.getStylesheets().get(context, path));
72
-		
73
-		for (Element element : components)
74
-			element.component.setContext(parent, context);
75
-		
76
-		layout();
77
-	}
78
-
79
-	@Override
80
-	public LiveObject<DSizing> getSizing() {
81
-		return sizing;
82
-	}
83
-
84
-	@Override
85
-	public DIRectangle getBounds() {
86
-		return bounds;
87
-	}
88
-
89
-	@Override
90
-	public int getBaselineY() {
91
-		return components[0].component.getBaselineY();
92
-	}
93
-
94
-	@Override
95
-	public void setBounds(DIRectangle bounds) {
96
-		this.bounds = bounds;
97
-		layout();
98
-	}
99
-
100
-	@Override
101
-	public void paint(DCanvas canvas) {
102
-		for (Element element : components) {
103
-			element.component.paint(canvas);
104
-		}
105
-	}
106
-
107
-	@Override
108
-	public void close() {
109
-		for (ListenerHandle<LiveObject.Listener<DSizing>> listener : componentSizeListeners) {
110
-			listener.close();
111
-		}
112
-	}
113
-	
114
-	public static enum Alignment {
115
-		TOP(0),
116
-		MIDDLE(0.5f),
117
-		BOTTOM(1);
118
-		
119
-		public final float align;
120
-		
121
-		Alignment(float align) {
122
-			this.align = align;
123
-		}
124
-	}
125
-	
126
-	public static enum ElementAlignment {
127
-		LEFT,
128
-		CENTER,
129
-		RIGHT,
130
-		STRETCH
131
-	}
132
-	
133
-	public static class Element {
134
-		public final DComponent component;
135
-		public final float grow;
136
-		public final float shrink;
137
-		public final ElementAlignment alignment;
138
-		
139
-		public Element(DComponent component, float grow, float shrink, ElementAlignment alignment) {
140
-			this.component = component;
141
-			this.grow = grow;
142
-			this.shrink = shrink;
143
-			this.alignment = alignment;
144
-		}
145
-	}
146
-	
147
-	private void layout() {
148
-		if (bounds == null || context == null)
149
-			return;
150
-		
151
-		DSizing myPreferences = sizing.getValue();
152
-		if (bounds.height < myPreferences.preferredHeight) {
153
-			layoutShrinked();
154
-		} else {
155
-			layoutGrown();
156
-		}
157
-	}
158
-	
159
-	private void layoutShrinked() {
160
-		DSizing myPreferences = sizing.getValue();
161
-		if (totalShrink == 0) {
162
-			// now what?
163
-			// shrink proportionally, we have to shrink...
164
-			float scale = (float)(bounds.height - (components.length - 1) * style.spacing) / (myPreferences.preferredHeight - (components.length - 1) * style.spacing);
165
-			int y = 0;
166
-			
167
-			for (int i = 0; i < components.length; i++) {
168
-				Element element = components[i];
169
-				DSizing preferences = element.component.getSizing().getValue();
170
-				int newY = y + preferences.preferredHeight;
171
-				float idealUnspacedY = newY * scale;
172
-				int idealY = (int)(idealUnspacedY + 0.5f + i * style.spacing);
173
-				layout(element, bounds.y + y, idealY - y);
174
-				y = idealY;
175
-			}
176
-		} else {
177
-			int delta = bounds.height - myPreferences.preferredHeight;
178
-			float deltaScaled = delta / totalShrink;
179
-			int y = bounds.y;
180
-			for (Element element : components) {
181
-				DSizing preferences = element.component.getSizing().getValue();
182
-				float scaledSize = preferences.preferredHeight + deltaScaled * element.shrink;
183
-				float idealUnspacedY = y + scaledSize;
184
-				int newY = (int)(idealUnspacedY + 0.5f);
185
-				layout(element, y, newY - y);
186
-				y = newY + style.spacing;
187
-			}
188
-		}
189
-	}
190
-	
191
-	private void layoutGrown() {
192
-		// resize according to grow values
193
-		DSizing myPreferences = sizing.getValue();
194
-		
195
-		if (totalGrow == 0) {
196
-			int deltaY = (int)(myPreferences.preferredHeight - bounds.height);
197
-			int y = bounds.y + (int)(deltaY * alignment.align);
198
-			for (Element element : components) {
199
-				DSizing preferences = element.component.getSizing().getValue();
200
-				int newY = y + preferences.preferredHeight;
201
-				layout(element, y, newY - y);
202
-				y = newY;
203
-			}
204
-		} else {
205
-			int delta = bounds.width - myPreferences.preferredWidth;
206
-			float deltaScaled = delta / totalGrow;
207
-			int y = bounds.y;
208
-			for (Element element : components) {
209
-				DSizing preferences = element.component.getSizing().getValue();
210
-				float scaledSize = preferences.preferredHeight + deltaScaled * element.grow;
211
-				float idealUnspacedY = y + scaledSize;
212
-				int newY = (int)(idealUnspacedY + 0.5f);
213
-				layout(element, y, newY - y);
214
-				y = newY + style.spacing;
215
-			}
216
-		}
217
-	}
218
-	
219
-	private void layout(Element element, int y, int height) {
220
-		DSizing preferences = element.component.getSizing().getValue();
221
-		int x;
222
-		int width;
223
-		switch (element.alignment) {
224
-			case LEFT:
225
-				width = Math.min(preferences.preferredWidth, bounds.width - style.paddingLeft - style.paddingRight);
226
-				x = bounds.x + style.paddingLeft;
227
-				break;
228
-			case CENTER:
229
-				width = Math.min(preferences.preferredWidth, bounds.width - style.paddingLeft - style.paddingRight);
230
-				x = bounds.x + style.paddingLeft + (bounds.width - style.paddingLeft - style.paddingRight - width) / 2;
231
-				break;
232
-			case RIGHT:
233
-				width = Math.min(preferences.preferredWidth, bounds.width - style.paddingLeft - style.paddingRight);
234
-				x = bounds.x + bounds.width - style.paddingLeft - width;
235
-				break;
236
-			case STRETCH:
237
-			default:
238
-				width = bounds.width - style.paddingLeft - style.paddingRight;
239
-				x = bounds.x + style.paddingLeft;
240
-				break;
241
-		}
242
-		element.component.setBounds(new DIRectangle(x, y, width, height));
243
-	}
244
-	
245
-	private void updateDimensionPreferences() {
246
-		int preferredWidth = 0;
247
-		int preferredHeight = -style.spacing;
248
-		int minimumWidth = 0;
249
-		int minimumHeight = -style.spacing;
250
-		int maximumWidth = Integer.MAX_VALUE;
251
-		int maximumHeight = -style.spacing;
252
-		
253
-		for (Element element : components) {
254
-			DSizing preferences = element.component.getSizing().getValue();
255
-			preferredWidth = Math.max(preferredWidth, preferences.preferredWidth);
256
-			preferredHeight += preferences.preferredHeight + style.spacing;
257
-			
258
-			minimumWidth = Math.max(minimumWidth, preferences.minimumWidth);
259
-			minimumHeight += preferences.minimumHeight + style.spacing;
260
-			
261
-			maximumWidth = Math.min(maximumWidth, preferences.maximumWidth);
262
-			maximumHeight += preferences.maximumHeight + style.spacing;
263
-		}
264
-		
265
-		DSizing preferences = new DSizing(
266
-				minimumWidth + style.paddingLeft + style.paddingRight,
267
-				minimumHeight + style.paddingTop + style.paddingBottom,
268
-				preferredWidth + style.paddingLeft + style.paddingRight,
269
-				preferredHeight + style.paddingTop + style.paddingBottom,
270
-				maximumWidth + style.paddingLeft + style.paddingRight,
271
-				maximumHeight + style.paddingTop + style.paddingBottom);
272
-		sizing.setValue(preferences);
273
-	}
274
-}

+ 0
- 31
DrawableGui/src/main/java/org/openzen/drawablegui/DVerticalLayoutStyle.java View File

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.DDpDimension;
9
-import org.openzen.drawablegui.style.DStyleDefinition;
10
-
11
-/**
12
- *
13
- * @author Hoofdgebruiker
14
- */
15
-public class DVerticalLayoutStyle {
16
-	public final int spacing;
17
-	
18
-	public final int paddingTop;
19
-	public final int paddingLeft;
20
-	public final int paddingRight;
21
-	public final int paddingBottom;
22
-	
23
-	public DVerticalLayoutStyle(DStyleDefinition style) {
24
-		spacing = style.getDimension("spacing", new DDpDimension(8));
25
-		
26
-		paddingTop = style.getDimension("paddingTop", new DDpDimension(8));
27
-		paddingLeft = style.getDimension("paddingLeft", new DDpDimension(8));
28
-		paddingRight = style.getDimension("paddingRight", new DDpDimension(8));
29
-		paddingBottom = style.getDimension("paddingBottom", new DDpDimension(8));
30
-	}
31
-}

+ 22
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/Destructible.java View File

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.List;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface Destructible extends AutoCloseable {
15
+	public static <T extends Destructible> void close(List<T> list) {
16
+		for (T item : list)
17
+			item.close();
18
+	}
19
+	
20
+	@Override
21
+	public void close();
22
+}

+ 15
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/border/DBorder.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.border;
6
 package org.openzen.drawablegui.border;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
8
+import java.io.Closeable;
9
 import org.openzen.drawablegui.DIRectangle;
9
 import org.openzen.drawablegui.DIRectangle;
10
+import org.openzen.drawablegui.draw.DDrawSurface;
10
 
11
 
11
 /**
12
 /**
12
  *
13
  *
13
  * @author Hoofdgebruiker
14
  * @author Hoofdgebruiker
14
  */
15
  */
15
-public interface DBorder {
16
-	public void paint(DCanvas canvas, DIRectangle bounds);
16
+public interface DBorder extends Closeable {
17
+	public void update(DDrawSurface surface, int z, DIRectangle bounds);
17
 	
18
 	
18
 	public int getPaddingLeft();
19
 	public int getPaddingLeft();
19
 	
20
 	
22
 	public int getPaddingTop();
23
 	public int getPaddingTop();
23
 	
24
 	
24
 	public int getPaddingBottom();
25
 	public int getPaddingBottom();
26
+	
27
+	default int getPaddingHorizontal() {
28
+		return getPaddingLeft() + getPaddingRight();
29
+	}
30
+	
31
+	default int getPaddingVertical() {
32
+		return getPaddingTop() + getPaddingBottom();
33
+	}
34
+	
35
+	@Override
36
+	void close();
25
 }
37
 }

+ 9
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCompositeBorder.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.border;
6
 package org.openzen.drawablegui.border;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DIRectangle;
8
 import org.openzen.drawablegui.DIRectangle;
9
+import org.openzen.drawablegui.draw.DDrawSurface;
10
 
10
 
11
 /**
11
 /**
12
  *
12
  *
20
 	}
20
 	}
21
 
21
 
22
 	@Override
22
 	@Override
23
-	public void paint(DCanvas canvas, DIRectangle bounds) {
23
+	public void update(DDrawSurface surface, int z, DIRectangle bounds) {
24
 		for (DBorder border : borders) {
24
 		for (DBorder border : borders) {
25
-			border.paint(canvas, bounds);
25
+			border.update(surface, z, bounds);
26
 			bounds = new DIRectangle(
26
 			bounds = new DIRectangle(
27
 					bounds.x + border.getPaddingLeft(),
27
 					bounds.x + border.getPaddingLeft(),
28
 					bounds.y + border.getPaddingTop(),
28
 					bounds.y + border.getPaddingTop(),
62
 			total += border.getPaddingBottom();
62
 			total += border.getPaddingBottom();
63
 		return total;
63
 		return total;
64
 	}
64
 	}
65
+	
66
+	@Override
67
+	public void close() {
68
+		for (DBorder border : borders)
69
+			border.close();
70
+	}
65
 }
71
 }

+ 63
- 42
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.border;
6
 package org.openzen.drawablegui.border;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DComponent;
8
 import org.openzen.drawablegui.DComponent;
10
 import org.openzen.drawablegui.DSizing;
9
 import org.openzen.drawablegui.DSizing;
11
 import org.openzen.drawablegui.DMouseEvent;
10
 import org.openzen.drawablegui.DMouseEvent;
12
 import org.openzen.drawablegui.DPath;
11
 import org.openzen.drawablegui.DPath;
13
 import org.openzen.drawablegui.DTransform2D;
12
 import org.openzen.drawablegui.DTransform2D;
14
-import org.openzen.drawablegui.DUIContext;
15
 import org.openzen.drawablegui.DUIWindow;
13
 import org.openzen.drawablegui.DUIWindow;
16
 import org.openzen.drawablegui.DIRectangle;
14
 import org.openzen.drawablegui.DIRectangle;
15
+import org.openzen.drawablegui.draw.DDrawSurface;
16
+import org.openzen.drawablegui.draw.DDrawnRectangle;
17
+import org.openzen.drawablegui.draw.DDrawnShape;
17
 import org.openzen.drawablegui.listeners.ListenerHandle;
18
 import org.openzen.drawablegui.listeners.ListenerHandle;
18
 import org.openzen.drawablegui.live.ImmutableLiveObject;
19
 import org.openzen.drawablegui.live.ImmutableLiveObject;
19
 import org.openzen.drawablegui.live.LiveBool;
20
 import org.openzen.drawablegui.live.LiveBool;
30
 	private final DComponent content;
31
 	private final DComponent content;
31
 	private final LiveObject<DSizing> sizing = new ImmutableLiveObject<>(DSizing.EMPTY);
32
 	private final LiveObject<DSizing> sizing = new ImmutableLiveObject<>(DSizing.EMPTY);
32
 	
33
 	
33
-	private DUIContext context;
34
+	private DDrawSurface surface;
35
+	private int z;
34
 	private DCustomWindowBorderStyle style;
36
 	private DCustomWindowBorderStyle style;
35
 	private DIRectangle bounds;
37
 	private DIRectangle bounds;
36
-	private DPath border;
37
 	
38
 	
38
 	private LiveBool active;
39
 	private LiveBool active;
39
 	private LiveObject<DUIWindow.State> state;
40
 	private LiveObject<DUIWindow.State> state;
41
 	private ListenerHandle<LiveObject.Listener<DUIWindow.State>> stateListener;
42
 	private ListenerHandle<LiveObject.Listener<DUIWindow.State>> stateListener;
42
 	private ListenerHandle<LiveBool.Listener> activeListener;
43
 	private ListenerHandle<LiveBool.Listener> activeListener;
43
 	
44
 	
45
+	private DDrawnRectangle background;
46
+	private DDrawnShape shadowedBackground;
47
+	private DDrawnShape border;
48
+	
44
 	public DCustomWindowBorder(DStyleClass styleClass, DComponent content) {
49
 	public DCustomWindowBorder(DStyleClass styleClass, DComponent content) {
45
 		this.styleClass = styleClass;
50
 		this.styleClass = styleClass;
46
 		this.content = content;
51
 		this.content = content;
47
 	}
52
 	}
48
 
53
 
49
 	@Override
54
 	@Override
50
-	public void setContext(DStylePath parent, DUIContext context) {
51
-		this.context = context;
52
-		content.setContext(parent, context);
55
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
56
+		this.surface = surface;
57
+		this.z = z;
58
+		content.mount(parent, z + 1, surface);
53
 		
59
 		
54
-		state = context.getWindow().getWindowState();
55
-		active = context.getWindow().getActive();
60
+		state = surface.getContext().getWindow().getWindowState();
61
+		active = surface.getContext().getWindow().getActive();
56
 		stateListener = state.addListener(this::onStateChanged);
62
 		stateListener = state.addListener(this::onStateChanged);
57
 		activeListener = active.addListener(this::onActiveChanged);
63
 		activeListener = active.addListener(this::onActiveChanged);
58
 		
64
 		
59
 		DStylePath path = parent.getChild("customwindowborder", styleClass);
65
 		DStylePath path = parent.getChild("customwindowborder", styleClass);
60
-		style = new DCustomWindowBorderStyle(context.getStylesheets().get(context, path));
66
+		style = new DCustomWindowBorderStyle(surface.getStylesheet(path));
61
 		
67
 		
62
 		if (bounds != null)
68
 		if (bounds != null)
63
 			layout();
69
 			layout();
64
 	}
70
 	}
71
+	
72
+	@Override
73
+	public void unmount() {
74
+		if (background != null)
75
+			background.close();
76
+		if (shadowedBackground != null)
77
+			shadowedBackground.close();
78
+		if (border != null)
79
+			border.close();
80
+	}
65
 
81
 
66
 	@Override
82
 	@Override
67
 	public LiveObject<DSizing> getSizing() {
83
 	public LiveObject<DSizing> getSizing() {
90
 			return;
106
 			return;
91
 		
107
 		
92
 		if (state.getValue() != DUIWindow.State.MAXIMIZED) {
108
 		if (state.getValue() != DUIWindow.State.MAXIMIZED) {
93
-			border = DPath.rectangle(
94
-				bounds.x + style.padding,
95
-				bounds.y + style.padding,
96
-				bounds.width - 2 * style.padding - style.borderWidth,
97
-				bounds.height - 2 * style.padding - style.borderWidth);
109
+			DPath path = DPath.rectangle(
110
+					bounds.x + style.padding,
111
+					bounds.y + style.padding,
112
+					bounds.width - 2 * style.padding - style.borderWidth,
113
+					bounds.height - 2 * style.padding - style.borderWidth);
114
+			if (border != null)
115
+				border.close();
116
+			border = surface.strokePath(
117
+					z + 1,
118
+					path,
119
+					DTransform2D.IDENTITY,
120
+					active.getValue() ? style.focusedBorderColor : style.inactiveBorderColor,
121
+					style.borderWidth);
98
 			
122
 			
99
 			int spacing = style.borderWidth + style.padding;
123
 			int spacing = style.borderWidth + style.padding;
100
 			DIRectangle inner = new DIRectangle(
124
 			DIRectangle inner = new DIRectangle(
104
 					bounds.height - 2 * spacing);
128
 					bounds.height - 2 * spacing);
105
 
129
 
106
 			content.setBounds(inner);
130
 			content.setBounds(inner);
131
+			
132
+			if (shadowedBackground != null)
133
+				shadowedBackground.close();
134
+			if (background != null) {
135
+				background.close();
136
+				background = null;
137
+			}
138
+			shadowedBackground = surface.shadowPath(z, path, DTransform2D.IDENTITY, style.backgroundColor, style.shadow);
107
 		} else {
139
 		} else {
108
 			content.setBounds(bounds);
140
 			content.setBounds(bounds);
109
-		}
110
-		context.repaint(bounds);
111
-	}
112
-
113
-	@Override
114
-	public void paint(DCanvas canvas) {
115
-		if (state.getValue() != DUIWindow.State.MAXIMIZED) {
116
-			int spacing = style.borderWidth + style.padding;
117
-			DIRectangle canvasBounds = canvas.getBounds();
118
-			if (canvasBounds == null
119
-					|| canvasBounds.x < bounds.x + spacing
120
-					|| canvasBounds.y < bounds.y + spacing
121
-					|| canvasBounds.x + canvasBounds.width > bounds.x + bounds.width - spacing
122
-					|| canvasBounds.y + canvasBounds.height > bounds.y + bounds.height - spacing) {
123
-				canvas.shadowPath(border, DTransform2D.IDENTITY, style.shadow);
124
-				canvas.fillPath(border, DTransform2D.IDENTITY, style.backgroundColor);
125
-				canvas.strokePath(
126
-						border,
127
-						DTransform2D.IDENTITY,
128
-						active.getValue() ? style.focusedBorderColor : style.inactiveBorderColor,
129
-						style.borderWidth);
141
+			
142
+			if (shadowedBackground != null) {
143
+				shadowedBackground.close();
144
+				shadowedBackground = null;
145
+			}
146
+			if (border != null) {
147
+				border.close();
148
+				border = null;
149
+			}
150
+			if (background == null) {
151
+				background = surface.fillRect(z, bounds, style.backgroundColor);
152
+			} else {
153
+				background.setRectangle(bounds);
130
 			}
154
 			}
131
-		} else {
132
-			canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.backgroundColor);
133
 		}
155
 		}
134
-		
135
-		content.paint(canvas);
136
 	}
156
 	}
137
 
157
 
138
 	@Override
158
 	@Override
177
 	
197
 	
178
 	@Override
198
 	@Override
179
 	public void close() {
199
 	public void close() {
180
-		
200
+		unmount();
181
 	}
201
 	}
182
 	
202
 	
183
 	private void onStateChanged(DUIWindow.State oldValue, DUIWindow.State newValue) {
203
 	private void onStateChanged(DUIWindow.State oldValue, DUIWindow.State newValue) {
185
 	}
205
 	}
186
 	
206
 	
187
 	private void onActiveChanged(boolean oldValue, boolean newValue) {
207
 	private void onActiveChanged(boolean oldValue, boolean newValue) {
188
-		context.repaint(bounds);
208
+		if (border != null)
209
+			border.setColor(newValue ? style.focusedBorderColor : style.inactiveBorderColor);
189
 	}
210
 	}
190
 }
211
 }

+ 9
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.border;
6
 package org.openzen.drawablegui.border;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DIRectangle;
8
 import org.openzen.drawablegui.DIRectangle;
9
+import org.openzen.drawablegui.draw.DDrawSurface;
10
+import org.openzen.drawablegui.style.DBorderElement;
10
 
11
 
11
 /**
12
 /**
12
  *
13
  *
14
  */
15
  */
15
 public class DEmptyBorder implements DBorder {
16
 public class DEmptyBorder implements DBorder {
16
 	public static final DEmptyBorder INSTANCE = new DEmptyBorder();
17
 	public static final DEmptyBorder INSTANCE = new DEmptyBorder();
18
+	public static final DBorderElement ELEMENT = context -> INSTANCE;
17
 	
19
 	
18
 	private DEmptyBorder() {}
20
 	private DEmptyBorder() {}
19
 	
21
 	
20
 	@Override
22
 	@Override
21
-	public void paint(DCanvas canvas, DIRectangle bounds) {
23
+	public void update(DDrawSurface surface, int z, DIRectangle bounds) {
22
 		
24
 		
23
 	}
25
 	}
24
 
26
 
41
 	public int getPaddingBottom() {
43
 	public int getPaddingBottom() {
42
 		return 0;
44
 		return 0;
43
 	}
45
 	}
46
+
47
+	@Override
48
+	public void close() {
49
+		
50
+	}
44
 }
51
 }

+ 15
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.border;
6
 package org.openzen.drawablegui.border;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DTransform2D;
8
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DIRectangle;
9
 import org.openzen.drawablegui.DIRectangle;
10
+import org.openzen.drawablegui.draw.DDrawSurface;
11
+import org.openzen.drawablegui.draw.DDrawnShape;
11
 
12
 
12
 /**
13
 /**
13
  *
14
  *
17
 	private final int color;
18
 	private final int color;
18
 	private final int borderWidth;
19
 	private final int borderWidth;
19
 	
20
 	
21
+	private DDrawnShape shape;
22
+	
20
 	public DLineBorder(int color, int borderWidth) {
23
 	public DLineBorder(int color, int borderWidth) {
21
 		this.color = color;
24
 		this.color = color;
22
 		this.borderWidth = borderWidth;
25
 		this.borderWidth = borderWidth;
23
 	}
26
 	}
24
 
27
 
25
 	@Override
28
 	@Override
26
-	public void paint(DCanvas canvas, DIRectangle bounds) {
27
-		canvas.strokePath(tracer -> {
29
+	public void update(DDrawSurface surface, int z, DIRectangle bounds) {
30
+		if (shape != null)
31
+			shape.close();
32
+		
33
+		shape = surface.strokePath(z, tracer -> {
28
 				tracer.moveTo(bounds.x, bounds.y);
34
 				tracer.moveTo(bounds.x, bounds.y);
29
 				tracer.lineTo(bounds.x + bounds.width - borderWidth, bounds.y);
35
 				tracer.lineTo(bounds.x + bounds.width - borderWidth, bounds.y);
30
 				tracer.lineTo(bounds.x + bounds.width - borderWidth, bounds.y + bounds.height - borderWidth);
36
 				tracer.lineTo(bounds.x + bounds.width - borderWidth, bounds.y + bounds.height - borderWidth);
52
 	public int getPaddingBottom() {
58
 	public int getPaddingBottom() {
53
 		return borderWidth;
59
 		return borderWidth;
54
 	}
60
 	}
61
+
62
+	@Override
63
+	public void close() {
64
+		if (shape != null)
65
+			shape.close();
66
+	}
55
 }
67
 }

+ 11
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/border/DPaddedBorder.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.border;
6
 package org.openzen.drawablegui.border;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DIRectangle;
8
 import org.openzen.drawablegui.DIRectangle;
9
+import org.openzen.drawablegui.draw.DDrawSurface;
10
 
10
 
11
 /**
11
 /**
12
  *
12
  *
24
 		this.right = right;
24
 		this.right = right;
25
 		this.bottom = bottom;
25
 		this.bottom = bottom;
26
 	}
26
 	}
27
+	
28
+	public DPaddedBorder(int size) {
29
+		this(size, size, size, size);
30
+	}
27
 
31
 
28
 	@Override
32
 	@Override
29
-	public void paint(DCanvas canvas, DIRectangle bounds) {
33
+	public void update(DDrawSurface surface, int z, DIRectangle bounds) {
30
 		// nothing to paint
34
 		// nothing to paint
31
 	}
35
 	}
32
 
36
 
49
 	public int getPaddingBottom() {
53
 	public int getPaddingBottom() {
50
 		return bottom;
54
 		return bottom;
51
 	}
55
 	}
56
+
57
+	@Override
58
+	public void close() {
59
+		
60
+	}
52
 }
61
 }

+ 107
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DSideBorder.java View File

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.DIRectangle;
9
+import org.openzen.drawablegui.DPath;
10
+import org.openzen.drawablegui.DTransform2D;
11
+import org.openzen.drawablegui.draw.DDrawSurface;
12
+import org.openzen.drawablegui.draw.DDrawnShape;
13
+
14
+/**
15
+ *
16
+ * @author Hoofdgebruiker
17
+ */
18
+public class DSideBorder implements DBorder {
19
+	public final int leftWidth;
20
+	public final int leftColor;
21
+	public final int topWidth;
22
+	public final int topColor;
23
+	public final int rightWidth;
24
+	public final int rightColor;
25
+	public final int bottomWidth;
26
+	public final int bottomColor;
27
+	
28
+	private DDrawnShape left;
29
+	private DDrawnShape top;
30
+	private DDrawnShape right;
31
+	private DDrawnShape bottom;
32
+	
33
+	public DSideBorder(
34
+			int leftWidth, int leftColor,
35
+			int topWidth, int topColor,
36
+			int rightWidth, int rightColor,
37
+			int bottomWidth, int bottomColor) {
38
+		this.leftWidth = leftWidth;
39
+		this.leftColor = leftColor;
40
+		this.topWidth = topWidth;
41
+		this.topColor = topColor;
42
+		this.rightWidth = rightWidth;
43
+		this.rightColor = rightColor;
44
+		this.bottomWidth = bottomWidth;
45
+		this.bottomColor = bottomColor;
46
+	}
47
+
48
+	@Override
49
+	public void update(DDrawSurface surface, int z, DIRectangle bounds) {
50
+		if (leftWidth > 0) {
51
+			int x = bounds.x;
52
+			if (left != null)
53
+				left.close();
54
+			left = surface.strokePath(z, DPath.line(x, bounds.y, x, bounds.y + bounds.height), DTransform2D.IDENTITY, topColor, topWidth);
55
+		}
56
+		if (topWidth > 0) {
57
+			int y = bounds.y;
58
+			if (top != null)
59
+				top.close();
60
+			top = surface.strokePath(z, DPath.line(bounds.x, y, bounds.x + bounds.width, y), DTransform2D.IDENTITY, topColor, topWidth);
61
+		}
62
+		if (rightWidth > 0) {
63
+			int x = bounds.x + bounds.width - rightWidth;
64
+			if (right != null)
65
+				right.close();
66
+			right = surface.strokePath(z, DPath.line(x, bounds.y, x, bounds.y + bounds.height), DTransform2D.IDENTITY, topColor, topWidth);
67
+		}
68
+		if (bottomWidth > 0) {
69
+			int y = bounds.y + bounds.height - bottomWidth;
70
+			if (bottom != null)
71
+				bottom.close();
72
+			bottom = surface.strokePath(z, DPath.line(bounds.x, y, bounds.x + bounds.width, y), DTransform2D.IDENTITY, topColor, topWidth);
73
+		}
74
+	}
75
+
76
+	@Override
77
+	public int getPaddingLeft() {
78
+		return leftWidth;
79
+	}
80
+
81
+	@Override
82
+	public int getPaddingRight() {
83
+		return rightWidth;
84
+	}
85
+
86
+	@Override
87
+	public int getPaddingTop() {
88
+		return topWidth;
89
+	}
90
+
91
+	@Override
92
+	public int getPaddingBottom() {
93
+		return bottomWidth;
94
+	}
95
+
96
+	@Override
97
+	public void close() {
98
+		if (left != null)
99
+			left.close();
100
+		if (top != null)
101
+			top.close();
102
+		if (right != null)
103
+			right.close();
104
+		if (bottom != null)
105
+			bottom.close();
106
+	}
107
+}

+ 22
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawSurface.java View File

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.draw;
7
+
8
+import org.openzen.drawablegui.DUIContext;
9
+import org.openzen.drawablegui.style.DStyleDefinition;
10
+import org.openzen.drawablegui.style.DStylePath;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public interface DDrawSurface extends DDrawTarget {
17
+	DUIContext getContext();
18
+	
19
+	DStyleDefinition getStylesheet(DStylePath path);
20
+	
21
+	DSubSurface createSubSurface(int z);
22
+}

+ 37
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawTarget.java View File

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.draw;
7
+
8
+import org.openzen.drawablegui.DFont;
9
+import org.openzen.drawablegui.DFontMetrics;
10
+import org.openzen.drawablegui.DIRectangle;
11
+import org.openzen.drawablegui.DPath;
12
+import org.openzen.drawablegui.DTransform2D;
13
+import org.openzen.drawablegui.style.DShadow;
14
+
15
+/**
16
+ *
17
+ * @author Hoofdgebruiker
18
+ */
19
+public interface DDrawTarget {
20
+	public static final int INSTANCE_COLOR = 1;
21
+	
22
+	DFontMetrics getFontMetrics(DFont font);
23
+	
24
+	float getScale();
25
+	
26
+	float getTextScale();
27
+	
28
+	DDrawnText drawText(int z, DFont font, int color, float x, float y, String text);
29
+	
30
+	DDrawnRectangle fillRect(int z, DIRectangle rectangle, int color);
31
+	
32
+	DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth);
33
+	
34
+	DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color);
35
+	
36
+	DDrawnShape shadowPath(int z, DPath path, DTransform2D transform, int color, DShadow shadow);
37
+}

+ 14
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnColorableElement.java View File

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.draw;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface DDrawnColorableElement extends DDrawnElement {
13
+	void setColor(int color);
14
+}

+ 20
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnElement.java View File

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.draw;
7
+
8
+import org.openzen.drawablegui.DIRectangle;
9
+import org.openzen.drawablegui.DTransform2D;
10
+import org.openzen.drawablegui.Destructible;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public interface DDrawnElement extends Destructible {
17
+	void setTransform(DTransform2D transform);
18
+	
19
+	DIRectangle getBounds();
20
+}

+ 16
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnRectangle.java View File

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.draw;
7
+
8
+import org.openzen.drawablegui.DIRectangle;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface DDrawnRectangle extends DDrawnColorableElement {
15
+	void setRectangle(DIRectangle rectangle);
16
+}

DrawableGui/src/main/java/org/openzen/drawablegui/DTooltipHandle.java → DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnShape.java View File

3
  * To change this template file, choose Tools | Templates
3
  * To change this template file, choose Tools | Templates
4
  * and open the template in the editor.
4
  * and open the template in the editor.
5
  */
5
  */
6
-package org.openzen.drawablegui;
6
+package org.openzen.drawablegui.draw;
7
 
7
 
8
 /**
8
 /**
9
  *
9
  *
10
  * @author Hoofdgebruiker
10
  * @author Hoofdgebruiker
11
  */
11
  */
12
-public interface DTooltipHandle {
13
-	void close();
12
+public interface DDrawnShape extends DDrawnColorableElement {
13
+	
14
 }
14
 }

+ 21
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnText.java View File

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.draw;
7
+
8
+import org.openzen.drawablegui.DTransform2D;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public interface DDrawnText extends DDrawnColorableElement {
15
+	@Override
16
+	default void setTransform(DTransform2D transform) { // only uses position, not scaling or rotation
17
+		setPosition(transform.xx, transform.yy);
18
+	}
19
+	
20
+	void setPosition(float x, float y);
21
+}

+ 24
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DSubSurface.java View File

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.draw;
7
+
8
+import org.openzen.drawablegui.DIRectangle;
9
+import org.openzen.drawablegui.DTransform2D;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface DSubSurface extends DDrawnElement, DDrawSurface {
16
+	@Override
17
+	default void setTransform(DTransform2D transform) {
18
+		setOffset((int)transform.xx, (int)transform.yy);
19
+	}
20
+	
21
+	void setOffset(int x, int y);
22
+	
23
+	void setClip(DIRectangle bounds);
24
+}

+ 42
- 25
DrawableGui/src/main/java/org/openzen/drawablegui/form/DForm.java View File

8
 import java.util.function.Consumer;
8
 import java.util.function.Consumer;
9
 import java.util.function.Predicate;
9
 import java.util.function.Predicate;
10
 import org.openzen.drawablegui.BaseComponentGroup;
10
 import org.openzen.drawablegui.BaseComponentGroup;
11
-import org.openzen.drawablegui.DCanvas;
12
 import org.openzen.drawablegui.DComponent;
11
 import org.openzen.drawablegui.DComponent;
13
 import org.openzen.drawablegui.DSizing;
12
 import org.openzen.drawablegui.DSizing;
14
 import org.openzen.drawablegui.DFontMetrics;
13
 import org.openzen.drawablegui.DFontMetrics;
15
 import org.openzen.drawablegui.DIRectangle;
14
 import org.openzen.drawablegui.DIRectangle;
16
-import org.openzen.drawablegui.DUIContext;
15
+import org.openzen.drawablegui.draw.DDrawSurface;
16
+import org.openzen.drawablegui.draw.DDrawnText;
17
 import org.openzen.drawablegui.live.LiveObject;
17
 import org.openzen.drawablegui.live.LiveObject;
18
 import org.openzen.drawablegui.live.MutableLiveObject;
18
 import org.openzen.drawablegui.live.MutableLiveObject;
19
 import org.openzen.drawablegui.style.DStyleClass;
19
 import org.openzen.drawablegui.style.DStyleClass;
29
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
29
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
30
 	
30
 	
31
 	private DIRectangle bounds;
31
 	private DIRectangle bounds;
32
-	private DUIContext context;
32
+	private DDrawSurface context;
33
 	private DFormStyle style;
33
 	private DFormStyle style;
34
 	private DFontMetrics fontMetrics;
34
 	private DFontMetrics fontMetrics;
35
 	private int maxFieldWidth;
35
 	private int maxFieldWidth;
36
 	private int maxLabelWidth;
36
 	private int maxLabelWidth;
37
 	
37
 	
38
+	private final DDrawnText[] labels;
39
+	
38
 	public DForm(DStyleClass styleClass, DFormComponent... components) {
40
 	public DForm(DStyleClass styleClass, DFormComponent... components) {
39
 		this.styleClass = styleClass;
41
 		this.styleClass = styleClass;
40
 		this.components = components;
42
 		this.components = components;
43
+		
44
+		labels = new DDrawnText[components.length];
41
 	}
45
 	}
42
 
46
 
43
 	@Override
47
 	@Override
44
-	public void setContext(DStylePath parent, DUIContext context) {
45
-		this.context = context;
48
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
49
+		this.context = surface;
46
 		
50
 		
47
 		DStylePath path = parent.getChild("form", styleClass);
51
 		DStylePath path = parent.getChild("form", styleClass);
48
-		style = new DFormStyle(context.getStylesheets().get(context, path));
49
-		fontMetrics = context.getFontMetrics(style.labelFont);
52
+		style = new DFormStyle(surface.getStylesheet(path));
53
+		fontMetrics = surface.getFontMetrics(style.labelFont);
54
+		
50
 		for (DFormComponent component : components)
55
 		for (DFormComponent component : components)
51
-			component.component.setContext(path, context);
56
+			component.component.mount(path, z + 1, surface);
52
 		
57
 		
53
 		int height = style.paddingBottom + style.paddingTop;
58
 		int height = style.paddingBottom + style.paddingTop;
54
 		int maxLabelWidth = style.minimumLabelSize;
59
 		int maxLabelWidth = style.minimumLabelSize;
71
 		
76
 		
72
 		if (bounds != null)
77
 		if (bounds != null)
73
 			layout();
78
 			layout();
79
+		
80
+		for (int i = 0; i < labels.length; i++) {
81
+			if (labels[i] != null)
82
+				labels[i].close();
83
+			labels[i] = surface.drawText(z + 1, style.labelFont, style.labelColor, 0, 0, components[i].label);
84
+		}
85
+	}
86
+	
87
+	@Override
88
+	public void unmount() {
89
+		for (int i = 0; i < labels.length; i++) {
90
+			if (labels[i] == null)
91
+				continue;
92
+			
93
+			labels[i].close();
94
+			labels[i] = null;
95
+		}
96
+		
97
+		for (DFormComponent component : components)
98
+			component.component.unmount();
74
 	}
99
 	}
75
 
100
 
76
 	@Override
101
 	@Override
97
 			layout();
122
 			layout();
98
 	}
123
 	}
99
 
124
 
100
-	@Override
101
-	public void paint(DCanvas canvas) {
102
-		int x = style.paddingLeft;
103
-		int y = style.paddingTop;
104
-		for (DFormComponent component : components) {
105
-			int baseline = component.component.getBaselineY();
106
-			if (baseline == -1)
107
-				baseline = fontMetrics.getAscent();
108
-			canvas.drawText(style.labelFont, style.labelColor, x, y + baseline, component.label);
109
-			component.component.paint(canvas);
110
-			
111
-			y += component.component.getSizing().getValue().preferredHeight + style.spacing;
112
-		}
113
-	}
114
-
115
 	@Override
125
 	@Override
116
 	public void close() {
126
 	public void close() {
117
-		
127
+		unmount();
118
 	}
128
 	}
119
 	
129
 	
120
 	private void layout() {
130
 	private void layout() {
121
 		int x = bounds.x + style.paddingLeft;
131
 		int x = bounds.x + style.paddingLeft;
122
 		int y = bounds.y + style.paddingBottom;
132
 		int y = bounds.y + style.paddingBottom;
123
 		
133
 		
124
-		for (DFormComponent component : components) {
134
+		for (int i = 0; i < components.length; i++) {
135
+			DFormComponent component = components[i];
136
+			
125
 			int preferredHeight = component.component.getSizing().getValue().preferredHeight;
137
 			int preferredHeight = component.component.getSizing().getValue().preferredHeight;
126
 			DIRectangle componentBounds = new DIRectangle(x + maxLabelWidth, y, bounds.width - maxLabelWidth - style.paddingLeft - style.paddingRight - style.spacing, preferredHeight);
138
 			DIRectangle componentBounds = new DIRectangle(x + maxLabelWidth, y, bounds.width - maxLabelWidth - style.paddingLeft - style.paddingRight - style.spacing, preferredHeight);
127
 			component.component.setBounds(componentBounds);
139
 			component.component.setBounds(componentBounds);
128
 			
140
 			
141
+			int baseline = component.component.getBaselineY();
142
+			if (baseline == -1)
143
+				baseline = fontMetrics.getAscent();
144
+			labels[i].setPosition(x, y + baseline);
145
+			
129
 			y += preferredHeight + style.spacing;
146
 			y += preferredHeight + style.spacing;
130
 		}
147
 		}
131
 	}
148
 	}

+ 463
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/layout/DLinearLayout.java View File

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.layout;
7
+
8
+import java.util.function.Consumer;
9
+import java.util.function.Predicate;
10
+import org.openzen.drawablegui.BaseComponentGroup;
11
+import org.openzen.drawablegui.DComponent;
12
+import org.openzen.drawablegui.DIRectangle;
13
+import org.openzen.drawablegui.DSizing;
14
+import org.openzen.drawablegui.DTransform2D;
15
+import org.openzen.drawablegui.draw.DDrawSurface;
16
+import org.openzen.drawablegui.draw.DDrawnShape;
17
+import org.openzen.drawablegui.listeners.ListenerHandle;
18
+import org.openzen.drawablegui.live.LiveObject;
19
+import org.openzen.drawablegui.live.MutableLiveObject;
20
+import org.openzen.drawablegui.style.DStyleClass;
21
+import org.openzen.drawablegui.style.DStylePath;
22
+
23
+/**
24
+ *
25
+ * @author Hoofdgebruiker
26
+ */
27
+public class DLinearLayout extends BaseComponentGroup {
28
+	private final DStyleClass styleClass;
29
+	private final Orientation orientation;
30
+	private final Alignment alignment;
31
+	private final Element[] components;
32
+	private final ListenerHandle<LiveObject.Listener<DSizing>>[] componentSizeListeners;
33
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
34
+	
35
+	private DDrawSurface surface;
36
+	private int z;
37
+	private DLinearLayoutStyle style;
38
+	private DIRectangle bounds;
39
+	private float totalGrow;
40
+	private float totalShrink;
41
+	private DDrawnShape shape;
42
+	
43
+	public DLinearLayout(DStyleClass styleClass, Orientation orientation, Alignment alignment, Element... components) {
44
+		this.styleClass = styleClass;
45
+		this.orientation = orientation;
46
+		this.alignment = alignment;
47
+		this.components = components;
48
+		
49
+		componentSizeListeners = new ListenerHandle[components.length];
50
+		totalGrow = 0;
51
+		totalShrink = 0;
52
+		
53
+		for (int i = 0; i < componentSizeListeners.length; i++) {
54
+			componentSizeListeners[i] = components[i].component.getSizing().addListener((oldValue, newValue) -> updateSizing());
55
+			
56
+			totalGrow += components[i].grow;
57
+			totalShrink += components[i].shrink;
58
+		}
59
+	}
60
+
61
+	@Override
62
+	protected void forEachChild(Consumer<DComponent> children) {
63
+		for (Element element : components)
64
+			children.accept(element.component);
65
+	}
66
+
67
+	@Override
68
+	protected DComponent findChild(Predicate<DComponent> predicate) {
69
+		for (Element element : components)
70
+			if (predicate.test(element.component))
71
+				return element.component;
72
+		
73
+		return null;
74
+	}
75
+
76
+	@Override
77
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
78
+		this.surface = surface;
79
+		this.z = z;
80
+		
81
+		DStylePath path = parent.getChild("linearlayout", styleClass);
82
+		style = new DLinearLayoutStyle(surface.getStylesheet(path));
83
+		
84
+		for (Element element : components)
85
+			element.component.mount(parent, z + 1, surface);
86
+	}
87
+	
88
+	@Override
89
+	public void unmount() {
90
+		for (Element element : components)
91
+			element.component.unmount();
92
+	}
93
+
94
+	@Override
95
+	public LiveObject<DSizing> getSizing() {
96
+		return sizing;
97
+	}
98
+
99
+	@Override
100
+	public DIRectangle getBounds() {
101
+		return bounds;
102
+	}
103
+
104
+	@Override
105
+	public int getBaselineY() {
106
+		return components[0].component.getBaselineY();
107
+	}
108
+
109
+	@Override
110
+	public void setBounds(DIRectangle bounds) {
111
+		if (bounds.equals(this.bounds))
112
+			return;
113
+		
114
+		this.bounds = bounds;
115
+		style.border.update(surface, z + 1, bounds);
116
+		
117
+		if (shape != null)
118
+			shape.close();
119
+		shape = surface.shadowPath(z, style.shape.instance(style.margin.apply(bounds)), DTransform2D.IDENTITY, style.backgroundColor, style.shadow);
120
+		
121
+		layout();
122
+	}
123
+
124
+	@Override
125
+	public void close() {
126
+		for (ListenerHandle<LiveObject.Listener<DSizing>> listener : componentSizeListeners) {
127
+			listener.close();
128
+		}
129
+		for (Element element : components)
130
+			element.component.close();
131
+	}
132
+	
133
+	private int getInnerWidth() {
134
+		return bounds.width - style.margin.getHorizontal() - style.border.getPaddingHorizontal();
135
+	}
136
+	
137
+	private int getInnerHeight() {
138
+		return bounds.height - style.margin.getVertical() - style.border.getPaddingVertical();
139
+	}
140
+	
141
+	private int getPreferredInnerWidth() {
142
+		DSizing myPreferences = sizing.getValue();
143
+		return myPreferences.preferredWidth - style.margin.getHorizontal() - style.border.getPaddingHorizontal();
144
+	}
145
+	
146
+	private int getPreferredInnerHeight() {
147
+		DSizing myPreferences = sizing.getValue();
148
+		return myPreferences.preferredHeight - style.margin.getVertical() - style.border.getPaddingVertical();
149
+	}
150
+	
151
+	private void layout() {
152
+		if (orientation == Orientation.HORIZONTAL) {
153
+			layoutHorizontal();
154
+		} else {
155
+			layoutVertical();
156
+		}
157
+	}
158
+	
159
+	private void layoutHorizontal() {
160
+		if (bounds == null || surface == null)
161
+			return;
162
+		
163
+		DSizing myPreferences = sizing.getValue();
164
+		if (bounds.width < myPreferences.preferredWidth) {
165
+			layoutHorizontalShrinked();
166
+		} else {
167
+			layoutHorizontalGrown();
168
+		}
169
+	}
170
+	
171
+	private void layoutVertical() {
172
+		if (bounds == null || surface == null)
173
+			return;
174
+		
175
+		DSizing myPreferences = sizing.getValue();
176
+		if (bounds.height < myPreferences.preferredHeight) {
177
+			layoutVerticalShrinked();
178
+		} else {
179
+			layoutVerticalGrown();
180
+		}
181
+	}
182
+	
183
+	private void layoutHorizontalShrinked() {
184
+		float availableWidth = getInnerWidth() - (components.length - 1) * style.spacing;
185
+		float preferredInnerWidth = getPreferredInnerWidth() - (components.length - 1) * style.spacing;
186
+		
187
+		if (totalShrink == 0) {
188
+			// now what?
189
+			// shrink proportionally, we have to shrink...
190
+			float scale = availableWidth / preferredInnerWidth;
191
+			int x = bounds.x + style.margin.left + style.border.getPaddingLeft();
192
+			
193
+			for (Element element : components) {
194
+				DSizing preferences = element.component.getSizing().getValue();
195
+				int newX = (int)(x + preferences.preferredWidth * scale + 0.5f);
196
+				layoutHorizontal(element, bounds.x + x, newX - x);
197
+				x = newX + style.spacing;
198
+			}
199
+		} else {
200
+			int delta = getInnerHeight() - getPreferredInnerHeight();
201
+			float deltaScaled = delta / totalShrink;
202
+			int y = bounds.y;
203
+			for (Element element : components) {
204
+				DSizing preferences = element.component.getSizing().getValue();
205
+				float scaledSize = preferences.preferredHeight + deltaScaled * element.shrink;
206
+				float idealUnspacedY = y + scaledSize;
207
+				int newX = (int)(idealUnspacedY + 0.5f);
208
+				layoutHorizontal(element, y, newX - y);
209
+				y = newX + style.spacing;
210
+			}
211
+		}
212
+	}
213
+	
214
+	private void layoutVerticalShrinked() {
215
+		float availableHeight = getInnerHeight() - (components.length - 1) * style.spacing;
216
+		float preferredInnerHeight = getPreferredInnerHeight() - (components.length - 1) * style.spacing;
217
+		
218
+		if (totalShrink == 0) {
219
+			// now what?
220
+			// shrink proportionally, we have to shrink...
221
+			float scale = availableHeight / preferredInnerHeight;
222
+			int y = bounds.y + style.margin.top + style.border.getPaddingTop();
223
+			
224
+			for (int i = 0; i < components.length; i++) {
225
+				Element element = components[i];
226
+				DSizing preferences = element.component.getSizing().getValue();
227
+				int newY = (int)(y + preferences.preferredHeight * scale + 0.5f);
228
+				layoutVertical(element, bounds.y + y, newY - y);
229
+				y = newY + style.spacing;
230
+			}
231
+		} else {
232
+			int delta = getInnerHeight() - getPreferredInnerHeight();
233
+			float deltaScaled = delta / totalShrink;
234
+			int y = bounds.y;
235
+			for (Element element : components) {
236
+				DSizing preferences = element.component.getSizing().getValue();
237
+				float scaledSize = preferences.preferredHeight + deltaScaled * element.shrink;
238
+				float idealUnspacedY = y + scaledSize;
239
+				int newY = (int)(idealUnspacedY + 0.5f);
240
+				layoutVertical(element, y, newY - y);
241
+				y = newY + style.spacing;
242
+			}
243
+		}
244
+	}
245
+	
246
+	private void layoutHorizontalGrown() {
247
+		// resize according to grow values
248
+		int delta = getPreferredInnerWidth() - getInnerWidth();
249
+		if (totalGrow == 0) {
250
+			int x = bounds.x + style.margin.left + style.border.getPaddingLeft() + (int)(delta * alignment.align);
251
+			for (Element element : components) {
252
+				DSizing preferences = element.component.getSizing().getValue();
253
+				int newX = x + preferences.preferredWidth;
254
+				layoutHorizontal(element, x, newX - x);
255
+				x = newX;
256
+			}
257
+		} else {
258
+			float deltaScaled = delta / totalGrow;
259
+			int x = bounds.x + style.margin.left + style.border.getPaddingLeft();
260
+			for (Element element : components) {
261
+				DSizing preferences = element.component.getSizing().getValue();
262
+				float scaledSize = preferences.preferredWidth - deltaScaled * element.grow;
263
+				float idealUnspacedX = x + scaledSize;
264
+				int newX = (int)(idealUnspacedX + 0.5f);
265
+				layoutHorizontal(element, x, newX - x);
266
+				x = newX + style.spacing;
267
+			}
268
+		}
269
+	}
270
+	
271
+	private void layoutVerticalGrown() {
272
+		// resize according to grow values
273
+		int delta = getPreferredInnerHeight() - getInnerHeight();
274
+		if (totalGrow == 0) {
275
+			int y = bounds.y + style.margin.top + style.border.getPaddingTop() + (int)(delta * alignment.align);
276
+			for (Element element : components) {
277
+				DSizing preferences = element.component.getSizing().getValue();
278
+				int newY = y + preferences.preferredHeight;
279
+				layoutVertical(element, y, newY - y);
280
+				y = newY;
281
+			}
282
+		} else {
283
+			float deltaScaled = delta / totalGrow;
284
+			int y = bounds.y + style.margin.top + style.border.getPaddingTop();
285
+			for (Element element : components) {
286
+				DSizing preferences = element.component.getSizing().getValue();
287
+				float scaledSize = preferences.preferredHeight - deltaScaled * element.grow;
288
+				float idealUnspacedY = y + scaledSize;
289
+				int newY = (int)(idealUnspacedY + 0.5f);
290
+				layoutVertical(element, y, newY - y);
291
+				y = newY + style.spacing;
292
+			}
293
+		}
294
+	}
295
+	
296
+	private void layoutHorizontal(Element element, int x, int width) {
297
+		DSizing preferences = element.component.getSizing().getValue();
298
+		int height;
299
+		int y;
300
+		switch (element.alignment) {
301
+			case BOTTOM:
302
+				height = Math.min(preferences.preferredHeight, bounds.height - style.border.getPaddingVertical());
303
+				y = bounds.y + style.border.getPaddingTop();
304
+				break;
305
+			case MIDDLE:
306
+				height = Math.min(preferences.preferredHeight, bounds.height - style.border.getPaddingVertical());
307
+				y = bounds.y + style.border.getPaddingTop() + (bounds.height - style.border.getPaddingVertical() - height) / 2;
308
+				break;
309
+			case TOP:
310
+				height = Math.min(preferences.preferredHeight, bounds.height - style.border.getPaddingVertical());
311
+				y = bounds.y + bounds.height - style.border.getPaddingBottom() - height;
312
+				break;
313
+			case STRETCH:
314
+			default:
315
+				height = bounds.height - style.border.getPaddingVertical();
316
+				y = bounds.y + style.border.getPaddingTop();
317
+				break;
318
+		}
319
+		element.component.setBounds(new DIRectangle(x, y, width, height));
320
+	}
321
+	
322
+	private void layoutVertical(Element element, int y, int height) {
323
+		DSizing preferences = element.component.getSizing().getValue();
324
+		int x;
325
+		int width;
326
+		switch (element.alignment) {
327
+			case LEFT:
328
+				width = Math.min(preferences.preferredWidth, bounds.width - style.border.getPaddingHorizontal() - style.margin.getHorizontal());
329
+				x = bounds.x + style.margin.left + style.border.getPaddingLeft();
330
+				break;
331
+			case CENTER:
332
+				width = Math.min(preferences.preferredWidth, bounds.width - style.border.getPaddingHorizontal());
333
+				x = bounds.x + style.margin.left + style.border.getPaddingLeft() + (bounds.width - style.border.getPaddingHorizontal() - width) / 2;
334
+				break;
335
+			case RIGHT:
336
+				width = Math.min(preferences.preferredWidth, bounds.width - style.border.getPaddingHorizontal());
337
+				x = bounds.x + bounds.width - style.margin.right - style.border.getPaddingRight() - width;
338
+				break;
339
+			case STRETCH:
340
+			default:
341
+				width = bounds.width - style.border.getPaddingHorizontal() - style.margin.getHorizontal();
342
+				x = bounds.x + style.margin.left + style.border.getPaddingLeft();
343
+				break;
344
+		}
345
+		element.component.setBounds(new DIRectangle(x, y, width, height));
346
+	}
347
+	
348
+	private void updateSizing() {
349
+		if (orientation == Orientation.HORIZONTAL) {
350
+			updateSizingHorizontal();
351
+		} else {
352
+			updateSizingVertical();
353
+		}
354
+	}
355
+	
356
+	private void updateSizingHorizontal() {
357
+		int preferredWidth = -style.spacing;
358
+		int preferredHeight = 0;
359
+		int minimumWidth = -style.spacing;
360
+		int minimumHeight = Integer.MAX_VALUE;
361
+		int maximumWidth = -style.spacing;
362
+		int maximumHeight = 0;
363
+		
364
+		for (Element element : components) {
365
+			DSizing preferences = element.component.getSizing().getValue();
366
+			preferredWidth += preferences.preferredWidth + style.spacing;
367
+			preferredHeight = Math.max(preferredHeight, preferences.preferredHeight);
368
+			
369
+			minimumWidth += preferences.minimumWidth + style.spacing;
370
+			minimumHeight = Math.max(minimumHeight, preferences.minimumHeight);
371
+			
372
+			maximumHeight += preferences.maximumWidth + style.spacing;
373
+			maximumWidth = Math.min(maximumHeight, preferences.maximumHeight);
374
+		}
375
+		
376
+		int paddingHorizontal = style.border.getPaddingHorizontal() + style.margin.getHorizontal();
377
+		int paddingVertical = style.border.getPaddingVertical() + style.margin.getVertical();
378
+		DSizing preferences = new DSizing(
379
+				minimumWidth + paddingHorizontal,
380
+				minimumHeight + paddingVertical,
381
+				preferredWidth + paddingHorizontal,
382
+				preferredHeight + paddingVertical,
383
+				maximumWidth + paddingHorizontal,
384
+				maximumHeight + paddingVertical);
385
+		sizing.setValue(preferences);
386
+	}
387
+	
388
+	private void updateSizingVertical() {
389
+		int preferredWidth = 0;
390
+		int preferredHeight = -style.spacing;
391
+		int minimumWidth = 0;
392
+		int minimumHeight = -style.spacing;
393
+		int maximumWidth = Integer.MAX_VALUE;
394
+		int maximumHeight = -style.spacing;
395
+		
396
+		for (Element element : components) {
397
+			DSizing preferences = element.component.getSizing().getValue();
398
+			preferredWidth = Math.max(preferredWidth, preferences.preferredWidth);
399
+			preferredHeight += preferences.preferredHeight + style.spacing;
400
+			
401
+			minimumWidth = Math.max(minimumWidth, preferences.minimumWidth);
402
+			minimumHeight += preferences.minimumHeight + style.spacing;
403
+			
404
+			maximumWidth = Math.min(maximumWidth, preferences.maximumWidth);
405
+			maximumHeight += preferences.maximumHeight + style.spacing;
406
+		}
407
+		
408
+		int paddingHorizontal = style.border.getPaddingHorizontal() + style.margin.getHorizontal();
409
+		int paddingVertical = style.border.getPaddingVertical() + style.margin.getVertical();
410
+		DSizing preferences = new DSizing(
411
+				minimumWidth + paddingHorizontal,
412
+				minimumHeight + paddingVertical,
413
+				preferredWidth + paddingHorizontal,
414
+				preferredHeight + paddingVertical,
415
+				maximumWidth + paddingHorizontal,
416
+				maximumHeight + paddingVertical);
417
+		sizing.setValue(preferences);
418
+	}
419
+	
420
+	public static enum Orientation {
421
+		HORIZONTAL,
422
+		VERTICAL
423
+	}
424
+	
425
+	public static enum Alignment {
426
+		TOP(0),
427
+		LEFT(0),
428
+		MIDDLE(0.5f),
429
+		CENTER(0.5f),
430
+		BOTTOM(1),
431
+		RIGHT(1);
432
+		
433
+		public final float align;
434
+		
435
+		Alignment(float align) {
436
+			this.align = align;
437
+		}
438
+	}
439
+	
440
+	public static enum ElementAlignment {
441
+		LEFT,
442
+		CENTER,
443
+		RIGHT,
444
+		TOP,
445
+		MIDDLE,
446
+		BOTTOM,
447
+		STRETCH
448
+	}
449
+	
450
+	public static class Element {
451
+		public final DComponent component;
452
+		public final float grow;
453
+		public final float shrink;
454
+		public final ElementAlignment alignment;
455
+		
456
+		public Element(DComponent component, float grow, float shrink, ElementAlignment alignment) {
457
+			this.component = component;
458
+			this.grow = grow;
459
+			this.shrink = shrink;
460
+			this.alignment = alignment;
461
+		}
462
+	}
463
+}

+ 24
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/layout/DLinearLayoutStyle.java View File

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.layout;
7
+
8
+import org.openzen.drawablegui.style.DBaseStyle;
9
+import org.openzen.drawablegui.style.DDpDimension;
10
+import org.openzen.drawablegui.style.DStyleDefinition;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class DLinearLayoutStyle extends DBaseStyle {
17
+	public final int spacing;
18
+	
19
+	public DLinearLayoutStyle(DStyleDefinition style) {
20
+		super(style);
21
+		
22
+		spacing = style.getDimension("spacing", new DDpDimension(8));
23
+	}
24
+}

DrawableGui/src/main/java/org/openzen/drawablegui/DSideLayout.java → DrawableGui/src/main/java/org/openzen/drawablegui/layout/DSideLayout.java View File

3
  * To change this template file, choose Tools | Templates
3
  * To change this template file, choose Tools | Templates
4
  * and open the template in the editor.
4
  * and open the template in the editor.
5
  */
5
  */
6
-package org.openzen.drawablegui;
6
+package org.openzen.drawablegui.layout;
7
 
7
 
8
 import java.io.Closeable;
8
 import java.io.Closeable;
9
 import java.util.ArrayList;
9
 import java.util.ArrayList;
10
 import java.util.List;
10
 import java.util.List;
11
 import java.util.function.Consumer;
11
 import java.util.function.Consumer;
12
 import java.util.function.Predicate;
12
 import java.util.function.Predicate;
13
+import org.openzen.drawablegui.BaseComponentGroup;
14
+import org.openzen.drawablegui.DComponent;
15
+import org.openzen.drawablegui.DIRectangle;
16
+import org.openzen.drawablegui.DSizing;
17
+import org.openzen.drawablegui.draw.DDrawSurface;
18
+import org.openzen.drawablegui.draw.DDrawnRectangle;
13
 import org.openzen.drawablegui.listeners.ListenerHandle;
19
 import org.openzen.drawablegui.listeners.ListenerHandle;
14
 import org.openzen.drawablegui.live.LiveObject;
20
 import org.openzen.drawablegui.live.LiveObject;
15
 import org.openzen.drawablegui.live.MutableLiveObject;
21
 import org.openzen.drawablegui.live.MutableLiveObject;
16
-import org.openzen.drawablegui.live.SimpleLiveObject;
17
 import org.openzen.drawablegui.style.DStyleClass;
22
 import org.openzen.drawablegui.style.DStyleClass;
18
 import org.openzen.drawablegui.style.DStylePath;
23
 import org.openzen.drawablegui.style.DStylePath;
19
 
24
 
29
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
34
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
30
 	
35
 	
31
 	private DStylePath path;
36
 	private DStylePath path;
32
-	private DUIContext context;
37
+	private DDrawSurface surface;
38
+	private int z;
39
+	private DSideLayoutStyle style;
33
 	private DIRectangle bounds;
40
 	private DIRectangle bounds;
34
 	
41
 	
42
+	private DDrawnRectangle background;
43
+	
35
 	public DSideLayout(DStyleClass styleClass, DComponent main) {
44
 	public DSideLayout(DStyleClass styleClass, DComponent main) {
36
 		this.styleClass = styleClass;
45
 		this.styleClass = styleClass;
37
 		this.main = main;
46
 		this.main = main;
38
 	}
47
 	}
39
 	
48
 	
40
 	public void add(Side side, DComponent component) {
49
 	public void add(Side side, DComponent component) {
41
-		if (context != null)
42
-			component.setContext(path, context);
50
+		if (surface != null)
51
+			component.mount(path, z + 1, surface);
43
 		
52
 		
44
 		sides.add(new SideComponent(side, component));
53
 		sides.add(new SideComponent(side, component));
45
 	}
54
 	}
50
 		
59
 		
51
 		this.main = component;
60
 		this.main = component;
52
 		
61
 		
53
-		if (context != null && bounds != null) {
54
-			main.setContext(path, context);
62
+		if (surface != null && bounds != null) {
63
+			main.mount(path, z + 1, surface);
55
 			setBounds(bounds);
64
 			setBounds(bounds);
56
-			context.repaint(bounds);
57
 		}
65
 		}
58
 	}
66
 	}
59
 
67
 
60
 	@Override
68
 	@Override
61
-	public void setContext(DStylePath parent, DUIContext context) {
62
-		this.context = context;
69
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
70
+		this.surface = surface;
71
+		this.z = z;
63
 		this.path = parent.getChild("sidelayout", styleClass);
72
 		this.path = parent.getChild("sidelayout", styleClass);
73
+		style = new DSideLayoutStyle(surface.getStylesheet(path));
64
 		
74
 		
65
-		main.setContext(path, context);
75
+		main.mount(path, z + 1, surface);
66
 		for (SideComponent side : sides)
76
 		for (SideComponent side : sides)
67
-			side.component.setContext(path, context);
77
+			side.component.mount(path, z + 1, surface);
78
+		
79
+		if (background != null)
80
+			background.close();
81
+		background = surface.fillRect(z, DIRectangle.EMPTY, style.backgroundColor);
82
+	}
83
+	
84
+	@Override
85
+	public void unmount() {
86
+		main.unmount();
87
+		for (SideComponent side : sides)
88
+			side.component.unmount();
89
+		
90
+		background.close();
91
+		background = null;
68
 	}
92
 	}
69
 	
93
 	
70
 	@Override
94
 	@Override
92
 	public void setBounds(DIRectangle bounds) {
116
 	public void setBounds(DIRectangle bounds) {
93
 		this.bounds = bounds;
117
 		this.bounds = bounds;
94
 		
118
 		
119
+		background.setRectangle(bounds);
120
+		
95
 		int left = bounds.x;
121
 		int left = bounds.x;
96
 		int right = bounds.x + bounds.width;
122
 		int right = bounds.x + bounds.width;
97
 		int top = bounds.y;
123
 		int top = bounds.y;
166
 		
192
 		
167
 		main.setBounds(new DIRectangle(left, top, right - left, bottom - top));
193
 		main.setBounds(new DIRectangle(left, top, right - left, bottom - top));
168
 	}
194
 	}
169
-
170
-	@Override
171
-	public void paint(DCanvas canvas) {
172
-		main.paint(canvas);
173
-		
174
-		for (SideComponent component : sides)
175
-			component.component.paint(canvas);
176
-	}
177
 	
195
 	
178
 	private void recalculateSize() {
196
 	private void recalculateSize() {
179
 		DSizing mainPreferences = main.getSizing().getValue();
197
 		DSizing mainPreferences = main.getSizing().getValue();
240
 		main.close();
258
 		main.close();
241
 		for (SideComponent side : sides)
259
 		for (SideComponent side : sides)
242
 			side.close();
260
 			side.close();
261
+		
262
+		background.close();
243
 	}
263
 	}
244
 	
264
 	
245
 	public class SideComponent implements Closeable, LiveObject.Listener<DSizing> {
265
 	public class SideComponent implements Closeable, LiveObject.Listener<DSizing> {

+ 20
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/layout/DSideLayoutStyle.java View File

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.layout;
7
+
8
+import org.openzen.drawablegui.style.DStyleDefinition;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class DSideLayoutStyle {
15
+	public final int backgroundColor;
16
+	
17
+	public DSideLayoutStyle(DStyleDefinition style) {
18
+		backgroundColor = style.getColor("backgroundColor", 0);
19
+	}
20
+}

+ 30
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/InverseLiveBool.java View File

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 class InverseLiveBool implements LiveBool {
15
+	private final LiveBool source;
16
+	
17
+	public InverseLiveBool(LiveBool source) {
18
+		this.source = source;
19
+	}
20
+
21
+	@Override
22
+	public boolean getValue() {
23
+		return !source.getValue();
24
+	}
25
+
26
+	@Override
27
+	public ListenerHandle<Listener> addListener(Listener listener) {
28
+		return source.addListener((oldValue, newValue) -> listener.onChanged(!oldValue, !newValue));
29
+	}
30
+}

+ 2
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveConcatList.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.live;
6
 package org.openzen.drawablegui.live;
7
 
7
 
8
-import java.io.Closeable;
9
 import java.util.Iterator;
8
 import java.util.Iterator;
9
+import org.openzen.drawablegui.Destructible;
10
 import org.openzen.drawablegui.listeners.ListenerHandle;
10
 import org.openzen.drawablegui.listeners.ListenerHandle;
11
 import org.openzen.drawablegui.listeners.ListenerList;
11
 import org.openzen.drawablegui.listeners.ListenerList;
12
 
12
 
14
  *
14
  *
15
  * @author Hoofdgebruiker
15
  * @author Hoofdgebruiker
16
  */
16
  */
17
-public class LiveConcatList<T> implements Closeable, LiveList<T> {
17
+public class LiveConcatList<T> implements Destructible, LiveList<T> {
18
 	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
18
 	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
19
 	private final LiveList<T> a;
19
 	private final LiveList<T> a;
20
 	private final LiveList<T> b;
20
 	private final LiveList<T> b;

+ 5
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveMappedList.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.live;
6
 package org.openzen.drawablegui.live;
7
 
7
 
8
-import java.io.Closeable;
9
 import java.util.ArrayList;
8
 import java.util.ArrayList;
10
 import java.util.Iterator;
9
 import java.util.Iterator;
11
 import java.util.List;
10
 import java.util.List;
12
 import java.util.function.Function;
11
 import java.util.function.Function;
12
+import org.openzen.drawablegui.Destructible;
13
 import org.openzen.drawablegui.listeners.ListenerHandle;
13
 import org.openzen.drawablegui.listeners.ListenerHandle;
14
 import org.openzen.drawablegui.listeners.ListenerList;
14
 import org.openzen.drawablegui.listeners.ListenerList;
15
 
15
 
17
  *
17
  *
18
  * @author Hoofdgebruiker
18
  * @author Hoofdgebruiker
19
  */
19
  */
20
-public class LiveMappedList<T, U> implements Closeable, LiveList<U> {
20
+public class LiveMappedList<T, U> implements Destructible, LiveList<U> {
21
 	private final ListenerList<Listener<U>> listeners = new ListenerList<>();
21
 	private final ListenerList<Listener<U>> listeners = new ListenerList<>();
22
 	private final Function<T, U> projection;
22
 	private final Function<T, U> projection;
23
 	private final List<U> mapped;
23
 	private final List<U> mapped;
80
 		@Override
80
 		@Override
81
 		public void onRemoved(int index, T oldValue) {
81
 		public void onRemoved(int index, T oldValue) {
82
 			U oldMappedValue = mapped.remove(index);
82
 			U oldMappedValue = mapped.remove(index);
83
+			if (oldMappedValue instanceof AutoCloseable) {
84
+				try { ((AutoCloseable) oldMappedValue).close(); } catch (Exception ex) {}
85
+			}
83
 			listeners.accept(listener -> listener.onRemoved(index, oldMappedValue));
86
 			listeners.accept(listener -> listener.onRemoved(index, oldMappedValue));
84
 		}
87
 		}
85
 	}
88
 	}

+ 2
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePredicateBool.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.live;
6
 package org.openzen.drawablegui.live;
7
 
7
 
8
-import java.io.Closeable;
9
 import java.util.function.Predicate;
8
 import java.util.function.Predicate;
9
+import org.openzen.drawablegui.Destructible;
10
 import org.openzen.drawablegui.listeners.ListenerHandle;
10
 import org.openzen.drawablegui.listeners.ListenerHandle;
11
 import org.openzen.drawablegui.listeners.ListenerList;
11
 import org.openzen.drawablegui.listeners.ListenerList;
12
 
12
 
14
  *
14
  *
15
  * @author Hoofdgebruiker
15
  * @author Hoofdgebruiker
16
  */
16
  */
17
-public class LivePredicateBool<T> implements LiveBool, Closeable, LiveObject.Listener<T> {
17
+public class LivePredicateBool<T> implements LiveBool, Destructible, LiveObject.Listener<T> {
18
 	private final ListenerList<LiveBool.Listener> listeners = new ListenerList<>();
18
 	private final ListenerList<LiveBool.Listener> listeners = new ListenerList<>();
19
 	private final LiveObject<T> source;
19
 	private final LiveObject<T> source;
20
 	private final Predicate<T> predicate;
20
 	private final Predicate<T> predicate;

+ 8
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveInt.java View File

14
  */
14
  */
15
 public class SimpleLiveInt implements LiveInt {
15
 public class SimpleLiveInt implements LiveInt {
16
 	private final ListenerList<Listener> listeners = new ListenerList<>();
16
 	private final ListenerList<Listener> listeners = new ListenerList<>();
17
-	private int value = 0;
17
+	private int value;
18
 
18
 
19
+	public SimpleLiveInt(int value) {
20
+		this.value = value;
21
+	}
22
+	
19
 	@Override
23
 	@Override
20
 	public int getValue() {
24
 	public int getValue() {
21
 		return value;
25
 		return value;
23
 
27
 
24
 	@Override
28
 	@Override
25
 	public void setValue(int value) {
29
 	public void setValue(int value) {
30
+		if (value == this.value)
31
+			return;
32
+		
26
 		int oldValue = this.value;
33
 		int oldValue = this.value;
27
 		this.value = value;
34
 		this.value = value;
28
 		listeners.accept(listener -> listener.onChanged(oldValue, value));
35
 		listeners.accept(listener -> listener.onChanged(oldValue, value));

+ 3
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveObject.java View File

27
 	
27
 	
28
 	@Override
28
 	@Override
29
 	public void setValue(T value) {
29
 	public void setValue(T value) {
30
+		if (value == this.value)
31
+			return;
32
+		
30
 		T oldValue = this.value;
33
 		T oldValue = this.value;
31
 		this.value = value;
34
 		this.value = value;
32
 		listeners.accept(listener -> listener.onUpdated(oldValue, value));
35
 		listeners.accept(listener -> listener.onUpdated(oldValue, value));

+ 3
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveString.java View File

33
 
33
 
34
 	@Override
34
 	@Override
35
 	public void setValue(String value) {
35
 	public void setValue(String value) {
36
+		if (value.equals(this.value))
37
+			return;
38
+		
36
 		String oldValue = this.value;
39
 		String oldValue = this.value;
37
 		this.value = value;
40
 		this.value = value;
38
 		listeners.accept(listener -> listener.onChanged(oldValue, value));
41
 		listeners.accept(listener -> listener.onChanged(oldValue, value));

+ 49
- 24
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.scroll;
6
 package org.openzen.drawablegui.scroll;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DComponent;
8
 import org.openzen.drawablegui.DComponent;
10
 import org.openzen.drawablegui.DSizing;
9
 import org.openzen.drawablegui.DSizing;
11
 import org.openzen.drawablegui.DMouseEvent;
10
 import org.openzen.drawablegui.DMouseEvent;
12
 import org.openzen.drawablegui.DIRectangle;
11
 import org.openzen.drawablegui.DIRectangle;
12
+import org.openzen.drawablegui.DPath;
13
+import org.openzen.drawablegui.DTransform2D;
13
 import org.openzen.drawablegui.listeners.ListenerHandle;
14
 import org.openzen.drawablegui.listeners.ListenerHandle;
14
 import org.openzen.drawablegui.live.LiveInt;
15
 import org.openzen.drawablegui.live.LiveInt;
15
 import org.openzen.drawablegui.live.LiveObject;
16
 import org.openzen.drawablegui.live.LiveObject;
16
-import org.openzen.drawablegui.DUIContext;
17
+import org.openzen.drawablegui.draw.DDrawSurface;
18
+import org.openzen.drawablegui.draw.DDrawnRectangle;
19
+import org.openzen.drawablegui.draw.DDrawnShape;
17
 import org.openzen.drawablegui.live.MutableLiveObject;
20
 import org.openzen.drawablegui.live.MutableLiveObject;
18
 import org.openzen.drawablegui.style.DStyleClass;
21
 import org.openzen.drawablegui.style.DStyleClass;
19
 import org.openzen.drawablegui.style.DStylePath;
22
 import org.openzen.drawablegui.style.DStylePath;
32
 	private final ListenerHandle<LiveInt.Listener> targetHeightListener;
35
 	private final ListenerHandle<LiveInt.Listener> targetHeightListener;
33
 	private final ListenerHandle<LiveInt.Listener> offsetListener;
36
 	private final ListenerHandle<LiveInt.Listener> offsetListener;
34
 	
37
 	
35
-	private DUIContext context;
38
+	private DDrawSurface surface;
36
 	private DScrollBarStyle style;
39
 	private DScrollBarStyle style;
40
+	private int z;
37
 	private DIRectangle bounds;
41
 	private DIRectangle bounds;
38
 	
42
 	
39
 	private int fromY = 0;
43
 	private int fromY = 0;
43
 	private int dragStartOffset;
47
 	private int dragStartOffset;
44
 	private int dragStartY;
48
 	private int dragStartY;
45
 	
49
 	
50
+	private DDrawnRectangle background;
51
+	private DDrawnShape bar;
52
+	
46
 	public DScrollBar(DStyleClass styleClass, LiveInt targetHeight, LiveInt offset) {
53
 	public DScrollBar(DStyleClass styleClass, LiveInt targetHeight, LiveInt offset) {
47
 		this.styleClass = styleClass;
54
 		this.styleClass = styleClass;
48
 		this.targetHeight = targetHeight;
55
 		this.targetHeight = targetHeight;
53
 	}
60
 	}
54
 
61
 
55
 	@Override
62
 	@Override
56
-	public void setContext(DStylePath parent, DUIContext context) {
57
-		this.context = context;
58
-		this.style = new DScrollBarStyle(context.getStylesheets().get(context, parent.getChild("scrollbar", styleClass)));
63
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
64
+		this.surface = surface;
65
+		this.z = z;
66
+		this.style = new DScrollBarStyle(surface.getStylesheet(parent.getChild("scrollbar", styleClass)));
59
 		sizing.setValue(new DSizing(style.width, 0));
67
 		sizing.setValue(new DSizing(style.width, 0));
68
+		
69
+		background = surface.fillRect(z, DIRectangle.EMPTY, style.scrollBarBackgroundColor);
70
+	}
71
+	
72
+	@Override
73
+	public void unmount() {
74
+		background.close();
75
+		background = null;
76
+		
77
+		if (bar != null) {
78
+			bar.close();
79
+			bar = null;
80
+		}
60
 	}
81
 	}
61
 
82
 
62
 	@Override
83
 	@Override
77
 	@Override
98
 	@Override
78
 	public void setBounds(DIRectangle bounds) {
99
 	public void setBounds(DIRectangle bounds) {
79
 		this.bounds = bounds;
100
 		this.bounds = bounds;
101
+		background.setRectangle(bounds);
80
 		recalculate();
102
 		recalculate();
81
 	}
103
 	}
82
-
83
-	@Override
84
-	public void paint(DCanvas canvas) {
85
-		if (targetHeight.getValue() <= this.bounds.height)
86
-			return; // no scrollbar
87
-		
88
-		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.scrollBarBackgroundColor);
89
-		
90
-		int color = style.scrollBarNormalColor;
91
-		if (hovering)
92
-			color = style.scrollBarHoverColor;
93
-		if (dragging)
94
-			color = style.scrollBarPressColor;
95
-		
96
-		canvas.fillRectangle(bounds.x, fromY, this.bounds.width, toY - fromY, color);
97
-	}
98
 	
104
 	
99
 	@Override
105
 	@Override
100
 	public void onMouseEnter(DMouseEvent e) {
106
 	public void onMouseEnter(DMouseEvent e) {
139
 	public void close() {
145
 	public void close() {
140
 		targetHeightListener.close();
146
 		targetHeightListener.close();
141
 		offsetListener.close();
147
 		offsetListener.close();
148
+		
149
+		unmount();
150
+	}
151
+	
152
+	private void updateBarColor() {
153
+		int color = style.scrollBarNormalColor;
154
+		if (hovering)
155
+			color = style.scrollBarHoverColor;
156
+		if (dragging)
157
+			color = style.scrollBarPressColor;		
158
+		if (targetHeight.getValue() <= this.bounds.height)
159
+			color = 0;
160
+		
161
+		bar.setColor(color);
142
 	}
162
 	}
143
 	
163
 	
144
 	private void checkHover(DMouseEvent e) {
164
 	private void checkHover(DMouseEvent e) {
150
 			return;
170
 			return;
151
 		
171
 		
152
 		this.hovering = hovering;
172
 		this.hovering = hovering;
153
-		context.repaint(bounds.x, fromY, bounds.width, toY - fromY);
173
+		updateBarColor();
154
 	}
174
 	}
155
 	
175
 	
156
 	private void setDragging(boolean dragging) {
176
 	private void setDragging(boolean dragging) {
158
 			return;
178
 			return;
159
 		
179
 		
160
 		this.dragging = dragging;
180
 		this.dragging = dragging;
161
-		context.repaint(bounds.x, fromY, bounds.width, toY - fromY);
181
+		updateBarColor();
162
 	}
182
 	}
163
 	
183
 	
164
 	private void recalculate() {
184
 	private void recalculate() {
167
 		
187
 		
168
 		fromY = bounds.y + this.bounds.height * offset.getValue() / targetHeight.getValue();
188
 		fromY = bounds.y + this.bounds.height * offset.getValue() / targetHeight.getValue();
169
 		toY = bounds.y + this.bounds.height * (offset.getValue() + this.bounds.height) / targetHeight.getValue();
189
 		toY = bounds.y + this.bounds.height * (offset.getValue() + this.bounds.height) / targetHeight.getValue();
190
+		
191
+		if (bar != null)
192
+			bar.close();
193
+		bar = surface.fillPath(z + 1, DPath.rectangle(bounds.x, fromY, bounds.width, toY - fromY), DTransform2D.IDENTITY, style.scrollBarNormalColor);
194
+		updateBarColor();
170
 	}
195
 	}
171
 	
196
 	
172
 	private class ScrollListener implements LiveInt.Listener {
197
 	private class ScrollListener implements LiveInt.Listener {

+ 56
- 127
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java View File

6
 package org.openzen.drawablegui.scroll;
6
 package org.openzen.drawablegui.scroll;
7
 
7
 
8
 import org.openzen.drawablegui.DAnchor;
8
 import org.openzen.drawablegui.DAnchor;
9
-import org.openzen.drawablegui.DCanvas;
10
 import org.openzen.drawablegui.DClipboard;
9
 import org.openzen.drawablegui.DClipboard;
11
 import org.openzen.drawablegui.DComponent;
10
 import org.openzen.drawablegui.DComponent;
12
 import org.openzen.drawablegui.DSizing;
11
 import org.openzen.drawablegui.DSizing;
15
 import org.openzen.drawablegui.DIRectangle;
14
 import org.openzen.drawablegui.DIRectangle;
16
 import org.openzen.drawablegui.DMouseEvent;
15
 import org.openzen.drawablegui.DMouseEvent;
17
 import org.openzen.drawablegui.DTimerHandle;
16
 import org.openzen.drawablegui.DTimerHandle;
18
-import org.openzen.drawablegui.DTooltip;
19
-import org.openzen.drawablegui.DTooltipHandle;
17
+import org.openzen.drawablegui.DTransform2D;
20
 import org.openzen.drawablegui.listeners.ListenerHandle;
18
 import org.openzen.drawablegui.listeners.ListenerHandle;
21
 import org.openzen.drawablegui.live.LiveInt;
19
 import org.openzen.drawablegui.live.LiveInt;
22
 import org.openzen.drawablegui.live.LiveObject;
20
 import org.openzen.drawablegui.live.LiveObject;
23
 import org.openzen.drawablegui.live.SimpleLiveInt;
21
 import org.openzen.drawablegui.live.SimpleLiveInt;
24
 import org.openzen.drawablegui.DUIContext;
22
 import org.openzen.drawablegui.DUIContext;
25
 import org.openzen.drawablegui.DUIWindow;
23
 import org.openzen.drawablegui.DUIWindow;
24
+import org.openzen.drawablegui.draw.DDrawSurface;
25
+import org.openzen.drawablegui.draw.DDrawnShape;
26
+import org.openzen.drawablegui.draw.DSubSurface;
26
 import org.openzen.drawablegui.style.DStyleClass;
27
 import org.openzen.drawablegui.style.DStyleClass;
27
 import org.openzen.drawablegui.style.DStylePath;
28
 import org.openzen.drawablegui.style.DStylePath;
28
 import org.openzen.drawablegui.style.DStyleSheets;
29
 import org.openzen.drawablegui.style.DStyleSheets;
35
 	private final DStyleClass styleClass;
36
 	private final DStyleClass styleClass;
36
 	private final DComponent contents;
37
 	private final DComponent contents;
37
 	private final DScrollBar scrollBar;
38
 	private final DScrollBar scrollBar;
38
-	private DUIContext context;
39
+	private DDrawSurface surface;
39
 	private DIRectangle bounds;
40
 	private DIRectangle bounds;
40
 	
41
 	
41
 	private DScrollPaneStyle style;
42
 	private DScrollPaneStyle style;
43
+	private int z;
44
+	private DDrawnShape shape;
42
 	private final LiveInt contentsHeight;
45
 	private final LiveInt contentsHeight;
43
 	private final LiveInt offsetX;
46
 	private final LiveInt offsetX;
44
 	private final LiveInt offsetY;
47
 	private final LiveInt offsetY;
45
 	
48
 	
49
+	private final LiveObject<DSizing> sizing;
50
+	
46
 	private final ListenerHandle<LiveInt.Listener> contentsHeightListener;
51
 	private final ListenerHandle<LiveInt.Listener> contentsHeightListener;
47
 	private final ListenerHandle<LiveInt.Listener> offsetXListener;
52
 	private final ListenerHandle<LiveInt.Listener> offsetXListener;
48
 	private final ListenerHandle<LiveInt.Listener> offsetYListener;
53
 	private final ListenerHandle<LiveInt.Listener> offsetYListener;
54
+	private final ListenerHandle<LiveObject.Listener<DSizing>> contentsSizingListener;
49
 	
55
 	
50
 	private DComponent hovering = null;
56
 	private DComponent hovering = null;
51
 	
57
 	
52
-	public DScrollPane(DStyleClass styleClass, DComponent contents) {
58
+	private DSubSurface subSurface;
59
+	
60
+	public DScrollPane(DStyleClass styleClass, DComponent contents, LiveObject<DSizing> sizing) {
61
+		this.sizing = sizing;
53
 		this.styleClass = styleClass;
62
 		this.styleClass = styleClass;
54
 		this.contents = contents;
63
 		this.contents = contents;
55
 		
64
 		
56
-		contentsHeight = new SimpleLiveInt();
57
-		offsetX = new SimpleLiveInt();
58
-		offsetY = new SimpleLiveInt();
65
+		contentsHeight = new SimpleLiveInt(0);
66
+		offsetX = new SimpleLiveInt(0);
67
+		offsetY = new SimpleLiveInt(0);
59
 		
68
 		
60
 		scrollBar = new DScrollBar(DStyleClass.EMPTY, contentsHeight, offsetY);
69
 		scrollBar = new DScrollBar(DStyleClass.EMPTY, contentsHeight, offsetY);
61
 		
70
 		
63
 		offsetXListener = offsetX.addListener(new ScrollListener());
72
 		offsetXListener = offsetX.addListener(new ScrollListener());
64
 		offsetYListener = offsetY.addListener(new ScrollListener());
73
 		offsetYListener = offsetY.addListener(new ScrollListener());
65
 		
74
 		
66
-		contents.getSizing().addListener((oldPreferences, newPreferences) -> {
75
+		contentsSizingListener = contents.getSizing().addListener((oldPreferences, newPreferences) -> {
67
 			if (bounds == null)
76
 			if (bounds == null)
68
 				return;
77
 				return;
69
 			
78
 			
83
 	}
92
 	}
84
 
93
 
85
 	@Override
94
 	@Override
86
-	public void setContext(DStylePath parent, DUIContext context) {
87
-		this.context = context;
95
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
96
+		this.surface = surface;
97
+		this.z = z;
88
 		
98
 		
89
 		DStylePath path = parent.getChild("scrollpane", styleClass);
99
 		DStylePath path = parent.getChild("scrollpane", styleClass);
90
-		contents.setContext(path, new TranslatedContext());
91
-		scrollBar.setContext(path, context);
92
-		style = new DScrollPaneStyle(context.getStylesheets().get(context, path));
100
+		subSurface = surface.createSubSurface(z + 1);
101
+		contents.mount(path, 1, subSurface);
102
+		scrollBar.mount(path, z + 2, surface);
103
+		style = new DScrollPaneStyle(surface.getStylesheet(path));
104
+	}
105
+	
106
+	@Override
107
+	public void unmount() {
108
+		subSurface.close();
93
 		
109
 		
94
-		if (bounds != null)
95
-			setBounds(bounds);
110
+		contents.unmount();
111
+		scrollBar.unmount();
96
 	}
112
 	}
97
 
113
 
98
 	@Override
114
 	@Override
99
 	public LiveObject<DSizing> getSizing() {
115
 	public LiveObject<DSizing> getSizing() {
100
-		return contents.getSizing(); // TODO: derived preferences
116
+		return sizing;
101
 	}
117
 	}
102
 
118
 
103
 	@Override
119
 	@Override
114
 	public void setBounds(DIRectangle bounds) {
130
 	public void setBounds(DIRectangle bounds) {
115
 		this.bounds = bounds;
131
 		this.bounds = bounds;
116
 		
132
 		
117
-		if (this.context == null)
118
-			return;
133
+		if (shape != null)
134
+			shape.close();
135
+		shape = surface.shadowPath(z, style.shape.instance(style.margin.apply(bounds)), DTransform2D.IDENTITY, style.backgroundColor, style.shadow);
136
+		style.border.update(surface, z + 1, style.margin.apply(bounds));
119
 		
137
 		
120
-		int height = Math.max(bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom(),
138
+		int height = Math.max(
139
+				bounds.height - style.border.getPaddingHorizontal(),
121
 				contents.getSizing().getValue().preferredHeight);
140
 				contents.getSizing().getValue().preferredHeight);
122
 		int scrollBarWidth = scrollBar.getSizing().getValue().preferredWidth;
141
 		int scrollBarWidth = scrollBar.getSizing().getValue().preferredWidth;
123
 		scrollBar.setBounds(new DIRectangle(
142
 		scrollBar.setBounds(new DIRectangle(
124
-				bounds.x + bounds.width - scrollBarWidth - style.border.getPaddingRight(),
125
-				bounds.y + style.border.getPaddingTop(),
143
+				bounds.x + bounds.width - scrollBarWidth - style.border.getPaddingRight() - style.margin.right,
144
+				bounds.y + style.border.getPaddingTop() + style.margin.top,
126
 				scrollBarWidth,
145
 				scrollBarWidth,
127
-				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom()));
146
+				bounds.height - style.border.getPaddingVertical() - style.margin.getVertical()));
128
 		contents.setBounds(new DIRectangle(0, 0, bounds.width - scrollBar.getBounds().width, height));
147
 		contents.setBounds(new DIRectangle(0, 0, bounds.width - scrollBar.getBounds().width, height));
129
 		contentsHeight.setValue(height);
148
 		contentsHeight.setValue(height);
130
-	}
131
-
132
-	@Override
133
-	public void paint(DCanvas canvas) {
134
-		if (bounds == null)
135
-			return;
136
 		
149
 		
137
-		style.border.paint(canvas, bounds);
138
-		scrollBar.paint(canvas);
139
-		
140
-		canvas.pushBounds(new DIRectangle(
141
-				bounds.x + style.border.getPaddingLeft(),
142
-				bounds.y + style.border.getPaddingTop(),
143
-				bounds.width - style.border.getPaddingLeft() - style.border.getPaddingTop() - scrollBar.getBounds().width,
144
-				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom()));
145
-		canvas.pushOffset(bounds.x - offsetX.getValue(), bounds.y - offsetY.getValue());
146
-		contents.paint(canvas);
147
-		canvas.popOffset();
148
-		canvas.popBounds();
150
+		subSurface.setOffset(bounds.x - offsetX.getValue(), bounds.y - offsetY.getValue());
151
+		subSurface.setClip(new DIRectangle(
152
+				bounds.x + style.margin.left + style.border.getPaddingLeft(),
153
+				bounds.y + style.margin.top + style.border.getPaddingTop(),
154
+				bounds.width - style.margin.getHorizontal() - style.border.getPaddingHorizontal(),
155
+				bounds.height - style.margin.getVertical() - style.border.getPaddingVertical()));
149
 	}
156
 	}
150
 	
157
 	
151
 	@Override
158
 	@Override
213
 	@Override
220
 	@Override
214
 	public void close() {
221
 	public void close() {
215
 		contents.close();
222
 		contents.close();
223
+		unmount();
224
+		
225
+		contentsSizingListener.close();
226
+		contentsHeightListener.close();
227
+		offsetXListener.close();
228
+		offsetYListener.close();
216
 	}
229
 	}
217
 	
230
 	
218
 	private DMouseEvent forward(DComponent target, DMouseEvent e) {
231
 	private DMouseEvent forward(DComponent target, DMouseEvent e) {
256
 		return y - bounds.y + offsetY.getValue();
269
 		return y - bounds.y + offsetY.getValue();
257
 	}
270
 	}
258
 	
271
 	
259
-	private class TranslatedContext implements DUIContext {
260
-		
261
-		@Override
262
-		public DStyleSheets getStylesheets(){
263
-			return context.getStylesheets();
264
-		}
265
-
266
-		@Override
267
-		public float getScale() {
268
-			return context.getScale();
269
-		}
270
-		
271
-		@Override
272
-		public float getTextScale() {
273
-			return context.getTextScale();
274
-		}
275
-
276
-		@Override
277
-		public void repaint(int x, int y, int width, int height) {
278
-			int left = toGlobalX(x);
279
-			int top = toGlobalY(y);
280
-			int right = left + width;
281
-			int bottom = top + height;
282
-			
283
-			left = Math.max(bounds.x, left);
284
-			top = Math.max(bounds.y, top);
285
-			right = Math.min(bounds.x + bounds.width, right);
286
-			bottom = Math.min(bounds.y + bounds.height, bottom);
287
-			
288
-			if (left >= right || top >= bottom)
289
-				return;
290
-			
291
-			context.repaint(left, top, right - left, bottom - top);
292
-		}
293
-
294
-		@Override
295
-		public void setCursor(Cursor cursor) {
296
-			context.setCursor(cursor);
297
-		}
298
-
299
-		@Override
300
-		public DFontMetrics getFontMetrics(DFont font) {
301
-			return context.getFontMetrics(font);
302
-		}
303
-
304
-		@Override
305
-		public void scrollInView(int x, int y, int width, int height) {
306
-			if (y < offsetY.getValue())
307
-				offsetY.setValue(y);
308
-			if (y + height > offsetY.getValue() + bounds.height)
309
-				offsetY.setValue(y + height - bounds.height);
310
-		}
311
-
312
-		@Override
313
-		public DTimerHandle setTimer(int millis, Runnable target) {
314
-			return context.setTimer(millis, target);
315
-		}
316
-
317
-		@Override
318
-		public DClipboard getClipboard() {
319
-			return context.getClipboard();
320
-		}
321
-
322
-		@Override
323
-		public DUIWindow getWindow() {
324
-			return context.getWindow();
325
-		}
326
-
327
-		@Override
328
-		public DUIWindow openDialog(int x, int y, DAnchor anchor, String title, DComponent root) {
329
-			return context.openDialog(toGlobalX(x), toGlobalY(y), anchor, title, root);
330
-		}
331
-
332
-		@Override
333
-		public DUIWindow openView(int x, int y, DAnchor anchor, DComponent root) {
334
-			return context.openView(toGlobalX(x), toGlobalY(y), anchor, root);
335
-		}
336
-		
337
-		@Override
338
-		public DTooltipHandle openTooltip(int x, int y, DTooltip tooltip) {
339
-			return context.openTooltip(toGlobalX(x), toGlobalY(y), tooltip);
340
-		}
341
-	}
342
-	
343
 	private class ScrollListener implements LiveInt.Listener {
272
 	private class ScrollListener implements LiveInt.Listener {
344
 
273
 
345
 		@Override
274
 		@Override
352
 			
281
 			
353
 			if (value != offsetY.getValue())
282
 			if (value != offsetY.getValue())
354
 				offsetY.setValue(value);
283
 				offsetY.setValue(value);
355
-			if (context != null && bounds != null)
356
-				context.repaint(bounds);
284
+			
285
+			subSurface.setOffset(bounds.x - offsetX.getValue(), bounds.y - offsetY.getValue());
357
 		}
286
 		}
358
 	}
287
 	}
359
 }
288
 }

+ 3
- 6
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPaneStyle.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.scroll;
6
 package org.openzen.drawablegui.scroll;
7
 
7
 
8
-import org.openzen.drawablegui.border.DBorder;
9
-import org.openzen.drawablegui.border.DLineBorder;
8
+import org.openzen.drawablegui.style.DBaseStyle;
10
 import org.openzen.drawablegui.style.DStyleDefinition;
9
 import org.openzen.drawablegui.style.DStyleDefinition;
11
 
10
 
12
 /**
11
 /**
13
  *
12
  *
14
  * @author Hoofdgebruiker
13
  * @author Hoofdgebruiker
15
  */
14
  */
16
-public class DScrollPaneStyle {
17
-	public final DBorder border;
18
-	
15
+public class DScrollPaneStyle extends DBaseStyle {
19
 	public DScrollPaneStyle(DStyleDefinition style) {
16
 	public DScrollPaneStyle(DStyleDefinition style) {
20
-		this.border = style.getBorder("border", context -> new DLineBorder(0xFF888888, 1));
17
+		super(style);
21
 	}
18
 	}
22
 }
19
 }

+ 45
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DBaseStyle.java View File

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.border.DBorder;
9
+import org.openzen.drawablegui.border.DEmptyBorder;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class DBaseStyle {
16
+	public final DMargin margin;
17
+	public final DBorder border;
18
+	public final DShadow shadow;
19
+	public final DShape shape;
20
+	public final int backgroundColor;
21
+	
22
+	public DBaseStyle(DStyleDefinition style) {
23
+		border = style.getBorder("border", DEmptyBorder.ELEMENT);
24
+		backgroundColor = style.getColor("backgroundColor", 0);
25
+		margin = style.getMargin("margin", DMargin.EMPTY_ELEMENT);
26
+		shape = style.getShape("shape", DRectangleShape.ELEMENT);
27
+		shadow = style.getShadow("shadow", DShadow.NONE_ELEMENT);
28
+	}
29
+	
30
+	public DBaseStyle(DStyleDefinition style, DBorderElement defaultBorder, int defaultBackgroundColor) {
31
+		border = style.getBorder("border", defaultBorder);
32
+		backgroundColor = style.getColor("backgroundColor", defaultBackgroundColor);
33
+		margin = style.getMargin("margin", DMargin.EMPTY_ELEMENT);
34
+		shape = style.getShape("shape", DRectangleShape.ELEMENT);
35
+		shadow = style.getShadow("shadow", DShadow.NONE_ELEMENT);
36
+	}
37
+	
38
+	public DBaseStyle(DStyleDefinition style, DBorderElement defaultBorder, int defaultBackgroundColor, DShapeElement defaultShape, DShadowElement defaultShadow) {
39
+		border = style.getBorder("border", defaultBorder);
40
+		backgroundColor = style.getColor("backgroundColor", defaultBackgroundColor);
41
+		margin = style.getMargin("margin", DMargin.EMPTY_ELEMENT);
42
+		shape = style.getShape("shape", defaultShape);
43
+		shadow = style.getShadow("shadow", defaultShadow);
44
+	}
45
+}

+ 22
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DBorderElement.java View File

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
+import org.openzen.drawablegui.border.DBorder;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface DBorderElement extends DStyleElement {
16
+	DBorder eval(DUIContext context);
17
+	
18
+	@Override
19
+	default DBorderElement asBorder() {
20
+		return this;
21
+	}
22
+}

+ 23
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DColorElement.java View File

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 DColorElement implements DStyleElement {
13
+	private final int color;
14
+	
15
+	public DColorElement(int color) {
16
+		this.color = color;
17
+	}
18
+	
19
+	@Override
20
+	public int asColor() {
21
+		return color;
22
+	}
23
+}

+ 6
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/style/DDimension.java View File

11
  *
11
  *
12
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
13
  */
13
  */
14
-public interface DDimension {
14
+public interface DDimension extends DStyleElement {
15
 	float eval(DUIContext context);
15
 	float eval(DUIContext context);
16
 	
16
 	
17
 	default int evalInt(DUIContext context) {
17
 	default int evalInt(DUIContext context) {
18
 		return (int)(eval(context) + 0.5f);
18
 		return (int)(eval(context) + 0.5f);
19
 	}
19
 	}
20
+	
21
+	@Override
22
+	default DDimension asDimension() {
23
+		return this;
24
+	}
20
 }
25
 }

+ 16
- 7
DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStyleDefinition.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.style;
6
 package org.openzen.drawablegui.style;
7
 
7
 
8
-import java.util.function.Function;
9
 import org.openzen.drawablegui.DFont;
8
 import org.openzen.drawablegui.DFont;
10
 import org.openzen.drawablegui.DUIContext;
9
 import org.openzen.drawablegui.DUIContext;
11
 import org.openzen.drawablegui.border.DBorder;
10
 import org.openzen.drawablegui.border.DBorder;
37
 	}
36
 	}
38
 
37
 
39
 	@Override
38
 	@Override
40
-	public DShadow getShadow(String name, Function<DUIContext, DShadow> defaultValue) {
41
-		return defaultValue.apply(context);
39
+	public DShadow getShadow(String name, DShadowElement defaultValue) {
40
+		return defaultValue.eval(context);
42
 	}
41
 	}
43
 
42
 
44
 	@Override
43
 	@Override
45
-	public DFont getFont(String name, Function<DUIContext, DFont> defaultValue) {
46
-		return defaultValue.apply(context);
44
+	public DFont getFont(String name, DFontElement defaultValue) {
45
+		return defaultValue.eval(context);
47
 	}
46
 	}
48
 
47
 
49
 	@Override
48
 	@Override
50
-	public DBorder getBorder(String name, Function<DUIContext, DBorder> defaultValue) {
51
-		return defaultValue.apply(context);
49
+	public DBorder getBorder(String name, DBorderElement defaultValue) {
50
+		return defaultValue.eval(context);
51
+	}
52
+	
53
+	@Override
54
+	public DMargin getMargin(String name, DMarginElement defaultValue) {
55
+		return defaultValue.eval(context);
56
+	}
57
+	
58
+	@Override
59
+	public DShape getShape(String name, DShapeElement defaultValue) {
60
+		return defaultValue.eval(context);
52
 	}
61
 	}
53
 }
62
 }

+ 23
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStylesheet.java View File

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 DEmptyStylesheet implements DStylesheet {
15
+	public static final DEmptyStylesheet INSTANCE = new DEmptyStylesheet();
16
+	
17
+	private DEmptyStylesheet() {}
18
+
19
+	@Override
20
+	public DStyleDefinition getInstance(DUIContext context) {
21
+		return new DEmptyStyleDefinition(context);
22
+	}
23
+}

+ 1
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/style/DEmptyStylesheets.java View File

16
 
16
 
17
 	@Override
17
 	@Override
18
 	public DStyleDefinition get(DUIContext context, DStylePath path) {
18
 	public DStyleDefinition get(DUIContext context, DStylePath path) {
19
-		return new DEmptyStyleDefinition(context);
19
+		return path.getInline(context);
20
 	}
20
 	}
21
 }
21
 }

+ 23
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DFontElement.java View File

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.DFont;
9
+import org.openzen.drawablegui.DUIContext;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+@FunctionalInterface
16
+public interface DFontElement extends DStyleElement {
17
+	DFont eval(DUIContext context);
18
+	
19
+	@Override
20
+	default DFontElement asFont() {
21
+		return this;
22
+	}
23
+}

+ 49
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DMargin.java View File

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.DIRectangle;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class DMargin {
15
+	public static final DMargin EMPTY = new DMargin(0);
16
+	public static final DMarginElement EMPTY_ELEMENT = context -> EMPTY;
17
+	
18
+	public final int left;
19
+	public final int right;
20
+	public final int top;
21
+	public final int bottom;
22
+	
23
+	public DMargin(int left, int right, int top, int bottom) {
24
+		this.left = left;
25
+		this.right = right;
26
+		this.top = top;
27
+		this.bottom = bottom;
28
+	}
29
+	
30
+	public DMargin(int amount) {
31
+		this(amount, amount, amount, amount);
32
+	}
33
+	
34
+	public int getVertical() {
35
+		return top + bottom;
36
+	}
37
+	
38
+	public int getHorizontal() {
39
+		return left + right;
40
+	}
41
+	
42
+	public DIRectangle apply(DIRectangle bounds) {
43
+		return new DIRectangle(
44
+				bounds.x + left,
45
+				bounds.y + top,
46
+				bounds.width - left - right,
47
+				bounds.height - top - bottom);
48
+	}
49
+}

+ 20
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DMarginElement.java View File

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 DMarginElement extends DStyleElement {
15
+	DMargin eval(DUIContext context);
16
+	
17
+	default DMarginElement asMargin() {
18
+		return this;
19
+	}
20
+}

+ 2
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DPxDimension.java View File

12
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
13
  */
13
  */
14
 public class DPxDimension implements DDimension {
14
 public class DPxDimension implements DDimension {
15
+	public static final DPxDimension ZERO = new DPxDimension(0);
16
+	
15
 	private final float pixels;
17
 	private final float pixels;
16
 	
18
 	
17
 	public DPxDimension(float pixels) {
19
 	public DPxDimension(float pixels) {

+ 23
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DRectangleShape.java View File

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.DIRectangle;
9
+import org.openzen.drawablegui.DPath;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class DRectangleShape implements DShape {
16
+	public static final DRectangleShape INSTANCE = new DRectangleShape();
17
+	public static final DShapeElement ELEMENT = context -> INSTANCE;
18
+
19
+	@Override
20
+	public DPath instance(DIRectangle bounds) {
21
+		return DPath.rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
22
+	}
23
+}

+ 36
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DRoundedRectangleShape.java View File

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.DIRectangle;
9
+import org.openzen.drawablegui.DPath;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class DRoundedRectangleShape implements DShape {
16
+	private final float radiusTopLeft;
17
+	private final float radiusTopRight;
18
+	private final float radiusBottomLeft;
19
+	private final float radiusBottomRight;
20
+	
21
+	public DRoundedRectangleShape(float radius) {
22
+		this(radius, radius, radius, radius);
23
+	}
24
+	
25
+	public DRoundedRectangleShape(float radiusTopLeft, float radiusTopRight, float radiusBottomLeft, float radiusBottomRight) {
26
+		this.radiusTopLeft = radiusTopLeft;
27
+		this.radiusTopRight = radiusTopRight;
28
+		this.radiusBottomLeft = radiusBottomLeft;
29
+		this.radiusBottomRight = radiusBottomRight;
30
+	}
31
+
32
+	@Override
33
+	public DPath instance(DIRectangle bounds) {
34
+		return DPath.roundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, radiusTopLeft, radiusTopRight, radiusBottomLeft, radiusBottomRight);
35
+	}
36
+}

+ 1
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DShadow.java View File

11
  */
11
  */
12
 public class DShadow {
12
 public class DShadow {
13
 	public static final DShadow NONE = new DShadow(0, 0, 0, 0);
13
 	public static final DShadow NONE = new DShadow(0, 0, 0, 0);
14
+	public static final DShadowElement NONE_ELEMENT = context -> NONE;
14
 	
15
 	
15
 	public final int color;
16
 	public final int color;
16
 	public final float offsetX;
17
 	public final float offsetX;

+ 21
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DShadowElement.java View File

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 DShadowElement extends DStyleElement {
15
+	DShadow eval(DUIContext context);
16
+	
17
+	@Override
18
+	default DShadowElement asShadow() {
19
+		return this;
20
+	}
21
+}

+ 17
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DShape.java View File

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.DIRectangle;
9
+import org.openzen.drawablegui.DPath;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public interface DShape {
16
+	DPath instance(DIRectangle bounds);
17
+}

+ 22
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DShapeElement.java View File

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
+@FunctionalInterface
15
+public interface DShapeElement extends DStyleElement {
16
+	DShape eval(DUIContext context);
17
+	
18
+	@Override
19
+	default DShapeElement asShape() {
20
+		return this;
21
+	}
22
+}

+ 100
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DSimpleStylesheet.java View File

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.Map;
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 DSimpleStylesheet implements DStylesheet {
18
+	private final Map<String, DStyleElement> elements;
19
+	
20
+	public DSimpleStylesheet(Map<String, DStyleElement> elements) {
21
+		this.elements = elements;
22
+	}
23
+
24
+	@Override
25
+	public DStyleDefinition getInstance(DUIContext context) {
26
+		return new Instance(context);
27
+	}
28
+	
29
+	private class Instance implements DStyleDefinition {
30
+		private final DUIContext context;
31
+		
32
+		private Instance(DUIContext context) {
33
+			this.context = context;
34
+		}
35
+
36
+		@Override
37
+		public int getDimension(String name, DDimension defaultValue) {
38
+			if (!elements.containsKey(name))
39
+				return defaultValue.evalInt(context);
40
+			
41
+			return elements.get(name).asDimension().evalInt(context);
42
+		}
43
+
44
+		@Override
45
+		public float getFloatDimension(String name, DDimension defaultValue) {
46
+			if (!elements.containsKey(name))
47
+				return defaultValue.eval(context);
48
+			
49
+			return elements.get(name).asDimension().eval(context);
50
+		}
51
+
52
+		@Override
53
+		public int getColor(String name, int defaultValue) {
54
+			if (!elements.containsKey(name))
55
+				return defaultValue;
56
+			
57
+			return elements.get(name).asColor();
58
+		}
59
+
60
+		@Override
61
+		public DShadow getShadow(String name, DShadowElement defaultValue) {
62
+			if (!elements.containsKey(name))
63
+				return defaultValue.eval(context);
64
+			
65
+			return elements.get(name).asShadow().eval(context);
66
+		}
67
+
68
+		@Override
69
+		public DFont getFont(String name, DFontElement defaultValue) {
70
+			if (!elements.containsKey(name))
71
+				return defaultValue.eval(context);
72
+			
73
+			return elements.get(name).asFont().eval(context);
74
+		}
75
+
76
+		@Override
77
+		public DBorder getBorder(String name, DBorderElement defaultValue) {
78
+			if (!elements.containsKey(name))
79
+				return defaultValue.eval(context);
80
+			
81
+			return elements.get(name).asBorder().eval(context);
82
+		}
83
+		
84
+		@Override
85
+		public DMargin getMargin(String name, DMarginElement defaultValue) {
86
+			if (!elements.containsKey(name))
87
+				return defaultValue.eval(context);
88
+			
89
+			return elements.get(name).asMargin().eval(context);
90
+		}
91
+		
92
+		@Override
93
+		public DShape getShape(String name, DShapeElement defaultValue) {
94
+			if (!elements.containsKey(name))
95
+				return defaultValue.eval(context);
96
+			
97
+			return elements.get(name).asShape().eval(context);
98
+		}
99
+	}
100
+}

+ 13
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleClass.java View File

11
  */
11
  */
12
 public class DStyleClass {
12
 public class DStyleClass {
13
 	private static final String[] NO_CLASSES = new String[0];
13
 	private static final String[] NO_CLASSES = new String[0];
14
-	public static final DStyleClass EMPTY = new DStyleClass(null, NO_CLASSES);
14
+	public static final DStyleClass EMPTY = new DStyleClass(null, NO_CLASSES, DEmptyStylesheet.INSTANCE);
15
 	
15
 	
16
 	public static DStyleClass forId(String id) {
16
 	public static DStyleClass forId(String id) {
17
-		return new DStyleClass(id, NO_CLASSES);
17
+		return new DStyleClass(id, NO_CLASSES, DEmptyStylesheet.INSTANCE);
18
+	}
19
+	
20
+	public static DStyleClass inline(DStylesheet stylesheet) {
21
+		return new DStyleClass(null, NO_CLASSES, stylesheet);
22
+	}
23
+	
24
+	public static DStyleClass inline(String id, DStylesheet stylesheet) {
25
+		return new DStyleClass(id, NO_CLASSES, stylesheet);
18
 	}
26
 	}
19
 	
27
 	
20
 	public final String id;
28
 	public final String id;
21
 	public final String[] classes;
29
 	public final String[] classes;
30
+	public final DStylesheet inline;
22
 	
31
 	
23
-	public DStyleClass(String id, String[] classes) {
32
+	public DStyleClass(String id, String[] classes, DStylesheet inline) {
24
 		this.id = id;
33
 		this.id = id;
25
 		this.classes = classes;
34
 		this.classes = classes;
35
+		this.inline = inline;
26
 	}
36
 	}
27
 }
37
 }

+ 7
- 5
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleDefinition.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.style;
6
 package org.openzen.drawablegui.style;
7
 
7
 
8
-import java.util.function.Function;
9
 import org.openzen.drawablegui.DFont;
8
 import org.openzen.drawablegui.DFont;
10
-import org.openzen.drawablegui.DUIContext;
11
 import org.openzen.drawablegui.border.DBorder;
9
 import org.openzen.drawablegui.border.DBorder;
12
 
10
 
13
 /**
11
 /**
21
 	
19
 	
22
 	public int getColor(String name, int defaultValue);
20
 	public int getColor(String name, int defaultValue);
23
 	
21
 	
24
-	public DShadow getShadow(String name, Function<DUIContext, DShadow> defaultValue);
22
+	public DShadow getShadow(String name, DShadowElement defaultValue);
25
 	
23
 	
26
-	public DFont getFont(String name, Function<DUIContext, DFont> defaultValue);
24
+	public DFont getFont(String name, DFontElement defaultValue);
27
 	
25
 	
28
-	public DBorder getBorder(String name, Function<DUIContext, DBorder> defaultValue);
26
+	public DBorder getBorder(String name, DBorderElement defaultValue);
27
+	
28
+	public DMargin getMargin(String name, DMarginElement defaultValue);
29
+	
30
+	public DShape getShape(String name, DShapeElement defaultValue);
29
 }
31
 }

+ 45
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStyleElement.java View File

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 DStyleElement {
18
+	default DDimension asDimension() {
19
+		throw new RuntimeException("Not a dimension!");
20
+	}
21
+	
22
+	default int asColor() {
23
+		throw new RuntimeException("Not a color!");
24
+	}
25
+	
26
+	default DFontElement asFont() {
27
+		throw new RuntimeException("Not a font!");
28
+	}
29
+	
30
+	default DBorderElement asBorder() {
31
+		throw new RuntimeException("Not a border!");
32
+	}
33
+	
34
+	default DMarginElement asMargin() {
35
+		throw new RuntimeException("Not a margin!");
36
+	}
37
+	
38
+	default DShadowElement asShadow() {
39
+		throw new RuntimeException("Not a shadow!");
40
+	}
41
+	
42
+	default DShapeElement asShape() {
43
+		throw new RuntimeException("Not a shape!");
44
+	}
45
+}

+ 4
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePath.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.style;
6
 package org.openzen.drawablegui.style;
7
 
7
 
8
+import org.openzen.drawablegui.DUIContext;
9
+
8
 /**
10
 /**
9
  *
11
  *
10
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
11
  */
13
  */
12
 public interface DStylePath {
14
 public interface DStylePath {
13
 	public DStylePath getChild(String element, DStyleClass styleClass);
15
 	public DStylePath getChild(String element, DStyleClass styleClass);
16
+	
17
+	public DStyleDefinition getInline(DUIContext context);
14
 }
18
 }

+ 12
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylePathRoot.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.style;
6
 package org.openzen.drawablegui.style;
7
 
7
 
8
+import org.openzen.drawablegui.DUIContext;
9
+
8
 /**
10
 /**
9
  *
11
  *
10
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
19
 		return new DStyleChildElement(this, element, styleClass);
21
 		return new DStyleChildElement(this, element, styleClass);
20
 	}
22
 	}
21
 	
23
 	
24
+	@Override
25
+	public DStyleDefinition getInline(DUIContext context) {
26
+		return new DEmptyStyleDefinition(context);
27
+	}
28
+	
22
 	private static class DStyleChildElement implements DStylePath {
29
 	private static class DStyleChildElement implements DStylePath {
23
 		private final DStylePath parent;
30
 		private final DStylePath parent;
24
 		private final String element;
31
 		private final String element;
34
 		public DStylePath getChild(String element, DStyleClass styleClass) {
41
 		public DStylePath getChild(String element, DStyleClass styleClass) {
35
 			return new DStyleChildElement(this, element, styleClass);
42
 			return new DStyleChildElement(this, element, styleClass);
36
 		}
43
 		}
44
+
45
+		@Override
46
+		public DStyleDefinition getInline(DUIContext context) {
47
+			return styleClass.inline.getInstance(context);
48
+		}
37
 	}
49
 	}
38
 }
50
 }

+ 16
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylesheet.java View File

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 DStylesheet {
15
+	DStyleDefinition getInstance(DUIContext context);
16
+}

+ 66
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/style/DStylesheetBuilder.java View File

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.HashMap;
9
+import java.util.Map;
10
+
11
+/**
12
+ *
13
+ * @author Hoofdgebruiker
14
+ */
15
+public class DStylesheetBuilder {
16
+	private final Map<String, DStyleElement> elements = new HashMap<>();
17
+	
18
+	public DStylesheetBuilder dimensionDp(String name, float value) {
19
+		elements.put(name, new DDpDimension(value));
20
+		return this;
21
+	}
22
+	
23
+	public DStylesheetBuilder dimensionPx(String name, float value) {
24
+		elements.put(name, new DPxDimension(value));
25
+		return this;
26
+	}
27
+	
28
+	public DStylesheetBuilder dimensionSp(String name, float value) {
29
+		elements.put(name, new DSpDimension(value));
30
+		return this;
31
+	}
32
+	
33
+	public DStylesheetBuilder color(String name, int value) {
34
+		elements.put(name, new DColorElement(value));
35
+		return this;
36
+	}
37
+	
38
+	public DStylesheetBuilder font(String name, DFontElement font) {
39
+		elements.put(name, font);
40
+		return this;
41
+	}
42
+	
43
+	public DStylesheetBuilder shadow(String name, DShadowElement shadow) {
44
+		elements.put(name, shadow);
45
+		return this;
46
+	}
47
+	
48
+	public DStylesheetBuilder border(String name, DBorderElement border) {
49
+		elements.put(name, border);
50
+		return this;
51
+	}
52
+	
53
+	public DStylesheetBuilder marginDp(String name, float value) {
54
+		elements.put(name, (DMarginElement)context -> new DMargin(context.dp(value)));
55
+		return this;
56
+	}
57
+	
58
+	public DStylesheetBuilder shape(String name, DShapeElement shape) {
59
+		elements.put(name, shape);
60
+		return this;
61
+	}
62
+	
63
+	public DStylesheet build() {
64
+		return new DSimpleStylesheet(elements);
65
+	}
66
+}

+ 0
- 209
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingCanvas.java View File

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
-}

+ 22
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDialog.java View File

7
 
7
 
8
 import java.awt.BorderLayout;
8
 import java.awt.BorderLayout;
9
 import java.awt.Color;
9
 import java.awt.Color;
10
+import java.awt.event.ComponentAdapter;
11
+import java.awt.event.ComponentEvent;
10
 import java.awt.event.WindowEvent;
12
 import java.awt.event.WindowEvent;
11
 import java.awt.event.WindowListener;
13
 import java.awt.event.WindowListener;
12
 import java.awt.event.WindowStateListener;
14
 import java.awt.event.WindowStateListener;
20
 import org.openzen.drawablegui.border.DCustomWindowBorder;
22
 import org.openzen.drawablegui.border.DCustomWindowBorder;
21
 import org.openzen.drawablegui.live.LiveBool;
23
 import org.openzen.drawablegui.live.LiveBool;
22
 import org.openzen.drawablegui.live.LiveObject;
24
 import org.openzen.drawablegui.live.LiveObject;
25
+import org.openzen.drawablegui.live.MutableLiveObject;
23
 import org.openzen.drawablegui.live.SimpleLiveBool;
26
 import org.openzen.drawablegui.live.SimpleLiveBool;
24
 import org.openzen.drawablegui.live.SimpleLiveObject;
27
 import org.openzen.drawablegui.live.SimpleLiveObject;
25
 import org.openzen.drawablegui.style.DStyleClass;
28
 import org.openzen.drawablegui.style.DStyleClass;
33
 	private final boolean noTitleBar;
36
 	private final boolean noTitleBar;
34
 	private final SimpleLiveObject<State> state = new SimpleLiveObject<>(State.NORMAL);
37
 	private final SimpleLiveObject<State> state = new SimpleLiveObject<>(State.NORMAL);
35
 	private final SimpleLiveBool active = new SimpleLiveBool(true);
38
 	private final SimpleLiveBool active = new SimpleLiveBool(true);
39
+	private final MutableLiveObject<DIRectangle> bounds = new SimpleLiveObject<>(DIRectangle.EMPTY);
36
 	
40
 	
37
 	public SwingDialog(SwingWindow owner, String title, DComponent root, boolean noTitleBar) {
41
 	public SwingDialog(SwingWindow owner, String title, DComponent root, boolean noTitleBar) {
38
 		super(owner, title);
42
 		super(owner, title);
46
 		
50
 		
47
 		addWindowListener(this);
51
 		addWindowListener(this);
48
 		addWindowStateListener(this);
52
 		addWindowStateListener(this);
53
+		addComponentListener(new ComponentAdapter() {
54
+			@Override
55
+			public void componentMoved(ComponentEvent componentEvent) {
56
+				updateBounds();
57
+			}
58
+			
59
+			@Override
60
+			public void componentResized(ComponentEvent componentEvent) {
61
+				updateBounds();
62
+			}
63
+		});
49
 		
64
 		
50
 		getContentPane().add(swingComponent = new SwingRoot(root), BorderLayout.CENTER);
65
 		getContentPane().add(swingComponent = new SwingRoot(root), BorderLayout.CENTER);
51
 		swingComponent.setWindow(this);
66
 		swingComponent.setWindow(this);
76
 	}
91
 	}
77
 
92
 
78
 	@Override
93
 	@Override
79
-	public DIRectangle getWindowBounds() {
80
-		return new DIRectangle(getX(), getY(), getWidth(), getHeight());
94
+	public LiveObject<DIRectangle> getWindowBounds() {
95
+		return bounds;
81
 	}
96
 	}
82
 
97
 
83
 	@Override
98
 	@Override
135
 
150
 
136
 	@Override
151
 	@Override
137
 	public void windowOpened(WindowEvent e) {
152
 	public void windowOpened(WindowEvent e) {
138
-		
153
+		updateBounds();
139
 	}
154
 	}
140
 
155
 
141
 	@Override
156
 	@Override
173
 		state.setValue(getStateFromWindowState());
188
 		state.setValue(getStateFromWindowState());
174
 	}
189
 	}
175
 	
190
 	
191
+	private void updateBounds() {
192
+		bounds.setValue(new DIRectangle(getX(), getY(), getWidth(), getHeight()));
193
+	}
194
+	
176
 	private State getStateFromWindowState() {
195
 	private State getStateFromWindowState() {
177
 		/*switch (ge()) {
196
 		/*switch (ge()) {
178
 			case NORMAL:
197
 			case NORMAL:

+ 202
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawSurface.java View File

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.Graphics2D;
10
+import java.awt.geom.AffineTransform;
11
+import java.awt.image.ConvolveOp;
12
+import java.awt.image.Kernel;
13
+import java.util.ArrayList;
14
+import java.util.List;
15
+import org.openzen.drawablegui.DFont;
16
+import org.openzen.drawablegui.DFontFamily;
17
+import org.openzen.drawablegui.DFontMetrics;
18
+import org.openzen.drawablegui.DIRectangle;
19
+import org.openzen.drawablegui.DPath;
20
+import org.openzen.drawablegui.DTransform2D;
21
+import org.openzen.drawablegui.draw.DDrawSurface;
22
+import org.openzen.drawablegui.draw.DDrawnRectangle;
23
+import org.openzen.drawablegui.draw.DDrawnShape;
24
+import org.openzen.drawablegui.draw.DDrawnText;
25
+import org.openzen.drawablegui.draw.DSubSurface;
26
+import org.openzen.drawablegui.style.DShadow;
27
+import org.openzen.drawablegui.style.DStyleDefinition;
28
+import org.openzen.drawablegui.style.DStylePath;
29
+
30
+/**
31
+ *
32
+ * @author Hoofdgebruiker
33
+ */
34
+public class SwingDrawSurface implements DDrawSurface {
35
+	private final List<SwingDrawnElement> elements = new ArrayList<>();
36
+	private final SwingGraphicsContext context;
37
+	public int offsetX;
38
+	public int offsetY;
39
+	
40
+	public SwingDrawSurface(SwingGraphicsContext context, int offsetX, int offsetY) {
41
+		this.context = context;
42
+		this.offsetX = offsetX;
43
+		this.offsetY = offsetY;
44
+	}
45
+	
46
+	public void setOffset(int offsetX, int offsetY) {
47
+		this.offsetX = offsetX;
48
+		this.offsetY = offsetY;
49
+	}
50
+	
51
+	public void paint(Graphics2D g, DIRectangle clip) {
52
+		for (SwingDrawnElement element : elements)
53
+			if (clip == null || clip.overlaps(element.getBounds()))
54
+				element.paint(g, clip);
55
+	}
56
+	
57
+	public DIRectangle calculateBounds() {
58
+		if (elements.isEmpty())
59
+			return DIRectangle.EMPTY;
60
+		
61
+		DIRectangle result = elements.get(0).getBounds();
62
+		for (SwingDrawnElement element : elements)
63
+			result = result.union(element.getBounds());
64
+		return result;
65
+	}
66
+
67
+	@Override
68
+	public SwingGraphicsContext getContext() {
69
+		return context;
70
+	}
71
+
72
+	@Override
73
+	public DStyleDefinition getStylesheet(DStylePath path) {
74
+		return context.getStylesheets().get(context, path);
75
+	}
76
+	
77
+	@Override
78
+	public DFontMetrics getFontMetrics(DFont font) {
79
+		return context.getFontMetrics(font);
80
+	}
81
+	
82
+	@Override
83
+	public float getScale() {
84
+		return context.getScale();
85
+	}
86
+	
87
+	@Override
88
+	public float getTextScale() {
89
+		return context.getTextScale();
90
+	}
91
+
92
+	@Override
93
+	public DDrawnText drawText(int z, DFont font, int color, float x, float y, String text) {
94
+		DFontMetrics fontMetrics = context.getFontMetrics(font);
95
+		return addElement(new SwingDrawnText(this, z, x, y, color, font, text, fontMetrics.getAscent(), fontMetrics.getDescent(), fontMetrics.getWidth(text)));
96
+	}
97
+
98
+	@Override
99
+	public DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth) {
100
+		return addElement(new SwingStrokedPath(this, z, transform, color, path, context.getPath(path), lineWidth));
101
+	}
102
+	
103
+	@Override
104
+	public DDrawnRectangle fillRect(int z, DIRectangle rectangle, int color) {
105
+		return addElement(new SwingDrawnRectangle(this, z, rectangle, color));
106
+	}
107
+
108
+	@Override
109
+	public DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color) {
110
+		return addElement(new SwingFilledPath(this, z, transform, path, context.getPath(path), color));
111
+	}
112
+
113
+	@Override
114
+	public DDrawnShape shadowPath(int z, DPath path, DTransform2D transform, int color, DShadow shadow) {
115
+		if (shadow.color == 0 || shadow.radius == 0) {
116
+			return fillPath(z, path, transform, color);
117
+		}
118
+		
119
+		return addElement(new SwingShadowedPath(this, z, transform, path, context.getPath(path), color, shadow));
120
+	}
121
+	
122
+	@Override
123
+	public DSubSurface createSubSurface(int z) {
124
+		return addElement(new SwingSubSurface(this, z));
125
+	}
126
+	
127
+	public void remove(SwingDrawnElement element) {
128
+		elements.remove(element);
129
+		repaint(element.getBounds());
130
+	}
131
+	
132
+	public void repaint(int x, int y, int width, int height) {
133
+		context.repaint(x + offsetX, y + offsetY, width, height);
134
+	}
135
+	
136
+	public void repaint(DIRectangle rectangle) {
137
+		context.repaint(rectangle.offset(offsetX, offsetY));
138
+	}
139
+	
140
+	private <T extends SwingDrawnElement> T addElement(T element) {
141
+		int index = elements.size();
142
+		while (index > 0 && element.z < elements.get(index - 1).z)
143
+			index--;
144
+		
145
+		elements.add(index, element);
146
+		repaint(element.getBounds());
147
+		return element;
148
+	}
149
+	
150
+	public static void prepare(DFont font) {
151
+		if (font.cached != null && font.cached instanceof Font)
152
+			return;
153
+		
154
+		String baseFontName = font.family == DFontFamily.CODE ? "Consolas" : Font.DIALOG;
155
+		int style = 0;
156
+		if (font.bold)
157
+			style |= Font.BOLD;
158
+		if (font.italic)
159
+			style |= Font.ITALIC;
160
+		
161
+		font.cached = Font.decode(baseFontName).deriveFont(style, font.size);
162
+	}
163
+	
164
+	public static AffineTransform getTransform(DTransform2D transform) {
165
+		return new AffineTransform(transform.xx, transform.xy, transform.yx, transform.yy, transform.dx, transform.dy);
166
+	}
167
+    
168
+	
169
+	// taken from http://www.java2s.com/Code/Java/Advanced-Graphics/GaussianBlurDemo.htm
170
+    public static ConvolveOp getGaussianBlurFilter(int radius, boolean horizontal) {
171
+        if (radius < 1) {
172
+            throw new IllegalArgumentException("Radius must be >= 1");
173
+        }
174
+        
175
+        int size = radius * 2 + 1;
176
+        float[] data = new float[size];
177
+        
178
+        float sigma = radius / 3.0f;
179
+        float twoSigmaSquare = 2.0f * sigma * sigma;
180
+        float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
181
+        float total = 0.0f;
182
+        
183
+        for (int i = -radius; i <= radius; i++) {
184
+            float distance = i * i;
185
+            int index = i + radius;
186
+            data[index] = (float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
187
+            total += data[index];
188
+        }
189
+        
190
+        for (int i = 0; i < data.length; i++) {
191
+            data[i] /= total;
192
+        }        
193
+        
194
+        Kernel kernel = null;
195
+        if (horizontal) {
196
+            kernel = new Kernel(size, 1, data);
197
+        } else {
198
+            kernel = new Kernel(1, size, data);
199
+        }
200
+        return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
201
+    }
202
+}

+ 35
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnElement.java View File

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.Graphics2D;
9
+import org.openzen.drawablegui.DIRectangle;
10
+import org.openzen.drawablegui.draw.DDrawnElement;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public abstract class SwingDrawnElement implements DDrawnElement {
17
+	public final SwingDrawSurface target;
18
+	public final int z;
19
+	
20
+	public SwingDrawnElement(SwingDrawSurface target, int z) {
21
+		this.target = target;
22
+		this.z = z;
23
+	}
24
+	
25
+	abstract void paint(Graphics2D g, DIRectangle clip);
26
+	
27
+	@Override
28
+	public void close() {
29
+		target.remove(this);
30
+	}
31
+	
32
+	protected void invalidate() {
33
+		target.repaint(getBounds());
34
+	}
35
+}

+ 57
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnRectangle.java View File

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.Color;
9
+import java.awt.Graphics2D;
10
+import org.openzen.drawablegui.DIRectangle;
11
+import org.openzen.drawablegui.DTransform2D;
12
+import org.openzen.drawablegui.draw.DDrawnRectangle;
13
+
14
+/**
15
+ *
16
+ * @author Hoofdgebruiker
17
+ */
18
+public class SwingDrawnRectangle extends SwingDrawnElement implements DDrawnRectangle {
19
+	private DIRectangle rectangle;
20
+	private Color awtColor;
21
+	
22
+	public SwingDrawnRectangle(SwingDrawSurface target, int z, DIRectangle rectangle, int color) {
23
+		super(target, z);
24
+		
25
+		this.rectangle = rectangle;
26
+		this.awtColor = new Color(color, true);
27
+	}
28
+	
29
+	@Override
30
+	public void setTransform(DTransform2D transform) {
31
+		// not supported?
32
+	}
33
+	
34
+	@Override
35
+	public DIRectangle getBounds() {
36
+		return rectangle;
37
+	}
38
+
39
+	@Override
40
+	public void setRectangle(DIRectangle rectangle) {
41
+		invalidate();
42
+		this.rectangle = rectangle;
43
+		invalidate();
44
+	}
45
+
46
+	@Override
47
+	public void setColor(int color) {
48
+		this.awtColor = new Color(color, true);
49
+		invalidate();
50
+	}
51
+
52
+	@Override
53
+	public void paint(Graphics2D g, DIRectangle clip) {
54
+		g.setColor(awtColor);
55
+		g.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
56
+	}
57
+}

+ 68
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnText.java View File

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.Color;
9
+import java.awt.Font;
10
+import java.awt.Graphics2D;
11
+import org.openzen.drawablegui.DFont;
12
+import org.openzen.drawablegui.DIRectangle;
13
+import org.openzen.drawablegui.draw.DDrawnText;
14
+
15
+/**
16
+ *
17
+ * @author Hoofdgebruiker
18
+ */
19
+public class SwingDrawnText extends SwingDrawnElement implements DDrawnText {
20
+	private float x;
21
+	private float y;
22
+	private final int width;
23
+	private final int ascent;
24
+	private final int descent;
25
+	private Color awtColor;
26
+	private final Font font;
27
+	private final String text;
28
+	
29
+	public SwingDrawnText(SwingDrawSurface target, int z, float x, float y, int color, DFont font, String text, int ascent, int descent, int width) {
30
+		super(target, z);
31
+		SwingDrawSurface.prepare(font);
32
+		
33
+		this.x = x;
34
+		this.y = y;
35
+		this.awtColor = new Color(color, true);
36
+		this.font = (Font) font.cached;
37
+		this.text = text;
38
+		this.ascent = ascent;
39
+		this.descent = descent;
40
+		this.width = width;
41
+	}
42
+
43
+	@Override
44
+	public void setPosition(float x, float y) {
45
+		invalidate();
46
+		this.x = x;
47
+		this.y = y;
48
+		invalidate();
49
+	}
50
+
51
+	@Override
52
+	public DIRectangle getBounds() {
53
+		return new DIRectangle((int)x, (int)y - ascent, width, ascent + descent);
54
+	}
55
+	
56
+	@Override
57
+	public void setColor(int color) {
58
+		this.awtColor = new Color(color, true);
59
+		invalidate();
60
+	}
61
+
62
+	@Override
63
+	public void paint(Graphics2D g, DIRectangle clip) {
64
+		g.setColor(awtColor);
65
+		g.setFont(font);
66
+		g.drawString(text, x, y);
67
+	}
68
+}

+ 75
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingFilledPath.java View File

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.Color;
9
+import java.awt.Graphics2D;
10
+import java.awt.geom.AffineTransform;
11
+import java.awt.geom.GeneralPath;
12
+import org.openzen.drawablegui.DIRectangle;
13
+import org.openzen.drawablegui.DPath;
14
+import org.openzen.drawablegui.DPathBoundsCalculator;
15
+import org.openzen.drawablegui.DTransform2D;
16
+import org.openzen.drawablegui.draw.DDrawnShape;
17
+
18
+/**
19
+ *
20
+ * @author Hoofdgebruiker
21
+ */
22
+public class SwingFilledPath extends SwingDrawnElement implements DDrawnShape {
23
+	private Color awtColor;
24
+	private AffineTransform transform;
25
+	
26
+	private final DPath originalPath;
27
+	private final GeneralPath path;
28
+	private DIRectangle bounds;
29
+	
30
+	public SwingFilledPath(
31
+			SwingDrawSurface target,
32
+			int z,
33
+			DTransform2D transform,
34
+			DPath originalPath,
35
+			GeneralPath path,
36
+			int color) {
37
+		super(target, z);
38
+		
39
+		this.originalPath = originalPath;
40
+		this.path = path;
41
+		
42
+		this.awtColor = color == 0 ? null : new Color(color, true);
43
+		this.transform = SwingDrawSurface.getTransform(transform);
44
+		this.bounds = DPathBoundsCalculator.getBounds(originalPath, transform);
45
+	}
46
+
47
+	@Override
48
+	public void setTransform(DTransform2D transform) {
49
+		this.transform = SwingDrawSurface.getTransform(transform);
50
+		this.bounds = DPathBoundsCalculator.getBounds(originalPath, transform);
51
+	}
52
+	
53
+	@Override
54
+	public DIRectangle getBounds() {
55
+		return bounds;
56
+	}
57
+
58
+	@Override
59
+	public void setColor(int color) {
60
+		this.awtColor = color == 0 ? null : new Color(color, true);
61
+		invalidate();
62
+	}
63
+
64
+	@Override
65
+	public void paint(Graphics2D g, DIRectangle clip) {
66
+		if (awtColor == null)
67
+			return;
68
+		
69
+		AffineTransform old = g.getTransform();
70
+		g.setColor(awtColor);
71
+		g.transform(transform);
72
+		g.fill(path);
73
+		g.setTransform(old);
74
+	}
75
+}

+ 29
- 19
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingGraphicsContext.java View File

8
 import java.awt.Dimension;
8
 import java.awt.Dimension;
9
 import java.awt.Font;
9
 import java.awt.Font;
10
 import java.awt.Graphics;
10
 import java.awt.Graphics;
11
+import java.awt.Point;
11
 import java.awt.geom.GeneralPath;
12
 import java.awt.geom.GeneralPath;
12
 import java.util.WeakHashMap;
13
 import java.util.WeakHashMap;
13
 import javax.swing.JFrame;
14
 import javax.swing.JFrame;
21
 import org.openzen.drawablegui.DFontMetrics;
22
 import org.openzen.drawablegui.DFontMetrics;
22
 import org.openzen.drawablegui.DPathTracer;
23
 import org.openzen.drawablegui.DPathTracer;
23
 import org.openzen.drawablegui.DTimerHandle;
24
 import org.openzen.drawablegui.DTimerHandle;
24
-import org.openzen.drawablegui.DTooltip;
25
-import org.openzen.drawablegui.DTooltipHandle;
26
 import org.openzen.drawablegui.DUIContext;
25
 import org.openzen.drawablegui.DUIContext;
27
 import org.openzen.drawablegui.DUIWindow;
26
 import org.openzen.drawablegui.DUIWindow;
27
+import org.openzen.drawablegui.draw.DDrawSurface;
28
 import org.openzen.drawablegui.style.DStylePathRoot;
28
 import org.openzen.drawablegui.style.DStylePathRoot;
29
 import org.openzen.drawablegui.style.DStyleSheets;
29
 import org.openzen.drawablegui.style.DStyleSheets;
30
 
30
 
41
 	private final JavaClipboard clipboard = new JavaClipboard();
41
 	private final JavaClipboard clipboard = new JavaClipboard();
42
 	private Graphics graphics;
42
 	private Graphics graphics;
43
 	private DUIWindow window;
43
 	private DUIWindow window;
44
+	private DDrawSurface surface;
44
 	
45
 	
45
 	public SwingGraphicsContext(DStyleSheets stylesheets, float scale, float textScale, SwingRoot root) {
46
 	public SwingGraphicsContext(DStyleSheets stylesheets, float scale, float textScale, SwingRoot root) {
46
 		this.stylesheets = stylesheets;
47
 		this.stylesheets = stylesheets;
49
 		this.root = root;
50
 		this.root = root;
50
 	}
51
 	}
51
 	
52
 	
53
+	public void setSurface(DDrawSurface surface) {
54
+		this.surface = surface;
55
+	}
56
+	
52
 	public GeneralPath getPath(DPath path) {
57
 	public GeneralPath getPath(DPath path) {
53
 		GeneralPath generalPath = preparedPaths.get(path);
58
 		GeneralPath generalPath = preparedPaths.get(path);
54
 		if (generalPath == null) {
59
 		if (generalPath == null) {
123
 		if (graphics == null)
128
 		if (graphics == null)
124
 			throw new AssertionError("No graphics available!");
129
 			throw new AssertionError("No graphics available!");
125
 		
130
 		
126
-		SwingCanvas.prepare(font);
131
+		SwingDrawSurface.prepare(font);
127
 		return new SwingFontMetrics(graphics.getFontMetrics((Font) font.cached), graphics);
132
 		return new SwingFontMetrics(graphics.getFontMetrics((Font) font.cached), graphics);
128
 	}
133
 	}
129
 
134
 
151
 
156
 
152
 	@Override
157
 	@Override
153
 	public DUIWindow openDialog(int x, int y, DAnchor anchor, String title, DComponent root) {
158
 	public DUIWindow openDialog(int x, int y, DAnchor anchor, String title, DComponent root) {
154
-		SwingDialog window = new SwingDialog((SwingWindow)this.window, title, root, false);
155
-		SwingGraphicsContext windowContext = new SwingGraphicsContext(stylesheets, scale, textScale, window.swingComponent);
159
+		SwingWindow swingWindow = (SwingWindow)this.window;
160
+		SwingDialog window = new SwingDialog(swingWindow, title, root, false);
161
+		SwingGraphicsContext windowContext = window.swingComponent.context;
156
 		windowContext.setWindow(window);
162
 		windowContext.setWindow(window);
157
 		windowContext.graphics = this.graphics; // help a little...
163
 		windowContext.graphics = this.graphics; // help a little...
164
+		windowContext.setSurface(window.swingComponent.surface);
165
+		
166
+		Point rootLocation = swingWindow.swingComponent.getLocationOnScreen();
158
 		
167
 		
159
-		root.setContext(DStylePathRoot.INSTANCE, windowContext);
168
+		root.mount(DStylePathRoot.INSTANCE, 0, windowContext.surface);
160
 		DSizing dimension = root.getSizing().getValue();
169
 		DSizing dimension = root.getSizing().getValue();
161
-		int tx = (int)(x - anchor.alignX * dimension.preferredWidth);
162
-		int ty = (int)(y - anchor.alignY * dimension.preferredHeight);
170
+		int tx = (int)(x + rootLocation.x - anchor.alignX * dimension.preferredWidth);
171
+		int ty = (int)(y + rootLocation.y - anchor.alignY * dimension.preferredHeight);
163
 		
172
 		
164
 		window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
173
 		window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
165
 		window.swingComponent.setPreferredSize(new Dimension(dimension.preferredWidth, dimension.preferredHeight));
174
 		window.swingComponent.setPreferredSize(new Dimension(dimension.preferredWidth, dimension.preferredHeight));
171
 
180
 
172
 	@Override
181
 	@Override
173
 	public DUIWindow openView(int x, int y, DAnchor anchor, DComponent root) {
182
 	public DUIWindow openView(int x, int y, DAnchor anchor, DComponent root) {
174
-		SwingDialog window = new SwingDialog((SwingWindow)this.window, "", root, false);
175
-		SwingGraphicsContext windowContext = new SwingGraphicsContext(stylesheets, scale, textScale, window.swingComponent);
183
+		SwingWindow swingWindow = (SwingWindow)this.window;
184
+		SwingInlineWindow window = new SwingInlineWindow(swingWindow, "", root);
185
+		SwingGraphicsContext windowContext = window.swingComponent.context;
176
 		windowContext.setWindow(window);
186
 		windowContext.setWindow(window);
177
 		windowContext.graphics = this.graphics; // help a little...
187
 		windowContext.graphics = this.graphics; // help a little...
188
+		windowContext.setSurface(window.swingComponent.surface);
178
 		
189
 		
179
-		root.setContext(DStylePathRoot.INSTANCE, windowContext);
190
+		root.mount(DStylePathRoot.INSTANCE, 0, windowContext.surface);
180
 		DSizing dimension = root.getSizing().getValue();
191
 		DSizing dimension = root.getSizing().getValue();
181
-		int tx = (int)(x - anchor.alignX * dimension.preferredWidth);
182
-		int ty = (int)(y - anchor.alignY * dimension.preferredHeight);
183
 		
192
 		
184
-		window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
193
+		Point rootLocation = swingWindow.swingComponent.getLocationOnScreen();
194
+		
195
+		int tx = (int)(x + rootLocation.x - anchor.alignX * dimension.preferredWidth);
196
+		int ty = (int)(y + rootLocation.y - anchor.alignY * dimension.preferredHeight);
197
+		
185
 		window.swingComponent.setPreferredSize(new Dimension(dimension.preferredWidth, dimension.preferredHeight));
198
 		window.swingComponent.setPreferredSize(new Dimension(dimension.preferredWidth, dimension.preferredHeight));
186
 		window.setLocation(tx, ty);
199
 		window.setLocation(tx, ty);
187
 		window.pack();
200
 		window.pack();
188
 		window.setVisible(true);
201
 		window.setVisible(true);
202
+		window.swingComponent.repaint();
203
+		
189
 		return window;
204
 		return window;
190
 	}
205
 	}
191
 	
206
 	
192
-	@Override
193
-	public DTooltipHandle openTooltip(int x, int y, DTooltip tooltip) {
194
-		return null; // TODO
195
-	}
196
-	
197
 	private class PathTracer implements DPathTracer {
207
 	private class PathTracer implements DPathTracer {
198
 		private final GeneralPath path;
208
 		private final GeneralPath path;
199
 		
209
 		

+ 156
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingInlineWindow.java View File

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.event.ComponentAdapter;
10
+import java.awt.event.ComponentEvent;
11
+import java.awt.event.WindowEvent;
12
+import java.awt.event.WindowListener;
13
+import java.awt.event.WindowStateListener;
14
+import javax.swing.JWindow;
15
+import org.openzen.drawablegui.DComponent;
16
+import org.openzen.drawablegui.DIRectangle;
17
+import org.openzen.drawablegui.DUIContext;
18
+import org.openzen.drawablegui.DUIWindow;
19
+import org.openzen.drawablegui.live.ImmutableLiveObject;
20
+import org.openzen.drawablegui.live.LiveBool;
21
+import org.openzen.drawablegui.live.LiveObject;
22
+import org.openzen.drawablegui.live.MutableLiveObject;
23
+import org.openzen.drawablegui.live.SimpleLiveBool;
24
+import org.openzen.drawablegui.live.SimpleLiveObject;
25
+
26
+/**
27
+ *
28
+ * @author Hoofdgebruiker
29
+ */
30
+public final class SwingInlineWindow extends JWindow implements WindowListener, WindowStateListener, DUIWindow {
31
+	public final SwingRoot swingComponent;
32
+	private final LiveObject<State> state = new ImmutableLiveObject<>(State.NORMAL);
33
+	private final SimpleLiveBool active = new SimpleLiveBool(true);
34
+	private final MutableLiveObject<DIRectangle> bounds = new SimpleLiveObject<>(DIRectangle.EMPTY);
35
+	
36
+	public SwingInlineWindow(SwingWindow owner, String title, DComponent root) {
37
+		super(owner);
38
+		
39
+		addWindowListener(this);
40
+		addWindowStateListener(this);
41
+		
42
+		getContentPane().add(swingComponent = new SwingRoot(root), BorderLayout.CENTER);
43
+		swingComponent.setWindow(this);
44
+		swingComponent.requestFocusInWindow();
45
+		addComponentListener(new ComponentAdapter() {
46
+			@Override
47
+			public void componentMoved(ComponentEvent componentEvent) {
48
+				updateBounds();
49
+			}
50
+			
51
+			@Override
52
+			public void componentResized(ComponentEvent componentEvent) {
53
+				updateBounds();
54
+			}
55
+		});
56
+	}
57
+	
58
+	@Override
59
+	public DUIContext getContext() {
60
+		return swingComponent.context;
61
+	}
62
+
63
+	@Override
64
+	public LiveObject<DIRectangle> getWindowBounds() {
65
+		return bounds;
66
+	}
67
+
68
+	@Override
69
+	public boolean hasTitleBar() {
70
+		return false;
71
+	}
72
+
73
+	@Override
74
+	public void close() {
75
+		dispose();
76
+	}
77
+
78
+	@Override
79
+	public void maximize() {
80
+		// cannot maximize
81
+	}
82
+
83
+	@Override
84
+	public void restore() {
85
+		// cannot restore
86
+	}
87
+
88
+	@Override
89
+	public void minimize() {
90
+		// cannot minimize
91
+	}
92
+
93
+	@Override
94
+	public LiveObject<State> getWindowState() {
95
+		return state;
96
+	}
97
+	
98
+	@Override
99
+	public LiveBool getActive() {
100
+		return active;
101
+	}
102
+	
103
+	@Override
104
+	public void focus(DComponent component) {
105
+		swingComponent.focus(component);
106
+	}
107
+	
108
+	@Override
109
+	public DUIWindow openModal(String title, DComponent component) {
110
+		throw new IllegalArgumentException("Cannot open a modal from an inline window!");
111
+	}
112
+
113
+	@Override
114
+	public void windowOpened(WindowEvent e) {
115
+		updateBounds();
116
+	}
117
+
118
+	@Override
119
+	public void windowClosing(WindowEvent e) {
120
+		
121
+	}
122
+
123
+	@Override
124
+	public void windowClosed(WindowEvent e) {
125
+		
126
+	}
127
+
128
+	@Override
129
+	public void windowIconified(WindowEvent e) {
130
+		
131
+	}
132
+
133
+	@Override
134
+	public void windowDeiconified(WindowEvent e) {
135
+		
136
+	}
137
+
138
+	@Override
139
+	public void windowActivated(WindowEvent e) {
140
+		active.setValue(true);
141
+	}
142
+
143
+	@Override
144
+	public void windowDeactivated(WindowEvent e) {
145
+		active.setValue(false);
146
+	}
147
+
148
+	@Override
149
+	public void windowStateChanged(WindowEvent e) {
150
+		
151
+	}
152
+	
153
+	private void updateBounds() {
154
+		bounds.setValue(new DIRectangle(getX(), getY(), getWidth(), getHeight()));
155
+	}
156
+}

+ 15
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingRoot.java View File

9
 import java.awt.Graphics;
9
 import java.awt.Graphics;
10
 import java.awt.Graphics2D;
10
 import java.awt.Graphics2D;
11
 import java.awt.Rectangle;
11
 import java.awt.Rectangle;
12
+import java.awt.RenderingHints;
12
 import java.awt.Toolkit;
13
 import java.awt.Toolkit;
13
 import java.awt.event.ComponentEvent;
14
 import java.awt.event.ComponentEvent;
14
 import java.awt.event.ComponentListener;
15
 import java.awt.event.ComponentListener;
34
  */
35
  */
35
 public final class SwingRoot extends Component implements ComponentListener, MouseListener, MouseMotionListener, MouseWheelListener, KeyListener {
36
 public final class SwingRoot extends Component implements ComponentListener, MouseListener, MouseMotionListener, MouseWheelListener, KeyListener {
36
 	public final SwingGraphicsContext context;
37
 	public final SwingGraphicsContext context;
38
+	public final SwingDrawSurface surface;
37
 	public final DComponent component;
39
 	public final DComponent component;
38
 	private DComponent focus = null;
40
 	private DComponent focus = null;
39
 	private boolean firstPaint = true;
41
 	private boolean firstPaint = true;
48
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
50
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
49
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
51
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
50
 				this);
52
 				this);
53
+		surface = new SwingDrawSurface(context, 0, 0);
54
+		context.setSurface(surface);
51
 		
55
 		
52
 		addComponentListener(this);
56
 		addComponentListener(this);
53
 		addMouseListener(this);
57
 		addMouseListener(this);
75
 	public void paint(Graphics g) {
79
 	public void paint(Graphics g) {
76
 		if (firstPaint) {
80
 		if (firstPaint) {
77
 			firstPaint = false;
81
 			firstPaint = false;
78
-			component.setContext(DStylePathRoot.INSTANCE, context);
82
+			component.mount(DStylePathRoot.INSTANCE, 0, surface);
79
 			component.setBounds(new DIRectangle(0, 0, getWidth(), getHeight()));
83
 			component.setBounds(new DIRectangle(0, 0, getWidth(), getHeight()));
80
 		}
84
 		}
81
 		
85
 		
86
+		long start = System.currentTimeMillis();
82
 		Rectangle clipBounds = g.getClipBounds();
87
 		Rectangle clipBounds = g.getClipBounds();
83
 		DIRectangle clipBounds2 = clipBounds == null ? null : new DIRectangle(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
88
 		DIRectangle clipBounds2 = clipBounds == null ? null : new DIRectangle(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
84
-		SwingCanvas canvas = new SwingCanvas((Graphics2D) g, context, clipBounds2);
85
-		component.paint(canvas);
89
+		Graphics2D g2d = (Graphics2D) g;
90
+		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
91
+		g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
92
+		surface.paint(g2d, clipBounds2);
93
+		
94
+		System.out.println("Paint in " + (System.currentTimeMillis() - start) + " ms, bounds: " + clipBounds.toString());
86
 	}
95
 	}
87
 
96
 
88
 	@Override
97
 	@Override
89
 	public void componentResized(ComponentEvent e) {
98
 	public void componentResized(ComponentEvent e) {
99
+		if (firstPaint)
100
+			return;
101
+		
90
 		component.setBounds(new DIRectangle(0, 0,
102
 		component.setBounds(new DIRectangle(0, 0,
91
 				e.getComponent().getWidth(),
103
 				e.getComponent().getWidth(),
92
 				e.getComponent().getHeight()));
104
 				e.getComponent().getHeight()));

+ 0
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingShadowedPath.java View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save