瀏覽代碼

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

kindlich 6 年之前
父節點
當前提交
b441aaf496
沒有發現已知的金鑰在資料庫的簽署中
共有 91 個檔案被更改,包括 1288 行新增426 行删除
  1. 1
    1
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionHeader.java
  2. 1
    1
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/Expression.java
  3. 3
    2
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/FunctionExpression.java
  4. 1
    1
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/scope/DefinitionScope.java
  5. 10
    7
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/DefinitionTypeID.java
  6. 8
    5
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GenericName.java
  7. 1
    1
      CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GlobalTypeRegistry.java
  8. 1
    1
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java
  9. 4
    1
      Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourcePackage.java
  10. 27
    10
      DrawableGui/src/main/java/org/openzen/drawablegui/DButton.java
  11. 6
    6
      DrawableGui/src/main/java/org/openzen/drawablegui/DButtonStyle.java
  12. 0
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIcon.java
  13. 1
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/DComponent.java
  14. 3
    4
      DrawableGui/src/main/java/org/openzen/drawablegui/DEmptyView.java
  15. 20
    18
      DrawableGui/src/main/java/org/openzen/drawablegui/DHorizontalLayout.java
  16. 39
    8
      DrawableGui/src/main/java/org/openzen/drawablegui/DInputField.java
  17. 89
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DLabel.java
  18. 30
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DLabelStyle.java
  19. 12
    11
      DrawableGui/src/main/java/org/openzen/drawablegui/DSideLayout.java
  20. 106
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltip.java
  21. 11
    4
      DrawableGui/src/main/java/org/openzen/drawablegui/DSizing.java
  22. 32
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DTooltipStyle.java
  23. 8
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DUIContext.java
  24. 22
    20
      DrawableGui/src/main/java/org/openzen/drawablegui/DVerticalLayout.java
  25. 65
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCompositeBorder.java
  26. 4
    4
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java
  27. 2
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java
  28. 0
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java
  29. 52
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DPaddedBorder.java
  30. 10
    10
      DrawableGui/src/main/java/org/openzen/drawablegui/form/DForm.java
  31. 0
    5
      DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveBool.java
  32. 0
    5
      DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveObject.java
  33. 31
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveString.java
  34. 6
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveArrayList.java
  35. 0
    6
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveBool.java
  36. 0
    25
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveConcatList.java
  37. 3
    23
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveEmptyList.java
  38. 2
    10
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveList.java
  39. 0
    25
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveMappedList.java
  40. 0
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveObject.java
  41. 0
    5
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePredicateBool.java
  42. 9
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePrefixedList.java
  43. 0
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveString.java
  44. 18
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveBool.java
  45. 22
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveList.java
  46. 14
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveObject.java
  47. 14
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveString.java
  48. 1
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveBool.java
  49. 1
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveObject.java
  50. 1
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveString.java
  51. 104
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/SortedLiveList.java
  52. 8
    8
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java
  53. 7
    8
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java
  54. 0
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPaneStyle.java
  55. 3
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDialog.java
  56. 3
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingGraphicsContext.java
  57. 2
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingWindow.java
  58. 4
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeNode.java
  59. 30
    10
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeView.java
  60. 4
    0
      IDE/src/main/java/org/openzen/zenscript/ide/host/IDEPackage.java
  61. 2
    1
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalLibrary.java
  62. 3
    1
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalModule.java
  63. 47
    8
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalPackage.java
  64. 4
    4
      IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalProjectDevelopmentHost.java
  65. 4
    4
      IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectBar.java
  66. 2
    2
      IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectToolbar.java
  67. 12
    33
      IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEWindow.java
  68. 89
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/dialog/CreatePackageDialog.java
  69. 91
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/dialog/CreateSourceFileDialog.java
  70. 5
    5
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/IconButtonControl.java
  71. 4
    4
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/StatusBarView.java
  72. 9
    8
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedView.java
  73. 11
    11
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTab.java
  74. 6
    8
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTabClose.java
  75. 2
    2
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/WindowView.java
  76. 17
    8
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarSelectorButton.java
  77. 1
    1
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarStyle.java
  78. 22
    25
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarView.java
  79. 6
    6
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/WindowActionButton.java
  80. 38
    9
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/editor/SourceEditor.java
  81. 5
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/LibraryTreeNode.java
  82. 1
    5
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/ModuleTreeNode.java
  83. 28
    2
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/PackageTreeNode.java
  84. 3
    3
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/ProjectOverviewNode.java
  85. 5
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/ProjectTreeNode.java
  86. 5
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/RootTreeNode.java
  87. 5
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/SourceFileTreeNode.java
  88. 1
    1
      Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedCallArguments.java
  89. 2
    1
      Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionFunction.java
  90. 1
    1
      Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionVariable.java
  91. 1
    1
      Parser/src/main/java/org/openzen/zenscript/parser/type/IParsedType.java

+ 1
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionHeader.java 查看文件

@@ -285,7 +285,7 @@ public class FunctionHeader {
285 285
 		for (int i = 0; i < parameters.length; i++) {
286 286
 			parameters[i] = this.parameters[i].withGenericArguments(mapper);
287 287
 		}
288
-		return new FunctionHeader(null, returnType, thrownType == null ? null : thrownType.instance(mapper), parameters);
288
+		return new FunctionHeader(TypeParameter.NONE, returnType, thrownType == null ? null : thrownType.instance(mapper), parameters);
289 289
 	}
290 290
 	
291 291
 	public FunctionHeader forTypeParameterInference() {

+ 1
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/Expression.java 查看文件

@@ -56,7 +56,7 @@ public abstract class Expression implements IPartialExpression {
56 56
 				if (body == function.body)
57 57
 					return function;
58 58
 				
59
-				return new FunctionExpression(function.position, (FunctionTypeID)function.type, function.closure, body);
59
+				return new FunctionExpression(function.position, (FunctionTypeID)function.type, function.closure, function.header, body);
60 60
 			} else {
61 61
 				return expression;
62 62
 			}

+ 3
- 2
CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/FunctionExpression.java 查看文件

@@ -31,10 +31,11 @@ public class FunctionExpression extends Expression {
31 31
 			CodePosition position,
32 32
 			FunctionTypeID type,
33 33
 			LambdaClosure closure,
34
+			FunctionHeader header,
34 35
 			Statement body) {
35 36
 		super(position, type, body.thrownType);
36 37
 		
37
-		this.header = type.header;
38
+		this.header = header;
38 39
 		this.closure = closure;
39 40
 		this.body = body;
40 41
 	}
@@ -47,7 +48,7 @@ public class FunctionExpression extends Expression {
47 48
 	@Override
48 49
 	public FunctionExpression transform(ExpressionTransformer transformer) {
49 50
 		Statement tBody = body.transform(transformer, ConcatMap.empty(LoopStatement.class, LoopStatement.class));
50
-		return tBody == body ? this : new FunctionExpression(position, (FunctionTypeID)type, closure, tBody);
51
+		return tBody == body ? this : new FunctionExpression(position, (FunctionTypeID)type, closure, header, tBody);
51 52
 	}
52 53
 	
53 54
 	@Override

+ 1
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/scope/DefinitionScope.java 查看文件

@@ -47,7 +47,7 @@ public class DefinitionScope extends BaseScope {
47 47
 		this.outer = outer;
48 48
 		this.definition = definition;
49 49
 		
50
-		ITypeID[] genericParameterList = null;
50
+		ITypeID[] genericParameterList = ITypeID.NONE;
51 51
 		if (definition.genericParameters != null) {
52 52
 			genericParameterList = new ITypeID[definition.genericParameters.length];
53 53
 			for (int i = 0; i < definition.genericParameters.length; i++) {

+ 10
- 7
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/DefinitionTypeID.java 查看文件

@@ -26,7 +26,7 @@ public class DefinitionTypeID implements ITypeID {
26 26
 		if (definition.genericParameters != null)
27 27
 			throw new IllegalArgumentException("Definition has type arguments!");
28 28
 		
29
-		return new DefinitionTypeID(definition, null);
29
+		return new DefinitionTypeID(definition, ITypeID.NONE);
30 30
 	}
31 31
 	
32 32
 	private static final OuterTypeEntry[] NO_OUTER_ENTRIES = new OuterTypeEntry[0];
@@ -44,6 +44,9 @@ public class DefinitionTypeID implements ITypeID {
44 44
 	
45 45
 	// For inner classes of generic outer classes
46 46
 	public DefinitionTypeID(HighLevelDefinition definition, ITypeID[] typeParameters, Map<TypeParameter, ITypeID> outerTypeParameters) {
47
+		if (typeParameters == null)
48
+			throw new NullPointerException("typeParameters cannot be null");
49
+		
47 50
 		this.definition = definition;
48 51
 		this.typeParameters = typeParameters;
49 52
 		this.outerTypeParameters = outerTypeParameters;
@@ -63,7 +66,7 @@ public class DefinitionTypeID implements ITypeID {
63 66
 	}
64 67
 	
65 68
 	public boolean hasTypeParameters() {
66
-		return typeParameters != null && typeParameters.length > 0;
69
+		return typeParameters.length > 0;
67 70
 	}
68 71
 	
69 72
 	public void init(GlobalTypeRegistry registry) {
@@ -81,7 +84,7 @@ public class DefinitionTypeID implements ITypeID {
81 84
 	// To be used exclusively by StaticDefinitionTypeID
82 85
 	protected DefinitionTypeID(HighLevelDefinition definition) {
83 86
 		this.definition = definition;
84
-		this.typeParameters = null;
87
+		this.typeParameters = ITypeID.NONE;
85 88
 		this.superType = definition.superType;
86 89
 		this.outerTypeParameters = Collections.emptyMap();
87 90
 		this.outerTypeEntries = NO_OUTER_ENTRIES;
@@ -92,8 +95,8 @@ public class DefinitionTypeID implements ITypeID {
92 95
 		if (!hasTypeParameters() && outerTypeParameters.isEmpty())
93 96
 			return this;
94 97
 		
95
-		ITypeID[] instancedArguments = null;
96
-		if (typeParameters != null) {
98
+		ITypeID[] instancedArguments = ITypeID.NONE;
99
+		if (hasTypeParameters()) {
97 100
 			instancedArguments = new ITypeID[typeParameters.length];
98 101
 			for (int i = 0; i < typeParameters.length; i++) {
99 102
 				// TODO: why was this line written like this?
@@ -160,7 +163,7 @@ public class DefinitionTypeID implements ITypeID {
160 163
 	
161 164
 	@Override
162 165
 	public boolean hasInferenceBlockingTypeParameters(TypeParameter[] parameters) {
163
-		if (typeParameters != null) {
166
+		if (hasTypeParameters()) {
164 167
 			for (ITypeID typeParameter : typeParameters)
165 168
 				if (typeParameter.hasInferenceBlockingTypeParameters(parameters))
166 169
 					return true;
@@ -197,7 +200,7 @@ public class DefinitionTypeID implements ITypeID {
197 200
 	
198 201
 	@Override
199 202
 	public String toString() {
200
-		if (typeParameters == null) {
203
+		if (!hasTypeParameters()) {
201 204
 			return definition.name;
202 205
 		} else {
203 206
 			StringBuilder result = new StringBuilder();

+ 8
- 5
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GenericName.java 查看文件

@@ -14,30 +14,33 @@ public class GenericName {
14 14
 	public final ITypeID[] arguments;
15 15
 	
16 16
 	public GenericName(String name) {
17
-		this(name, null);
17
+		this(name, ITypeID.NONE);
18 18
 	}
19 19
 	
20 20
 	public GenericName(String name, ITypeID[] arguments) {
21
+		if (arguments == null)
22
+			throw new NullPointerException("Arguments cannot be null");
23
+		
21 24
 		this.name = name;
22 25
 		this.arguments = arguments;
23 26
 	}
24 27
 	
25 28
 	public int getNumberOfArguments() {
26
-		return arguments == null ? 0 : arguments.length;
29
+		return arguments.length;
27 30
 	}
28 31
 	
29 32
 	public boolean hasArguments() {
30
-		return arguments != null && arguments.length > 0;
33
+		return arguments.length > 0;
31 34
 	}
32 35
 	
33 36
 	public boolean hasNoArguments() {
34
-		return arguments == null || arguments.length == 0;
37
+		return arguments.length == 0;
35 38
 	}
36 39
 	
37 40
 	@Override
38 41
 	public String toString() {
39 42
 		StringBuilder result = new StringBuilder(name);
40
-		if (arguments != null) {
43
+		if (hasArguments()) {
41 44
 			result.append("<");
42 45
 			for (int i = 0; i < arguments.length; i++) {
43 46
 				if (i > 0)

+ 1
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/GlobalTypeRegistry.java 查看文件

@@ -120,7 +120,7 @@ public class GlobalTypeRegistry {
120 120
 	
121 121
 	public DefinitionTypeID getForDefinition(HighLevelDefinition definition, ITypeID[] typeParameters, Map<TypeParameter, ITypeID> outerInstance) {
122 122
 		DefinitionTypeID id;
123
-		if ((definition instanceof FunctionDefinition) || (definition.genericParameters == null && typeParameters == null && outerInstance.isEmpty())) {
123
+		if ((definition instanceof FunctionDefinition) || (definition.genericParameters == null && typeParameters.length == 0 && outerInstance.isEmpty())) {
124 124
 			// make it a static one
125 125
 			id = new StaticDefinitionTypeID(definition);
126 126
 		} else {

+ 1
- 1
Constructor/src/main/java/org/openzen/zenscript/constructor/module/DirectoryModuleLoader.java 查看文件

@@ -106,7 +106,7 @@ public class DirectoryModuleLoader implements ModuleReference {
106 106
 	}
107 107
 	
108 108
 	private SourcePackage loadPackage(String name, File directory) {
109
-		SourcePackage pkg = new SourcePackage(name);
109
+		SourcePackage pkg = new SourcePackage(directory, name);
110 110
 		
111 111
 		for (File file : directory.listFiles()) {
112 112
 			if (file.isDirectory()) {

+ 4
- 1
Constructor/src/main/java/org/openzen/zenscript/constructor/module/SourcePackage.java 查看文件

@@ -5,6 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.constructor.module;
7 7
 
8
+import java.io.File;
8 9
 import java.util.HashMap;
9 10
 import java.util.Map;
10 11
 
@@ -13,11 +14,13 @@ import java.util.Map;
13 14
  * @author Hoofdgebruiker
14 15
  */
15 16
 public class SourcePackage {
17
+	public final File directory;
16 18
 	public final String name;
17 19
 	public final Map<String, SourcePackage> subPackages = new HashMap<>();
18 20
 	public final Map<String, SourceFile> sourceFiles = new HashMap<>();
19 21
 	
20
-	public SourcePackage(String name) {
22
+	public SourcePackage(File directory, String name) {
23
+		this.directory = directory;
21 24
 		this.name = name;
22 25
 	}
23 26
 	

+ 27
- 10
DrawableGui/src/main/java/org/openzen/drawablegui/DButton.java 查看文件

@@ -8,7 +8,8 @@ package org.openzen.drawablegui;
8 8
 import org.openzen.drawablegui.live.LiveBool;
9 9
 import org.openzen.drawablegui.live.LiveObject;
10 10
 import org.openzen.drawablegui.live.LiveString;
11
-import org.openzen.drawablegui.live.SimpleLiveObject;
11
+import org.openzen.drawablegui.live.MutableLiveObject;
12
+import org.openzen.drawablegui.style.DShadow;
12 13
 import org.openzen.drawablegui.style.DStyleClass;
13 14
 import org.openzen.drawablegui.style.DStylePath;
14 15
 
@@ -19,8 +20,9 @@ import org.openzen.drawablegui.style.DStylePath;
19 20
 public class DButton implements DComponent {
20 21
 	private final DStyleClass styleClass;
21 22
 	private final LiveString label;
22
-	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
23
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
23 24
 	private final LiveBool disabled;
25
+	private final Runnable action;
24 26
 	
25 27
 	private DUIContext context;
26 28
 	private DIRectangle bounds;
@@ -31,10 +33,11 @@ public class DButton implements DComponent {
31 33
 	private boolean hovering = false;
32 34
 	private boolean pressing = false;
33 35
 	
34
-	public DButton(DStyleClass styleClass, LiveString label, LiveBool disabled) {
36
+	public DButton(DStyleClass styleClass, LiveString label, LiveBool disabled, Runnable action) {
35 37
 		this.styleClass = styleClass;
36 38
 		this.label = label;
37 39
 		this.disabled = disabled;
40
+		this.action = action;
38 41
 	}
39 42
 
40 43
 	@Override
@@ -44,11 +47,15 @@ public class DButton implements DComponent {
44 47
 		DStylePath path = parent.getChild("Button", styleClass);
45 48
 		this.style = new DButtonStyle(context.getStylesheets().get(context, path));
46 49
 		fontMetrics = context.getFontMetrics(style.font);
50
+		
51
+		sizing.setValue(new DSizing(
52
+				style.paddingLeft + style.paddingRight + fontMetrics.getWidth(label.getValue()),
53
+				style.paddingTop + style.paddingBottom + fontMetrics.getAscent() + fontMetrics.getDescent()));
47 54
 	}
48 55
 
49 56
 	@Override
50
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
51
-		return dimensionPreferences;
57
+	public LiveObject<DSizing> getSizing() {
58
+		return sizing;
52 59
 	}
53 60
 
54 61
 	@Override
@@ -69,14 +76,24 @@ public class DButton implements DComponent {
69 76
 	@Override
70 77
 	public void paint(DCanvas canvas) {
71 78
 		int backgroundColor = style.backgroundColorNormal;
72
-		if (hovering)
79
+		DShadow shadow = style.shadowNormal;
80
+		if (hovering) {
73 81
 			backgroundColor = style.backgroundColorHover;
74
-		if (pressing)
82
+			shadow = style.shadowNormal;
83
+		}
84
+		if (pressing) {
75 85
 			backgroundColor = style.backgroundColorPress;
76
-		if (disabled.getValue())
86
+			shadow = style.shadowPress;
87
+		}
88
+		if (disabled.getValue()) {
77 89
 			backgroundColor = style.backgroundColorDisabled;
90
+			shadow = style.shadowDisabled;
91
+		}
78 92
 		
79
-		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, backgroundColor);
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());
80 97
 	}
81 98
 
82 99
 	@Override
@@ -108,7 +125,7 @@ public class DButton implements DComponent {
108 125
 		pressing = false;
109 126
 		
110 127
 		if (!disabled.getValue()) {
111
-			// TODO
128
+			action.run();
112 129
 		}
113 130
 		
114 131
 		repaint();

+ 6
- 6
DrawableGui/src/main/java/org/openzen/drawablegui/DButtonStyle.java 查看文件

@@ -35,8 +35,8 @@ public class DButtonStyle {
35 35
 	public DButtonStyle(DStyleDefinition style) {
36 36
 		this.paddingTop = style.getDimension("paddingTop", new DDpDimension(4));
37 37
 		this.paddingBottom = style.getDimension("paddingBottom", new DDpDimension(4));
38
-		this.paddingLeft = style.getDimension("paddingLeft", new DDpDimension(4));
39
-		this.paddingRight = style.getDimension("paddingRight", new DDpDimension(4));
38
+		this.paddingLeft = style.getDimension("paddingLeft", new DDpDimension(8));
39
+		this.paddingRight = style.getDimension("paddingRight", new DDpDimension(8));
40 40
 		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, (int)(14 * context.getTextScale())));
41 41
 		textColor = style.getColor("textColor", 0xFF000000);
42 42
 		textColorDisabled = style.getColor("textColorDisabled", 0xFF888888);
@@ -46,9 +46,9 @@ public class DButtonStyle {
46 46
 		backgroundColorPress = style.getColor("backgroundColorPress", 0xFFE5EFF8);
47 47
 		backgroundColorDisabled = style.getColor("backgroundColorDisabled", 0xFFE5EFF8);
48 48
 		
49
-		shadowNormal = style.getShadow("shadowNormal", context -> new DShadow(0xFF888888, 0, 0.5f * context.getScale(), 3 * context.getScale()));
50
-		shadowHover = style.getShadow("shadowHover", context -> new DShadow(0xFF888888, 0, 0.5f * context.getScale(), 3 * context.getScale()));
51
-		shadowPress = style.getShadow("shadowPress", context -> new DShadow(0xFF888888, 0, 0.5f * context.getScale(), 3 * context.getScale()));
52
-		shadowDisabled = style.getShadow("shadowDisabled", context -> new DShadow(0xFF888888, 0, 0.5f * context.getScale(), 3 * context.getScale()));
49
+		shadowNormal = style.getShadow("shadowNormal", context -> new DShadow(0xFF888888, 0, 1f * context.getScale(), 4 * context.getScale()));
50
+		shadowHover = style.getShadow("shadowHover", context -> new DShadow(0xFF888888, 0, 1f * context.getScale(), 4 * context.getScale()));
51
+		shadowPress = style.getShadow("shadowPress", context -> new DShadow(0xFF888888, 0, 1f * context.getScale(), 3 * context.getScale()));
52
+		shadowDisabled = style.getShadow("shadowDisabled", context -> new DShadow(0xFF888888, 0, 1f * context.getScale(), 3 * context.getScale()));
53 53
 	}
54 54
 }

+ 0
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIcon.java 查看文件

@@ -5,9 +5,6 @@
5 5
  */
6 6
 package org.openzen.drawablegui;
7 7
 
8
-import org.openzen.drawablegui.DCanvas;
9
-import org.openzen.drawablegui.DTransform2D;
10
-
11 8
 /**
12 9
  *
13 10
  * @author Hoofdgebruiker

+ 1
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/DComponent.java 查看文件

@@ -16,7 +16,7 @@ import org.openzen.drawablegui.style.DStylePath;
16 16
 public interface DComponent extends Closeable {
17 17
 	void setContext(DStylePath parent, DUIContext context);
18 18
 	
19
-	LiveObject<DDimensionPreferences> getDimensionPreferences();
19
+	LiveObject<DSizing> getSizing();
20 20
 	
21 21
 	DIRectangle getBounds();
22 22
 	

+ 3
- 4
DrawableGui/src/main/java/org/openzen/drawablegui/DEmptyView.java 查看文件

@@ -16,8 +16,7 @@ import org.openzen.drawablegui.style.DStylePath;
16 16
 public class DEmptyView implements DComponent {
17 17
 	public static final DEmptyView INSTANCE = new DEmptyView();
18 18
 	
19
-	private static final LiveObject<DDimensionPreferences> DIMENSION = new ImmutableLiveObject(new DDimensionPreferences(0, 0));
20
-	private static final DIRectangle NO_BOUNDS = new DIRectangle(0, 0, 0, 0);
19
+	private static final LiveObject<DSizing> DIMENSION = new ImmutableLiveObject(DSizing.EMPTY);
21 20
 	
22 21
 	private DEmptyView() {}
23 22
 
@@ -27,13 +26,13 @@ public class DEmptyView implements DComponent {
27 26
 	}
28 27
 	
29 28
 	@Override
30
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
29
+	public LiveObject<DSizing> getSizing() {
31 30
 		return DIMENSION;
32 31
 	}
33 32
 	
34 33
 	@Override
35 34
 	public DIRectangle getBounds() {
36
-		return NO_BOUNDS;
35
+		return DIRectangle.EMPTY;
37 36
 	}
38 37
 
39 38
 	@Override

+ 20
- 18
DrawableGui/src/main/java/org/openzen/drawablegui/DHorizontalLayout.java 查看文件

@@ -9,6 +9,7 @@ import java.util.function.Consumer;
9 9
 import java.util.function.Predicate;
10 10
 import org.openzen.drawablegui.listeners.ListenerHandle;
11 11
 import org.openzen.drawablegui.live.LiveObject;
12
+import org.openzen.drawablegui.live.MutableLiveObject;
12 13
 import org.openzen.drawablegui.live.SimpleLiveObject;
13 14
 import org.openzen.drawablegui.style.DStyleClass;
14 15
 import org.openzen.drawablegui.style.DStylePath;
@@ -21,8 +22,8 @@ public class DHorizontalLayout extends BaseComponentGroup {
21 22
 	private final DStyleClass styleClass;
22 23
 	private final Alignment alignment;
23 24
 	private final Element[] components;
24
-	private final ListenerHandle<LiveObject.Listener<DDimensionPreferences>>[] componentSizeListeners;
25
-	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
25
+	private final ListenerHandle<LiveObject.Listener<DSizing>>[] componentSizeListeners;
26
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
26 27
 	
27 28
 	private DUIContext context;
28 29
 	private DHorizontalLayoutStyle style;
@@ -40,7 +41,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
40 41
 		totalShrink = 0;
41 42
 		
42 43
 		for (int i = 0; i < componentSizeListeners.length; i++) {
43
-			componentSizeListeners[i] = components[i].component.getDimensionPreferences().addListener((oldValue, newValue) -> updateDimensionPreferences());
44
+			componentSizeListeners[i] = components[i].component.getSizing().addListener((oldValue, newValue) -> updateDimensionPreferences());
44 45
 			
45 46
 			totalGrow += components[i].grow;
46 47
 			totalShrink += components[i].shrink;
@@ -76,8 +77,8 @@ public class DHorizontalLayout extends BaseComponentGroup {
76 77
 	}
77 78
 
78 79
 	@Override
79
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
80
-		return dimensionPreferences;
80
+	public LiveObject<DSizing> getSizing() {
81
+		return sizing;
81 82
 	}
82 83
 
83 84
 	@Override
@@ -93,6 +94,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
93 94
 	@Override
94 95
 	public void setBounds(DIRectangle bounds) {
95 96
 		this.bounds = bounds;
97
+		layout();
96 98
 	}
97 99
 
98 100
 	@Override
@@ -146,7 +148,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
146 148
 		if (bounds == null || context == null)
147 149
 			return;
148 150
 		
149
-		DDimensionPreferences myPreferences = dimensionPreferences.getValue();
151
+		DSizing myPreferences = sizing.getValue();
150 152
 		if (bounds.width < myPreferences.preferredWidth) {
151 153
 			layoutShrinked();
152 154
 		} else {
@@ -155,7 +157,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
155 157
 	}
156 158
 	
157 159
 	private void layoutShrinked() {
158
-		DDimensionPreferences myPreferences = dimensionPreferences.getValue();
160
+		DSizing myPreferences = sizing.getValue();
159 161
 		if (totalShrink == 0) {
160 162
 			// now what?
161 163
 			// shrink proportionally, we have to shrink...
@@ -164,7 +166,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
164 166
 			
165 167
 			for (int i = 0; i < components.length; i++) {
166 168
 				Element element = components[i];
167
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
169
+				DSizing preferences = element.component.getSizing().getValue();
168 170
 				int newX = x + preferences.preferredWidth;
169 171
 				float idealUnspacedX = newX * scale;
170 172
 				int idealX = (int)(idealUnspacedX + 0.5f + i * style.spacing);
@@ -176,7 +178,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
176 178
 			float deltaScaled = delta / totalShrink;
177 179
 			int x = 0;
178 180
 			for (Element element : components) {
179
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
181
+				DSizing preferences = element.component.getSizing().getValue();
180 182
 				float scaledSize = preferences.preferredWidth + deltaScaled * element.shrink;
181 183
 				float idealUnspacedX = x + scaledSize;
182 184
 				int newX = (int)(idealUnspacedX + 0.5f);
@@ -188,23 +190,23 @@ public class DHorizontalLayout extends BaseComponentGroup {
188 190
 	
189 191
 	private void layoutGrown() {
190 192
 		// resize according to grow values
191
-		DDimensionPreferences myPreferences = dimensionPreferences.getValue();
193
+		DSizing myPreferences = sizing.getValue();
192 194
 		
193 195
 		if (totalGrow == 0) {
194 196
 			int deltaX = (int)(myPreferences.preferredWidth - bounds.width);
195 197
 			int x = bounds.x + (int)(deltaX * alignment.align);
196 198
 			for (Element element : components) {
197
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
199
+				DSizing preferences = element.component.getSizing().getValue();
198 200
 				int newX = x + preferences.preferredWidth;
199 201
 				layout(element, x, newX - x);
200
-				x = newX;
202
+				x = newX + style.spacing;
201 203
 			}
202 204
 		} else {
203 205
 			int delta = bounds.width - myPreferences.preferredWidth;
204 206
 			float deltaScaled = delta / totalGrow;
205 207
 			int x = 0;
206 208
 			for (Element element : components) {
207
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
209
+				DSizing preferences = element.component.getSizing().getValue();
208 210
 				float scaledSize = preferences.preferredWidth + deltaScaled * element.grow;
209 211
 				float idealUnspacedX = x + scaledSize;
210 212
 				int newX = (int)(idealUnspacedX + 0.5f);
@@ -215,7 +217,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
215 217
 	}
216 218
 	
217 219
 	private void layout(Element element, int x, int width) {
218
-		DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
220
+		DSizing preferences = element.component.getSizing().getValue();
219 221
 		int height;
220 222
 		int y;
221 223
 		switch (element.alignment) {
@@ -237,7 +239,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
237 239
 				y = bounds.y + style.paddingTop;
238 240
 				break;
239 241
 		}
240
-		element.component.setBounds(new DIRectangle(bounds.x + x, y, width, height));
242
+		element.component.setBounds(new DIRectangle(x, y, width, height));
241 243
 	}
242 244
 	
243 245
 	private void updateDimensionPreferences() {
@@ -248,7 +250,7 @@ public class DHorizontalLayout extends BaseComponentGroup {
248 250
 		int maximumWidth = -style.spacing;
249 251
 		int maximumHeight = Integer.MAX_VALUE;
250 252
 		for (Element element : components) {
251
-			DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
253
+			DSizing preferences = element.component.getSizing().getValue();
252 254
 			preferredWidth += preferences.preferredWidth + style.spacing;
253 255
 			preferredHeight = Math.max(preferredHeight, preferences.preferredHeight);
254 256
 			
@@ -259,13 +261,13 @@ public class DHorizontalLayout extends BaseComponentGroup {
259 261
 			maximumHeight = Math.min(maximumHeight, preferences.maximumHeight);
260 262
 		}
261 263
 		
262
-		DDimensionPreferences preferences = new DDimensionPreferences(
264
+		DSizing preferences = new DSizing(
263 265
 				minimumWidth + style.paddingLeft + style.paddingRight,
264 266
 				minimumHeight + style.paddingTop + style.paddingBottom,
265 267
 				preferredWidth + style.paddingLeft + style.paddingRight,
266 268
 				preferredHeight + style.paddingTop + style.paddingBottom,
267 269
 				maximumWidth + style.paddingLeft + style.paddingRight,
268 270
 				maximumHeight + style.paddingTop + style.paddingBottom);
269
-		dimensionPreferences.setValue(preferences);
271
+		sizing.setValue(preferences);
270 272
 	}
271 273
 }

+ 39
- 8
DrawableGui/src/main/java/org/openzen/drawablegui/DInputField.java 查看文件

@@ -8,7 +8,8 @@ package org.openzen.drawablegui;
8 8
 import org.openzen.drawablegui.listeners.ListenerHandle;
9 9
 import org.openzen.drawablegui.live.LiveObject;
10 10
 import org.openzen.drawablegui.live.LiveString;
11
-import org.openzen.drawablegui.live.SimpleLiveObject;
11
+import org.openzen.drawablegui.live.MutableLiveObject;
12
+import org.openzen.drawablegui.live.MutableLiveString;
12 13
 import org.openzen.drawablegui.style.DDimension;
13 14
 import org.openzen.drawablegui.style.DStyleClass;
14 15
 import org.openzen.drawablegui.style.DStylePath;
@@ -18,11 +19,11 @@ import org.openzen.drawablegui.style.DStylePath;
18 19
  * @author Hoofdgebruiker
19 20
  */
20 21
 public class DInputField implements DComponent {
21
-	public final LiveString value;
22
+	public final MutableLiveString value;
22 23
 	private final ListenerHandle<LiveString.Listener> valueListener;
23 24
 	
24 25
 	private final DStyleClass styleClass;
25
-	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
26
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
26 27
 	private DIRectangle bounds = DIRectangle.EMPTY;
27 28
 	private final DDimension preferredWidth;
28 29
 	
@@ -32,10 +33,13 @@ public class DInputField implements DComponent {
32 33
 	private int cursorFrom = -1;
33 34
 	private int cursorTo = -1;
34 35
 	
36
+	private Runnable onEnter = null;
37
+	private Runnable onEscape = null;
38
+	
35 39
 	private boolean cursorBlink = true;
36 40
 	private DTimerHandle blinkTimer;
37 41
 	
38
-	public DInputField(DStyleClass styleClass, LiveString value, DDimension preferredWidth) {
42
+	public DInputField(DStyleClass styleClass, MutableLiveString value, DDimension preferredWidth) {
39 43
 		this.styleClass = styleClass;
40 44
 		this.value = value;
41 45
 		this.preferredWidth = preferredWidth;
@@ -45,6 +49,14 @@ public class DInputField implements DComponent {
45 49
 		cursorTo = value.getValue().length();
46 50
 	}
47 51
 	
52
+	public void setOnEnter(Runnable onEnter) {
53
+		this.onEnter = onEnter;
54
+	}
55
+	
56
+	public void setOnEscape(Runnable onEscape) {
57
+		this.onEscape = onEscape;
58
+	}
59
+	
48 60
 	@Override
49 61
 	public void close() {
50 62
 		valueListener.close();
@@ -58,7 +70,7 @@ public class DInputField implements DComponent {
58 70
 		DStylePath path = parent.getChild("input", styleClass);
59 71
 		style = new DInputFieldStyle(context.getStylesheets().get(context, path));
60 72
 		fontMetrics = context.getFontMetrics(style.font);
61
-		dimensionPreferences.setValue(new DDimensionPreferences(
73
+		sizing.setValue(new DSizing(
62 74
 				preferredWidth.evalInt(context) + style.paddingLeft + style.paddingRight + 2 * style.borderWidth,
63 75
 				fontMetrics.getAscent() + fontMetrics.getDescent() + style.paddingTop + style.paddingBottom + 2 * style.borderWidth));
64 76
 		
@@ -73,8 +85,8 @@ public class DInputField implements DComponent {
73 85
 	}
74 86
 
75 87
 	@Override
76
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
77
-		return dimensionPreferences;
88
+	public LiveObject<DSizing> getSizing() {
89
+		return sizing;
78 90
 	}
79 91
 
80 92
 	@Override
@@ -126,6 +138,16 @@ public class DInputField implements DComponent {
126 138
 		}
127 139
 	}
128 140
 	
141
+	@Override
142
+	public void onMouseEnter(DMouseEvent e) {
143
+		context.setCursor(DUIContext.Cursor.TEXT);
144
+	}
145
+	
146
+	@Override
147
+	public void onMouseExit(DMouseEvent e) {
148
+		context.setCursor(DUIContext.Cursor.NORMAL);
149
+	}
150
+	
129 151
 	@Override
130 152
 	public void onMouseClick(DMouseEvent e) {
131 153
 		context.getWindow().focus(this);
@@ -160,6 +182,9 @@ public class DInputField implements DComponent {
160 182
 			case ENTER:
161 183
 				enter();
162 184
 				break;
185
+			case ESCAPE:
186
+				escape();
187
+				break;
163 188
 			default:
164 189
 				if (e.character == DKeyEvent.CHAR_UNDEFINED)
165 190
 					return;
@@ -218,6 +243,12 @@ public class DInputField implements DComponent {
218 243
 	}
219 244
 	
220 245
 	private void enter() {
221
-		
246
+		if (onEnter != null)
247
+			onEnter.run();
248
+	}
249
+	
250
+	private void escape() {
251
+		if (onEscape != null)
252
+			onEscape.run();
222 253
 	}
223 254
 }

+ 89
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DLabel.java 查看文件

@@ -0,0 +1,89 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import org.openzen.drawablegui.listeners.ListenerHandle;
9
+import org.openzen.drawablegui.live.LiveObject;
10
+import org.openzen.drawablegui.live.LiveString;
11
+import org.openzen.drawablegui.live.MutableLiveObject;
12
+import org.openzen.drawablegui.style.DStyleClass;
13
+import org.openzen.drawablegui.style.DStylePath;
14
+
15
+/**
16
+ *
17
+ * @author Hoofdgebruiker
18
+ */
19
+public class DLabel implements DComponent {
20
+	private final LiveString label;
21
+	private final DStyleClass styleClass;
22
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
23
+	private final ListenerHandle<LiveString.Listener> labelListener;
24
+	
25
+	private DUIContext context;
26
+	private DIRectangle bounds;
27
+	private DLabelStyle style;
28
+	private DFontMetrics fontMetrics;
29
+	
30
+	public DLabel(DStyleClass styleClass, LiveString label) {
31
+		this.styleClass = styleClass;
32
+		this.label = label;
33
+		
34
+		labelListener = label.addListener(this::onLabelChanged);
35
+	}
36
+
37
+	@Override
38
+	public void setContext(DStylePath parent, DUIContext context) {
39
+		this.context = context;
40
+		
41
+		DStylePath path = parent.getChild("label", styleClass);
42
+		style = new DLabelStyle(context.getStylesheets().get(context, path));
43
+		
44
+		fontMetrics = context.getFontMetrics(style.font);
45
+		calculateDimension();
46
+	}
47
+
48
+	@Override
49
+	public LiveObject<DSizing> getSizing() {
50
+		return sizing;
51
+	}
52
+
53
+	@Override
54
+	public DIRectangle getBounds() {
55
+		return bounds;
56
+	}
57
+
58
+	@Override
59
+	public int getBaselineY() {
60
+		return style.border.getPaddingTop() + fontMetrics.getAscent();
61
+	}
62
+
63
+	@Override
64
+	public void setBounds(DIRectangle bounds) {
65
+		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());
72
+	}
73
+
74
+	@Override
75
+	public void close() {
76
+		labelListener.close();
77
+	}
78
+	
79
+	private void onLabelChanged(String oldValue, String newValue) {
80
+		calculateDimension();
81
+		context.repaint(bounds);
82
+	}
83
+	
84
+	private void calculateDimension() {
85
+		sizing.setValue(new DSizing(
86
+			style.border.getPaddingLeft() + fontMetrics.getWidth(label.getValue()) + style.border.getPaddingRight(),
87
+			style.border.getPaddingTop() + fontMetrics.getAscent() + fontMetrics.getDescent() + style.border.getPaddingTop()));
88
+	}
89
+}

+ 30
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DLabelStyle.java 查看文件

@@ -0,0 +1,30 @@
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.border.DBorder;
9
+import org.openzen.drawablegui.border.DPaddedBorder;
10
+import org.openzen.drawablegui.style.DStyleDefinition;
11
+
12
+/**
13
+ *
14
+ * @author Hoofdgebruiker
15
+ */
16
+public class DLabelStyle {
17
+	public final DBorder border;
18
+	public final DFont font;
19
+	public final int color;
20
+	
21
+	public DLabelStyle(DStyleDefinition style) {
22
+		border = style.getBorder("border", context -> new DPaddedBorder(
23
+				(int)(4 * context.getScale()),
24
+				(int)(4 * context.getScale()),
25
+				(int)(4 * context.getScale()),
26
+				(int)(4 * context.getScale())));
27
+		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, (int)(14 * context.getTextScale())));
28
+		color = style.getColor("color", 0xFF000000);
29
+	}
30
+}

+ 12
- 11
DrawableGui/src/main/java/org/openzen/drawablegui/DSideLayout.java 查看文件

@@ -12,6 +12,7 @@ import java.util.function.Consumer;
12 12
 import java.util.function.Predicate;
13 13
 import org.openzen.drawablegui.listeners.ListenerHandle;
14 14
 import org.openzen.drawablegui.live.LiveObject;
15
+import org.openzen.drawablegui.live.MutableLiveObject;
15 16
 import org.openzen.drawablegui.live.SimpleLiveObject;
16 17
 import org.openzen.drawablegui.style.DStyleClass;
17 18
 import org.openzen.drawablegui.style.DStylePath;
@@ -25,7 +26,7 @@ public class DSideLayout extends BaseComponentGroup {
25 26
 	
26 27
 	private DComponent main;
27 28
 	private final List<SideComponent> sides = new ArrayList<>();
28
-	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
29
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
29 30
 	
30 31
 	private DStylePath path;
31 32
 	private DUIContext context;
@@ -83,8 +84,8 @@ public class DSideLayout extends BaseComponentGroup {
83 84
 	}
84 85
 
85 86
 	@Override
86
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
87
-		return dimensionPreferences;
87
+	public LiveObject<DSizing> getSizing() {
88
+		return sizing;
88 89
 	}
89 90
 
90 91
 	@Override
@@ -97,7 +98,7 @@ public class DSideLayout extends BaseComponentGroup {
97 98
 		int bottom = bounds.y + bounds.height;
98 99
 		for (int i = sides.size() - 1; i >= 0; i--) {
99 100
 			SideComponent side = sides.get(i);
100
-			DDimensionPreferences preferences = side.component.getDimensionPreferences().getValue();
101
+			DSizing preferences = side.component.getSizing().getValue();
101 102
 			
102 103
 			switch (side.side) {
103 104
 				case TOP: {
@@ -175,7 +176,7 @@ public class DSideLayout extends BaseComponentGroup {
175 176
 	}
176 177
 	
177 178
 	private void recalculateSize() {
178
-		DDimensionPreferences mainPreferences = main.getDimensionPreferences().getValue();
179
+		DSizing mainPreferences = main.getSizing().getValue();
179 180
 		int minimumWidth = mainPreferences.minimumWidth;
180 181
 		int minimumHeight = mainPreferences.minimumHeight;
181 182
 		int preferredWidth = mainPreferences.preferredWidth;
@@ -184,7 +185,7 @@ public class DSideLayout extends BaseComponentGroup {
184 185
 		int maximumHeight = mainPreferences.maximumHeight;
185 186
 		
186 187
 		for (SideComponent side : sides) {
187
-			DDimensionPreferences sidePreferences = side.component.getDimensionPreferences().getValue();
188
+			DSizing sidePreferences = side.component.getSizing().getValue();
188 189
 			switch (side.side) {
189 190
 				case LEFT:
190 191
 				case RIGHT:
@@ -207,7 +208,7 @@ public class DSideLayout extends BaseComponentGroup {
207 208
 			}
208 209
 		}
209 210
 		
210
-		dimensionPreferences.setValue(new DDimensionPreferences(
211
+		sizing.setValue(new DSizing(
211 212
 				minimumWidth,
212 213
 				minimumHeight,
213 214
 				preferredWidth,
@@ -241,15 +242,15 @@ public class DSideLayout extends BaseComponentGroup {
241 242
 			side.close();
242 243
 	}
243 244
 	
244
-	public class SideComponent implements Closeable, LiveObject.Listener<DDimensionPreferences> {
245
+	public class SideComponent implements Closeable, LiveObject.Listener<DSizing> {
245 246
 		public final Side side;
246 247
 		public final DComponent component;
247
-		public final ListenerHandle<LiveObject.Listener<DDimensionPreferences>> listenerHandle;
248
+		public final ListenerHandle<LiveObject.Listener<DSizing>> listenerHandle;
248 249
 
249 250
 		public SideComponent(Side side, DComponent component) {
250 251
 			this.side = side;
251 252
 			this.component = component;
252
-			listenerHandle = component.getDimensionPreferences().addListener(this);
253
+			listenerHandle = component.getSizing().addListener(this);
253 254
 		}
254 255
 		
255 256
 		@Override
@@ -258,7 +259,7 @@ public class DSideLayout extends BaseComponentGroup {
258 259
 		}
259 260
 
260 261
 		@Override
261
-		public void onUpdated(DDimensionPreferences oldValue, DDimensionPreferences newValue) {
262
+		public void onUpdated(DSizing oldValue, DSizing newValue) {
262 263
 			recalculateSize();
263 264
 		}
264 265
 	}

+ 106
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltip.java 查看文件

@@ -0,0 +1,106 @@
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.listeners.ListenerHandle;
9
+import org.openzen.drawablegui.live.LiveString;
10
+import org.openzen.drawablegui.style.DStyleClass;
11
+import org.openzen.drawablegui.style.DStylePath;
12
+
13
+/**
14
+ *
15
+ * @author Hoofdgebruiker
16
+ */
17
+public class DSimpleTooltip {
18
+	private final DStyleClass styleClass;
19
+	private final LiveString tooltip;
20
+	private final ListenerHandle<LiveString.Listener> tooltipListener;
21
+	
22
+	private DUIContext context;
23
+	private DIRectangle bounds;
24
+	private DFontMetrics fontMetrics;
25
+	private DTooltipStyle style;
26
+	private boolean visible = false;
27
+	private DTimerHandle timerHandle = null;
28
+	
29
+	public DSimpleTooltip(DStyleClass styleClass, LiveString tooltip) {
30
+		this.styleClass = styleClass;
31
+		this.tooltip = tooltip;
32
+		tooltipListener = tooltip.addListener(this::onTooltipChanged);
33
+	}
34
+	
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);
45
+	}
46
+	
47
+	public void onTargetMouseEnter(DMouseEvent e) {
48
+		if (timerHandle != null)
49
+			timerHandle.close();
50
+		
51
+		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());
57
+	}
58
+	
59
+	public void onTargetMouseExit(DMouseEvent e) {
60
+		if (timerHandle != null) {
61
+			timerHandle.close();
62
+			timerHandle = null;
63
+		}
64
+		
65
+		hide();
66
+	}
67
+	
68
+	private void show() {
69
+		System.out.println("Show tooltip");
70
+		visible = true;
71
+		context.repaint(bounds);
72
+		
73
+		if (timerHandle != null) {
74
+			timerHandle.close();
75
+			timerHandle = null;
76
+		}
77
+	}
78
+	
79
+	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());
101
+	}
102
+	
103
+	public void close() {
104
+		tooltipListener.close();
105
+	}
106
+}

DrawableGui/src/main/java/org/openzen/drawablegui/DDimensionPreferences.java → DrawableGui/src/main/java/org/openzen/drawablegui/DSizing.java 查看文件

@@ -5,12 +5,19 @@
5 5
  */
6 6
 package org.openzen.drawablegui;
7 7
 
8
+import org.openzen.drawablegui.live.MutableLiveObject;
9
+import org.openzen.drawablegui.live.SimpleLiveObject;
10
+
8 11
 /**
9 12
  *
10 13
  * @author Hoofdgebruiker
11 14
  */
12
-public class DDimensionPreferences {
13
-	public static final DDimensionPreferences EMPTY = new DDimensionPreferences(0, 0);
15
+public class DSizing {
16
+	public static MutableLiveObject<DSizing> create() {
17
+		return new SimpleLiveObject<>(DSizing.EMPTY);
18
+	}
19
+	
20
+	public static final DSizing EMPTY = new DSizing(0, 0);
14 21
 	
15 22
 	public final int minimumWidth;
16 23
 	public final int minimumHeight;
@@ -19,7 +26,7 @@ public class DDimensionPreferences {
19 26
 	public final int maximumWidth;
20 27
 	public final int maximumHeight;
21 28
 	
22
-	public DDimensionPreferences(int preferredWidth, int preferredHeight) {
29
+	public DSizing(int preferredWidth, int preferredHeight) {
23 30
 		this.minimumWidth = 0;
24 31
 		this.minimumHeight = 0;
25 32
 		this.preferredWidth = preferredWidth;
@@ -28,7 +35,7 @@ public class DDimensionPreferences {
28 35
 		this.maximumHeight = 1000000;
29 36
 	}
30 37
 	
31
-	public DDimensionPreferences(int minimumWidth, int minimumHeight, int preferredWidth, int preferredHeight, int maximumWidth, int maximumHeight) {
38
+	public DSizing(int minimumWidth, int minimumHeight, int preferredWidth, int preferredHeight, int maximumWidth, int maximumHeight) {
32 39
 		this.minimumWidth = minimumWidth;
33 40
 		this.minimumHeight = minimumHeight;
34 41
 		this.preferredWidth = preferredWidth;

+ 32
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DTooltipStyle.java 查看文件

@@ -0,0 +1,32 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui;
7
+
8
+import org.openzen.drawablegui.border.DBorder;
9
+import org.openzen.drawablegui.border.DCompositeBorder;
10
+import org.openzen.drawablegui.border.DLineBorder;
11
+import org.openzen.drawablegui.border.DPaddedBorder;
12
+import org.openzen.drawablegui.style.DStyleDefinition;
13
+
14
+/**
15
+ *
16
+ * @author Hoofdgebruiker
17
+ */
18
+public class DTooltipStyle {
19
+	public final DBorder border;
20
+	public final DFont font;
21
+	public final int backgroundColor;
22
+	public final int textColor;
23
+	
24
+	public DTooltipStyle(DStyleDefinition style) {
25
+		border = style.getBorder("border", context -> new DCompositeBorder(
26
+				new DLineBorder(0xFF, 1),
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)));
29
+		backgroundColor = style.getColor("backgroundColor", 0xFFFFFFE1);
30
+		textColor = style.getColor("textColor", 0xFF000000);
31
+	}
32
+}

+ 8
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DUIContext.java 查看文件

@@ -40,6 +40,14 @@ public interface DUIContext {
40 40
 	
41 41
 	DUIWindow openView(int x, int y, DAnchor anchor, DComponent root);
42 42
 	
43
+	default int dp(float dp) {
44
+		return (int)(dp * getScale());
45
+	}
46
+	
47
+	default int sp(float sp) {
48
+		return (int)(sp * getTextScale());
49
+	}
50
+	
43 51
 	enum Cursor {
44 52
 		NORMAL,
45 53
 		HAND,

+ 22
- 20
DrawableGui/src/main/java/org/openzen/drawablegui/DVerticalLayout.java 查看文件

@@ -9,6 +9,7 @@ import java.util.function.Consumer;
9 9
 import java.util.function.Predicate;
10 10
 import org.openzen.drawablegui.listeners.ListenerHandle;
11 11
 import org.openzen.drawablegui.live.LiveObject;
12
+import org.openzen.drawablegui.live.MutableLiveObject;
12 13
 import org.openzen.drawablegui.live.SimpleLiveObject;
13 14
 import org.openzen.drawablegui.style.DStyleClass;
14 15
 import org.openzen.drawablegui.style.DStylePath;
@@ -21,8 +22,8 @@ public class DVerticalLayout extends BaseComponentGroup {
21 22
 	private final DStyleClass styleClass;
22 23
 	private final Alignment alignment;
23 24
 	private final Element[] components;
24
-	private final ListenerHandle<LiveObject.Listener<DDimensionPreferences>>[] componentSizeListeners;
25
-	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
25
+	private final ListenerHandle<LiveObject.Listener<DSizing>>[] componentSizeListeners;
26
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
26 27
 	
27 28
 	private DUIContext context;
28 29
 	private DHorizontalLayoutStyle style;
@@ -40,7 +41,7 @@ public class DVerticalLayout extends BaseComponentGroup {
40 41
 		totalShrink = 0;
41 42
 		
42 43
 		for (int i = 0; i < componentSizeListeners.length; i++) {
43
-			componentSizeListeners[i] = components[i].component.getDimensionPreferences().addListener((oldValue, newValue) -> updateDimensionPreferences());
44
+			componentSizeListeners[i] = components[i].component.getSizing().addListener((oldValue, newValue) -> updateDimensionPreferences());
44 45
 			
45 46
 			totalGrow += components[i].grow;
46 47
 			totalShrink += components[i].shrink;
@@ -76,8 +77,8 @@ public class DVerticalLayout extends BaseComponentGroup {
76 77
 	}
77 78
 
78 79
 	@Override
79
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
80
-		return dimensionPreferences;
80
+	public LiveObject<DSizing> getSizing() {
81
+		return sizing;
81 82
 	}
82 83
 
83 84
 	@Override
@@ -93,6 +94,7 @@ public class DVerticalLayout extends BaseComponentGroup {
93 94
 	@Override
94 95
 	public void setBounds(DIRectangle bounds) {
95 96
 		this.bounds = bounds;
97
+		layout();
96 98
 	}
97 99
 
98 100
 	@Override
@@ -104,8 +106,8 @@ public class DVerticalLayout extends BaseComponentGroup {
104 106
 
105 107
 	@Override
106 108
 	public void close() {
107
-		for (int i = 0; i < componentSizeListeners.length; i++) {
108
-			componentSizeListeners[i].close();
109
+		for (ListenerHandle<LiveObject.Listener<DSizing>> listener : componentSizeListeners) {
110
+			listener.close();
109 111
 		}
110 112
 	}
111 113
 	
@@ -146,7 +148,7 @@ public class DVerticalLayout extends BaseComponentGroup {
146 148
 		if (bounds == null || context == null)
147 149
 			return;
148 150
 		
149
-		DDimensionPreferences myPreferences = dimensionPreferences.getValue();
151
+		DSizing myPreferences = sizing.getValue();
150 152
 		if (bounds.height < myPreferences.preferredHeight) {
151 153
 			layoutShrinked();
152 154
 		} else {
@@ -155,7 +157,7 @@ public class DVerticalLayout extends BaseComponentGroup {
155 157
 	}
156 158
 	
157 159
 	private void layoutShrinked() {
158
-		DDimensionPreferences myPreferences = dimensionPreferences.getValue();
160
+		DSizing myPreferences = sizing.getValue();
159 161
 		if (totalShrink == 0) {
160 162
 			// now what?
161 163
 			// shrink proportionally, we have to shrink...
@@ -164,7 +166,7 @@ public class DVerticalLayout extends BaseComponentGroup {
164 166
 			
165 167
 			for (int i = 0; i < components.length; i++) {
166 168
 				Element element = components[i];
167
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
169
+				DSizing preferences = element.component.getSizing().getValue();
168 170
 				int newY = y + preferences.preferredHeight;
169 171
 				float idealUnspacedY = newY * scale;
170 172
 				int idealY = (int)(idealUnspacedY + 0.5f + i * style.spacing);
@@ -176,7 +178,7 @@ public class DVerticalLayout extends BaseComponentGroup {
176 178
 			float deltaScaled = delta / totalShrink;
177 179
 			int y = bounds.y;
178 180
 			for (Element element : components) {
179
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
181
+				DSizing preferences = element.component.getSizing().getValue();
180 182
 				float scaledSize = preferences.preferredHeight + deltaScaled * element.shrink;
181 183
 				float idealUnspacedY = y + scaledSize;
182 184
 				int newY = (int)(idealUnspacedY + 0.5f);
@@ -188,13 +190,13 @@ public class DVerticalLayout extends BaseComponentGroup {
188 190
 	
189 191
 	private void layoutGrown() {
190 192
 		// resize according to grow values
191
-		DDimensionPreferences myPreferences = dimensionPreferences.getValue();
193
+		DSizing myPreferences = sizing.getValue();
192 194
 		
193 195
 		if (totalGrow == 0) {
194 196
 			int deltaY = (int)(myPreferences.preferredHeight - bounds.height);
195 197
 			int y = bounds.y + (int)(deltaY * alignment.align);
196 198
 			for (Element element : components) {
197
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
199
+				DSizing preferences = element.component.getSizing().getValue();
198 200
 				int newY = y + preferences.preferredHeight;
199 201
 				layout(element, y, newY - y);
200 202
 				y = newY;
@@ -204,10 +206,10 @@ public class DVerticalLayout extends BaseComponentGroup {
204 206
 			float deltaScaled = delta / totalGrow;
205 207
 			int y = bounds.y;
206 208
 			for (Element element : components) {
207
-				DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
209
+				DSizing preferences = element.component.getSizing().getValue();
208 210
 				float scaledSize = preferences.preferredHeight + deltaScaled * element.grow;
209
-				float idealUnspacedX = y + scaledSize;
210
-				int newY = (int)(idealUnspacedX + 0.5f);
211
+				float idealUnspacedY = y + scaledSize;
212
+				int newY = (int)(idealUnspacedY + 0.5f);
211 213
 				layout(element, y, newY - y);
212 214
 				y = newY + style.spacing;
213 215
 			}
@@ -215,7 +217,7 @@ public class DVerticalLayout extends BaseComponentGroup {
215 217
 	}
216 218
 	
217 219
 	private void layout(Element element, int y, int height) {
218
-		DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
220
+		DSizing preferences = element.component.getSizing().getValue();
219 221
 		int x;
220 222
 		int width;
221 223
 		switch (element.alignment) {
@@ -249,7 +251,7 @@ public class DVerticalLayout extends BaseComponentGroup {
249 251
 		int maximumHeight = -style.spacing;
250 252
 		
251 253
 		for (Element element : components) {
252
-			DDimensionPreferences preferences = element.component.getDimensionPreferences().getValue();
254
+			DSizing preferences = element.component.getSizing().getValue();
253 255
 			preferredWidth = Math.max(preferredWidth, preferences.preferredWidth);
254 256
 			preferredHeight += preferences.preferredHeight + style.spacing;
255 257
 			
@@ -260,13 +262,13 @@ public class DVerticalLayout extends BaseComponentGroup {
260 262
 			maximumHeight += preferences.maximumHeight + style.spacing;
261 263
 		}
262 264
 		
263
-		DDimensionPreferences preferences = new DDimensionPreferences(
265
+		DSizing preferences = new DSizing(
264 266
 				minimumWidth + style.paddingLeft + style.paddingRight,
265 267
 				minimumHeight + style.paddingTop + style.paddingBottom,
266 268
 				preferredWidth + style.paddingLeft + style.paddingRight,
267 269
 				preferredHeight + style.paddingTop + style.paddingBottom,
268 270
 				maximumWidth + style.paddingLeft + style.paddingRight,
269 271
 				maximumHeight + style.paddingTop + style.paddingBottom);
270
-		dimensionPreferences.setValue(preferences);
272
+		sizing.setValue(preferences);
271 273
 	}
272 274
 }

+ 65
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCompositeBorder.java 查看文件

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

+ 4
- 4
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java 查看文件

@@ -7,7 +7,7 @@ package org.openzen.drawablegui.border;
7 7
 
8 8
 import org.openzen.drawablegui.DCanvas;
9 9
 import org.openzen.drawablegui.DComponent;
10
-import org.openzen.drawablegui.DDimensionPreferences;
10
+import org.openzen.drawablegui.DSizing;
11 11
 import org.openzen.drawablegui.DMouseEvent;
12 12
 import org.openzen.drawablegui.DPath;
13 13
 import org.openzen.drawablegui.DTransform2D;
@@ -28,7 +28,7 @@ import org.openzen.drawablegui.style.DStylePath;
28 28
 public class DCustomWindowBorder implements DComponent {
29 29
 	private final DStyleClass styleClass;
30 30
 	private final DComponent content;
31
-	private final LiveObject<DDimensionPreferences> preferences = new ImmutableLiveObject<>(DDimensionPreferences.EMPTY);
31
+	private final LiveObject<DSizing> sizing = new ImmutableLiveObject<>(DSizing.EMPTY);
32 32
 	
33 33
 	private DUIContext context;
34 34
 	private DCustomWindowBorderStyle style;
@@ -64,8 +64,8 @@ public class DCustomWindowBorder implements DComponent {
64 64
 	}
65 65
 
66 66
 	@Override
67
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
68
-		return preferences;
67
+	public LiveObject<DSizing> getSizing() {
68
+		return sizing;
69 69
 	}
70 70
 
71 71
 	@Override

+ 2
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java 查看文件

@@ -7,7 +7,6 @@ package org.openzen.drawablegui.border;
7 7
 
8 8
 import org.openzen.drawablegui.DCanvas;
9 9
 import org.openzen.drawablegui.DIRectangle;
10
-import org.openzen.drawablegui.DUIContext;
11 10
 
12 11
 /**
13 12
  *
@@ -16,6 +15,8 @@ import org.openzen.drawablegui.DUIContext;
16 15
 public class DEmptyBorder implements DBorder {
17 16
 	public static final DEmptyBorder INSTANCE = new DEmptyBorder();
18 17
 	
18
+	private DEmptyBorder() {}
19
+	
19 20
 	@Override
20 21
 	public void paint(DCanvas canvas, DIRectangle bounds) {
21 22
 		

+ 0
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java 查看文件

@@ -8,7 +8,6 @@ package org.openzen.drawablegui.border;
8 8
 import org.openzen.drawablegui.DCanvas;
9 9
 import org.openzen.drawablegui.DTransform2D;
10 10
 import org.openzen.drawablegui.DIRectangle;
11
-import org.openzen.drawablegui.DUIContext;
12 11
 
13 12
 /**
14 13
  *

+ 52
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DPaddedBorder.java 查看文件

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

+ 10
- 10
DrawableGui/src/main/java/org/openzen/drawablegui/form/DForm.java 查看文件

@@ -10,12 +10,12 @@ import java.util.function.Predicate;
10 10
 import org.openzen.drawablegui.BaseComponentGroup;
11 11
 import org.openzen.drawablegui.DCanvas;
12 12
 import org.openzen.drawablegui.DComponent;
13
-import org.openzen.drawablegui.DDimensionPreferences;
13
+import org.openzen.drawablegui.DSizing;
14 14
 import org.openzen.drawablegui.DFontMetrics;
15 15
 import org.openzen.drawablegui.DIRectangle;
16 16
 import org.openzen.drawablegui.DUIContext;
17 17
 import org.openzen.drawablegui.live.LiveObject;
18
-import org.openzen.drawablegui.live.SimpleLiveObject;
18
+import org.openzen.drawablegui.live.MutableLiveObject;
19 19
 import org.openzen.drawablegui.style.DStyleClass;
20 20
 import org.openzen.drawablegui.style.DStylePath;
21 21
 
@@ -26,7 +26,7 @@ import org.openzen.drawablegui.style.DStylePath;
26 26
 public class DForm extends BaseComponentGroup {
27 27
 	private final DFormComponent[] components;
28 28
 	private final DStyleClass styleClass;
29
-	private final LiveObject<DDimensionPreferences> preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
29
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
30 30
 	
31 31
 	private DIRectangle bounds;
32 32
 	private DUIContext context;
@@ -56,26 +56,26 @@ public class DForm extends BaseComponentGroup {
56 56
 		
57 57
 		for (DFormComponent component : components) {
58 58
 			maxLabelWidth = Math.max(maxLabelWidth, fontMetrics.getWidth(component.label));
59
-			int componentWidth = component.component.getDimensionPreferences().getValue().preferredWidth;
59
+			int componentWidth = component.component.getSizing().getValue().preferredWidth;
60 60
 			maxFieldWidth = Math.max(maxFieldWidth, componentWidth);
61 61
 		}
62 62
 		
63 63
 		for (DFormComponent component : components) {
64
-			height += component.component.getDimensionPreferences().getValue().preferredHeight;
64
+			height += component.component.getSizing().getValue().preferredHeight;
65 65
 			height += style.spacing;
66 66
 		}
67 67
 		
68 68
 		this.maxFieldWidth = maxFieldWidth;
69 69
 		this.maxLabelWidth = maxLabelWidth;
70
-		preferences.setValue(new DDimensionPreferences(maxLabelWidth + maxFieldWidth + style.paddingLeft + style.paddingRight + style.spacing, height));
70
+		sizing.setValue(new DSizing(maxLabelWidth + maxFieldWidth + style.paddingLeft + style.paddingRight + style.spacing, height));
71 71
 		
72 72
 		if (bounds != null)
73 73
 			layout();
74 74
 	}
75 75
 
76 76
 	@Override
77
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
78
-		return preferences;
77
+	public LiveObject<DSizing> getSizing() {
78
+		return sizing;
79 79
 	}
80 80
 
81 81
 	@Override
@@ -108,7 +108,7 @@ public class DForm extends BaseComponentGroup {
108 108
 			canvas.drawText(style.labelFont, style.labelColor, x, y + baseline, component.label);
109 109
 			component.component.paint(canvas);
110 110
 			
111
-			y += component.component.getDimensionPreferences().getValue().preferredHeight + style.spacing;
111
+			y += component.component.getSizing().getValue().preferredHeight + style.spacing;
112 112
 		}
113 113
 	}
114 114
 
@@ -122,7 +122,7 @@ public class DForm extends BaseComponentGroup {
122 122
 		int y = bounds.y + style.paddingBottom;
123 123
 		
124 124
 		for (DFormComponent component : components) {
125
-			int preferredHeight = component.component.getDimensionPreferences().getValue().preferredHeight;
125
+			int preferredHeight = component.component.getSizing().getValue().preferredHeight;
126 126
 			DIRectangle componentBounds = new DIRectangle(x + maxLabelWidth, y, bounds.width - maxLabelWidth - style.paddingLeft - style.paddingRight - style.spacing, preferredHeight);
127 127
 			component.component.setBounds(componentBounds);
128 128
 			

+ 0
- 5
DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveBool.java 查看文件

@@ -27,11 +27,6 @@ public class ImmutableLiveBool implements LiveBool {
27 27
 		return value;
28 28
 	}
29 29
 
30
-	@Override
31
-	public void setValue(boolean value) {
32
-		throw new UnsupportedOperationException("Cannot modify an immutable value");
33
-	}
34
-
35 30
 	@Override
36 31
 	public ListenerHandle<Listener> addListener(Listener listener) {
37 32
 		return new DummyListenerHandle<>(listener);

+ 0
- 5
DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveObject.java 查看文件

@@ -24,11 +24,6 @@ public class ImmutableLiveObject<T> implements LiveObject<T> {
24 24
 		return value;
25 25
 	}
26 26
 
27
-	@Override
28
-	public void setValue(T value) {
29
-		throw new UnsupportedOperationException("Immutable value");
30
-	}
31
-
32 27
 	@Override
33 28
 	public ListenerHandle<Listener<T>> addListener(Listener<T> listener) {
34 29
 		return new DummyListenerHandle<>(listener);

+ 31
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/ImmutableLiveString.java 查看文件

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

+ 6
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveArrayList.java 查看文件

@@ -15,7 +15,7 @@ import org.openzen.drawablegui.listeners.ListenerList;
15 15
  *
16 16
  * @author Hoofdgebruiker
17 17
  */
18
-public class LiveArrayList<T> implements LiveList<T> {
18
+public class LiveArrayList<T> implements MutableLiveList<T> {
19 19
 	private final List<T> values = new ArrayList<>();
20 20
 	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
21 21
 
@@ -67,6 +67,11 @@ public class LiveArrayList<T> implements LiveList<T> {
67 67
 	public T get(int index) {
68 68
 		return values.get(index);
69 69
 	}
70
+	
71
+	@Override
72
+	public void close() {
73
+		// TODO: close closeables
74
+	}
70 75
 
71 76
 	@Override
72 77
 	public Iterator<T> iterator() {

+ 0
- 6
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveBool.java 查看文件

@@ -14,12 +14,6 @@ import org.openzen.drawablegui.listeners.ListenerHandle;
14 14
 public interface LiveBool {
15 15
 	public boolean getValue();
16 16
 	
17
-	public void setValue(boolean value);
18
-	
19
-	default void toggle() {
20
-		setValue(!getValue());
21
-	}
22
-	
23 17
 	public ListenerHandle<Listener> addListener(Listener listener);
24 18
 	
25 19
 	public interface Listener {

+ 0
- 25
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveConcatList.java 查看文件

@@ -36,31 +36,6 @@ public class LiveConcatList<T> implements Closeable, LiveList<T> {
36 36
 		bListener.close();
37 37
 	}
38 38
 
39
-	@Override
40
-	public void add(T value) {
41
-		throw new UnsupportedOperationException("Cannot modify a concat list");
42
-	}
43
-
44
-	@Override
45
-	public void add(int index, T value) {
46
-		throw new UnsupportedOperationException("Cannot modify a concat list");
47
-	}
48
-
49
-	@Override
50
-	public void set(int index, T value) {
51
-		throw new UnsupportedOperationException("Cannot modify a concat list");
52
-	}
53
-
54
-	@Override
55
-	public void remove(int index) {
56
-		throw new UnsupportedOperationException("Cannot modify a concat list");
57
-	}
58
-
59
-	@Override
60
-	public void remove(T value) {
61
-		throw new UnsupportedOperationException("Cannot modify a concat list");
62
-	}
63
-
64 39
 	@Override
65 40
 	public int indexOf(T value) {
66 41
 		int result = a.indexOf(value);

+ 3
- 23
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveEmptyList.java 查看文件

@@ -20,30 +20,10 @@ public class LiveEmptyList<T> implements LiveList<T> {
20 20
 	public static <T> LiveEmptyList<T> get() {
21 21
 		return INSTANCE;
22 22
 	}
23
-
24
-	@Override
25
-	public void add(T value) {
26
-		throw new UnsupportedOperationException("Immutable list");
27
-	}
28
-
29
-	@Override
30
-	public void add(int index, T value) {
31
-		throw new UnsupportedOperationException("Immutable list");
32
-	}
33
-
34
-	@Override
35
-	public void set(int index, T value) {
36
-		throw new UnsupportedOperationException("Immutable list");
37
-	}
38
-
39
-	@Override
40
-	public void remove(int index) {
41
-		throw new UnsupportedOperationException("Immutable list");
42
-	}
43
-
23
+	
44 24
 	@Override
45
-	public void remove(T value) {
46
-		throw new UnsupportedOperationException("Immutable list");
25
+	public void close() {
26
+		
47 27
 	}
48 28
 
49 29
 	@Override

+ 2
- 10
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveList.java 查看文件

@@ -13,22 +13,14 @@ import org.openzen.drawablegui.listeners.ListenerHandle;
13 13
  * @author Hoofdgebruiker
14 14
  */
15 15
 public interface LiveList<T> extends Iterable<T> {
16
-	void add(T value);
17
-	
18
-	void add(int index, T value);
19
-	
20
-	void set(int index, T value);
21
-	
22
-	void remove(int index);
23
-	
24
-	void remove(T value);
25
-	
26 16
 	int indexOf(T value);
27 17
 	
28 18
 	int size();
29 19
 	
30 20
 	T get(int index);
31 21
 	
22
+	void close();
23
+	
32 24
 	@Override
33 25
 	Iterator<T> iterator();
34 26
 	

+ 0
- 25
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveMappedList.java 查看文件

@@ -37,31 +37,6 @@ public class LiveMappedList<T, U> implements Closeable, LiveList<U> {
37 37
 		mappingListenerHandle.close();
38 38
 	}
39 39
 
40
-	@Override
41
-	public void add(U value) {
42
-		throw new UnsupportedOperationException("Cannot modify a mapped list");
43
-	}
44
-
45
-	@Override
46
-	public void add(int index, U value) {
47
-		throw new UnsupportedOperationException("Cannot modify a mapped list");
48
-	}
49
-
50
-	@Override
51
-	public void set(int index, U value) {
52
-		throw new UnsupportedOperationException("Cannot modify a mapped list");
53
-	}
54
-
55
-	@Override
56
-	public void remove(int index) {
57
-		throw new UnsupportedOperationException("Cannot modify a mapped list");
58
-	}
59
-
60
-	@Override
61
-	public void remove(U value) {
62
-		throw new UnsupportedOperationException("Cannot modify a mapped list");
63
-	}
64
-
65 40
 	@Override
66 41
 	public int indexOf(U value) {
67 42
 		return mapped.indexOf(value);

+ 0
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveObject.java 查看文件

@@ -14,8 +14,6 @@ import org.openzen.drawablegui.listeners.ListenerHandle;
14 14
 public interface LiveObject<T> {
15 15
 	public T getValue();
16 16
 	
17
-	public void setValue(T value);
18
-	
19 17
 	public ListenerHandle<Listener<T>> addListener(Listener<T> listener);
20 18
 	
21 19
 	public interface Listener<T> {

+ 0
- 5
DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePredicateBool.java 查看文件

@@ -32,11 +32,6 @@ public class LivePredicateBool<T> implements LiveBool, Closeable, LiveObject.Lis
32 32
 	public void close() {
33 33
 		sourceListener.close();
34 34
 	}
35
-	
36
-	@Override
37
-	public void setValue(boolean value) {
38
-		throw new UnsupportedOperationException("Cannot modify a calculated value");
39
-	}
40 35
 
41 36
 	@Override
42 37
 	public boolean getValue() {

+ 9
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/live/LivePrefixedList.java 查看文件

@@ -17,13 +17,20 @@ public class LivePrefixedList<T> implements LiveList<T> {
17 17
 	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
18 18
 	private final T prefix;
19 19
 	private final LiveList<T> values;
20
+	private final ListenerHandle<LiveList.Listener<T>> baseListener;
20 21
 	
21 22
 	public LivePrefixedList(T prefix, LiveList<T> values) {
22 23
 		this.prefix = prefix;
23 24
 		this.values = values;
25
+		this.baseListener = values.addListener(new BaseListener());
24 26
 	}
25
-
27
+	
26 28
 	@Override
29
+	public void close() {
30
+		baseListener.close();
31
+	}
32
+
33
+	/*@Override
27 34
 	public void add(T value) {
28 35
 		values.add(value);
29 36
 	}
@@ -54,7 +61,7 @@ public class LivePrefixedList<T> implements LiveList<T> {
54 61
 	@Override
55 62
 	public void remove(T value) {
56 63
 		values.remove(value);
57
-	}
64
+	}*/
58 65
 
59 66
 	@Override
60 67
 	public int indexOf(T value) {

+ 0
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveString.java 查看文件

@@ -16,8 +16,6 @@ public interface LiveString {
16 16
 	
17 17
 	String getValue();
18 18
 	
19
-	void setValue(String value);
20
-	
21 19
 	interface Listener {
22 20
 		void onChanged(String oldValue, String newValue);
23 21
 	}

+ 18
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveBool.java 查看文件

@@ -0,0 +1,18 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface MutableLiveBool extends LiveBool {
13
+	void setValue(boolean value);
14
+	
15
+	default void toggle() {
16
+		setValue(!getValue());
17
+	}
18
+}

+ 22
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveList.java 查看文件

@@ -0,0 +1,22 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.live;
7
+
8
+/**
9
+ *
10
+ * @author Hoofdgebruiker
11
+ */
12
+public interface MutableLiveList<T> extends LiveList<T> {
13
+	void add(T value);
14
+	
15
+	void add(int index, T value);
16
+	
17
+	void set(int index, T value);
18
+	
19
+	void remove(int index);
20
+	
21
+	void remove(T value);
22
+}

+ 14
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveObject.java 查看文件

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

+ 14
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/MutableLiveString.java 查看文件

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

+ 1
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveBool.java 查看文件

@@ -12,7 +12,7 @@ import org.openzen.drawablegui.listeners.ListenerList;
12 12
  *
13 13
  * @author Hoofdgebruiker
14 14
  */
15
-public class SimpleLiveBool implements LiveBool {
15
+public class SimpleLiveBool implements MutableLiveBool {
16 16
 	private final ListenerList<LiveBool.Listener> listeners = new ListenerList<>();
17 17
 	private boolean value;
18 18
 	

+ 1
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveObject.java 查看文件

@@ -12,7 +12,7 @@ import org.openzen.drawablegui.listeners.ListenerList;
12 12
  *
13 13
  * @author Hoofdgebruiker
14 14
  */
15
-public class SimpleLiveObject<T> implements LiveObject<T> {
15
+public class SimpleLiveObject<T> implements MutableLiveObject<T> {
16 16
 	private final ListenerList<Listener<T>> listeners = new ListenerList<>();
17 17
 	private T value;
18 18
 	

+ 1
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/live/SimpleLiveString.java 查看文件

@@ -12,7 +12,7 @@ import org.openzen.drawablegui.listeners.ListenerList;
12 12
  *
13 13
  * @author Hoofdgebruiker
14 14
  */
15
-public class SimpleLiveString implements LiveString {
15
+public class SimpleLiveString implements MutableLiveString {
16 16
 	private final ListenerList<Listener> listeners = new ListenerList<>();
17 17
 	
18 18
 	private String value;

+ 104
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/live/SortedLiveList.java 查看文件

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

+ 8
- 8
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java 查看文件

@@ -7,14 +7,14 @@ package org.openzen.drawablegui.scroll;
7 7
 
8 8
 import org.openzen.drawablegui.DCanvas;
9 9
 import org.openzen.drawablegui.DComponent;
10
-import org.openzen.drawablegui.DDimensionPreferences;
10
+import org.openzen.drawablegui.DSizing;
11 11
 import org.openzen.drawablegui.DMouseEvent;
12 12
 import org.openzen.drawablegui.DIRectangle;
13 13
 import org.openzen.drawablegui.listeners.ListenerHandle;
14 14
 import org.openzen.drawablegui.live.LiveInt;
15 15
 import org.openzen.drawablegui.live.LiveObject;
16
-import org.openzen.drawablegui.live.SimpleLiveObject;
17 16
 import org.openzen.drawablegui.DUIContext;
17
+import org.openzen.drawablegui.live.MutableLiveObject;
18 18
 import org.openzen.drawablegui.style.DStyleClass;
19 19
 import org.openzen.drawablegui.style.DStylePath;
20 20
 
@@ -23,7 +23,7 @@ import org.openzen.drawablegui.style.DStylePath;
23 23
  * @author Hoofdgebruiker
24 24
  */
25 25
 public class DScrollBar implements DComponent {
26
-	private final LiveObject<DDimensionPreferences> preferences;
26
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
27 27
 	
28 28
 	private final DStyleClass styleClass;
29 29
 	private final LiveInt targetHeight;
@@ -47,7 +47,6 @@ public class DScrollBar implements DComponent {
47 47
 		this.styleClass = styleClass;
48 48
 		this.targetHeight = targetHeight;
49 49
 		this.offset = offset;
50
-		this.preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
51 50
 		
52 51
 		targetHeightListener = targetHeight.addListener(new ScrollListener());
53 52
 		offsetListener = offset.addListener(new ScrollListener());
@@ -57,12 +56,12 @@ public class DScrollBar implements DComponent {
57 56
 	public void setContext(DStylePath parent, DUIContext context) {
58 57
 		this.context = context;
59 58
 		this.style = new DScrollBarStyle(context.getStylesheets().get(context, parent.getChild("scrollbar", styleClass)));
60
-		preferences.setValue(new DDimensionPreferences(style.width, 0));
59
+		sizing.setValue(new DSizing(style.width, 0));
61 60
 	}
62 61
 
63 62
 	@Override
64
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
65
-		return preferences;
63
+	public LiveObject<DSizing> getSizing() {
64
+		return sizing;
66 65
 	}
67 66
 
68 67
 	@Override
@@ -138,7 +137,8 @@ public class DScrollBar implements DComponent {
138 137
 
139 138
 	@Override
140 139
 	public void close() {
141
-		// nothing to clean up
140
+		targetHeightListener.close();
141
+		offsetListener.close();
142 142
 	}
143 143
 	
144 144
 	private void checkHover(DMouseEvent e) {

+ 7
- 8
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java 查看文件

@@ -9,7 +9,7 @@ import org.openzen.drawablegui.DAnchor;
9 9
 import org.openzen.drawablegui.DCanvas;
10 10
 import org.openzen.drawablegui.DClipboard;
11 11
 import org.openzen.drawablegui.DComponent;
12
-import org.openzen.drawablegui.DDimensionPreferences;
12
+import org.openzen.drawablegui.DSizing;
13 13
 import org.openzen.drawablegui.DFont;
14 14
 import org.openzen.drawablegui.DFontMetrics;
15 15
 import org.openzen.drawablegui.DIRectangle;
@@ -61,7 +61,7 @@ public class DScrollPane implements DComponent {
61 61
 		offsetXListener = offsetX.addListener(new ScrollListener());
62 62
 		offsetYListener = offsetY.addListener(new ScrollListener());
63 63
 		
64
-		contents.getDimensionPreferences().addListener((oldPreferences, newPreferences) -> {
64
+		contents.getSizing().addListener((oldPreferences, newPreferences) -> {
65 65
 			if (bounds == null)
66 66
 				return;
67 67
 			
@@ -94,8 +94,8 @@ public class DScrollPane implements DComponent {
94 94
 	}
95 95
 
96 96
 	@Override
97
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
98
-		return contents.getDimensionPreferences(); // TODO: derived preferences
97
+	public LiveObject<DSizing> getSizing() {
98
+		return contents.getSizing(); // TODO: derived preferences
99 99
 	}
100 100
 
101 101
 	@Override
@@ -115,10 +115,9 @@ public class DScrollPane implements DComponent {
115 115
 		if (this.context == null)
116 116
 			return;
117 117
 		
118
-		int height = Math.max(
119
-				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom(),
120
-				contents.getDimensionPreferences().getValue().preferredHeight);
121
-		int scrollBarWidth = scrollBar.getDimensionPreferences().getValue().preferredWidth;
118
+		int height = Math.max(bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom(),
119
+				contents.getSizing().getValue().preferredHeight);
120
+		int scrollBarWidth = scrollBar.getSizing().getValue().preferredWidth;
122 121
 		scrollBar.setBounds(new DIRectangle(
123 122
 				bounds.x + bounds.width - scrollBarWidth - style.border.getPaddingRight(),
124 123
 				bounds.y + style.border.getPaddingTop(),

+ 0
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPaneStyle.java 查看文件

@@ -7,7 +7,6 @@ package org.openzen.drawablegui.scroll;
7 7
 
8 8
 import org.openzen.drawablegui.border.DBorder;
9 9
 import org.openzen.drawablegui.border.DLineBorder;
10
-import org.openzen.drawablegui.DUIContext;
11 10
 import org.openzen.drawablegui.style.DStyleDefinition;
12 11
 
13 12
 /**

+ 3
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDialog.java 查看文件

@@ -13,7 +13,7 @@ import java.awt.event.WindowStateListener;
13 13
 import javax.swing.JDialog;
14 14
 import javax.swing.JFrame;
15 15
 import org.openzen.drawablegui.DComponent;
16
-import org.openzen.drawablegui.DDimensionPreferences;
16
+import org.openzen.drawablegui.DSizing;
17 17
 import org.openzen.drawablegui.DIRectangle;
18 18
 import org.openzen.drawablegui.DUIContext;
19 19
 import org.openzen.drawablegui.DUIWindow;
@@ -87,7 +87,7 @@ public final class SwingDialog extends JDialog implements WindowListener, Window
87 87
 
88 88
 	@Override
89 89
 	public void close() {
90
-		System.exit(0);
90
+		dispose();
91 91
 	}
92 92
 
93 93
 	@Override
@@ -125,7 +125,7 @@ public final class SwingDialog extends JDialog implements WindowListener, Window
125 125
 		SwingDialog result = new SwingDialog(this, title, component, false);
126 126
 		result.setResizable(false);
127 127
 		
128
-		DDimensionPreferences size = component.getDimensionPreferences().getValue();
128
+		DSizing size = component.getSizing().getValue();
129 129
 		result.setLocation(
130 130
 				getX() + (getWidth() - size.preferredWidth) / 2,
131 131
 				getY() + (getHeight() - size.preferredHeight) / 2);

+ 3
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingGraphicsContext.java 查看文件

@@ -15,7 +15,7 @@ import javax.swing.Timer;
15 15
 import org.openzen.drawablegui.DAnchor;
16 16
 import org.openzen.drawablegui.DClipboard;
17 17
 import org.openzen.drawablegui.DComponent;
18
-import org.openzen.drawablegui.DDimensionPreferences;
18
+import org.openzen.drawablegui.DSizing;
19 19
 import org.openzen.drawablegui.DPath;
20 20
 import org.openzen.drawablegui.DFont;
21 21
 import org.openzen.drawablegui.DFontMetrics;
@@ -155,7 +155,7 @@ public class SwingGraphicsContext implements DUIContext {
155 155
 		windowContext.graphics = this.graphics; // help a little...
156 156
 		
157 157
 		root.setContext(DStylePathRoot.INSTANCE, windowContext);
158
-		DDimensionPreferences dimension = root.getDimensionPreferences().getValue();
158
+		DSizing dimension = root.getSizing().getValue();
159 159
 		int tx = (int)(x - anchor.alignX * dimension.preferredWidth);
160 160
 		int ty = (int)(y - anchor.alignY * dimension.preferredHeight);
161 161
 		
@@ -175,7 +175,7 @@ public class SwingGraphicsContext implements DUIContext {
175 175
 		windowContext.graphics = this.graphics; // help a little...
176 176
 		
177 177
 		root.setContext(DStylePathRoot.INSTANCE, windowContext);
178
-		DDimensionPreferences dimension = root.getDimensionPreferences().getValue();
178
+		DSizing dimension = root.getSizing().getValue();
179 179
 		int tx = (int)(x - anchor.alignX * dimension.preferredWidth);
180 180
 		int ty = (int)(y - anchor.alignY * dimension.preferredHeight);
181 181
 		

+ 2
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingWindow.java 查看文件

@@ -12,7 +12,7 @@ import java.awt.event.WindowListener;
12 12
 import java.awt.event.WindowStateListener;
13 13
 import javax.swing.JFrame;
14 14
 import org.openzen.drawablegui.DComponent;
15
-import org.openzen.drawablegui.DDimensionPreferences;
15
+import org.openzen.drawablegui.DSizing;
16 16
 import org.openzen.drawablegui.DIRectangle;
17 17
 import org.openzen.drawablegui.DUIContext;
18 18
 import org.openzen.drawablegui.DUIWindow;
@@ -106,7 +106,7 @@ public final class SwingWindow extends JFrame implements WindowListener, WindowS
106 106
 		SwingWindow result = new SwingWindow(title, component, false);
107 107
 		result.setResizable(false);
108 108
 		
109
-		DDimensionPreferences size = component.getDimensionPreferences().getValue();
109
+		DSizing size = component.getSizing().getValue();
110 110
 		result.setLocation(
111 111
 				getX() + (getWidth() - size.preferredWidth) / 2,
112 112
 				getY() + (getHeight() - size.preferredHeight) / 2);

+ 4
- 2
DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeNode.java 查看文件

@@ -7,21 +7,23 @@ package org.openzen.drawablegui.tree;
7 7
 
8 8
 import org.openzen.drawablegui.DColorableIcon;
9 9
 import org.openzen.drawablegui.DMouseEvent;
10
-import org.openzen.drawablegui.live.LiveBool;
11 10
 import org.openzen.drawablegui.live.LiveList;
11
+import org.openzen.drawablegui.live.MutableLiveBool;
12 12
 
13 13
 /**
14 14
  *
15 15
  * @author Hoofdgebruiker
16 16
  */
17 17
 public interface DTreeNode<N extends DTreeNode<N>> {
18
+	void close();
19
+	
18 20
 	DColorableIcon getIcon();
19 21
 	
20 22
 	String getTitle();
21 23
 	
22 24
 	LiveList<N> getChildren();
23 25
 	
24
-	LiveBool isCollapsed();
26
+	MutableLiveBool isCollapsed();
25 27
 	
26 28
 	boolean isLeaf();
27 29
 	

+ 30
- 10
DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeView.java 查看文件

@@ -10,7 +10,7 @@ import java.util.ArrayList;
10 10
 import java.util.List;
11 11
 import org.openzen.drawablegui.DCanvas;
12 12
 import org.openzen.drawablegui.DComponent;
13
-import org.openzen.drawablegui.DDimensionPreferences;
13
+import org.openzen.drawablegui.DSizing;
14 14
 import org.openzen.drawablegui.DDrawable;
15 15
 import org.openzen.drawablegui.DFontMetrics;
16 16
 import org.openzen.drawablegui.DMouseEvent;
@@ -18,9 +18,9 @@ import org.openzen.drawablegui.DTransform2D;
18 18
 import org.openzen.drawablegui.DIRectangle;
19 19
 import org.openzen.drawablegui.listeners.ListenerHandle;
20 20
 import org.openzen.drawablegui.live.LiveBool;
21
-import org.openzen.drawablegui.live.LiveObject;
22
-import org.openzen.drawablegui.live.SimpleLiveObject;
23 21
 import org.openzen.drawablegui.DUIContext;
22
+import org.openzen.drawablegui.live.LiveList;
23
+import org.openzen.drawablegui.live.MutableLiveObject;
24 24
 import org.openzen.drawablegui.style.DStylePath;
25 25
 
26 26
 /**
@@ -28,7 +28,7 @@ import org.openzen.drawablegui.style.DStylePath;
28 28
  * @author Hoofdgebruiker
29 29
  */
30 30
 public class DTreeView<N extends DTreeNode<N>> implements DComponent {
31
-	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
31
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
32 32
 	private DIRectangle bounds;
33 33
 	
34 34
 	private int selectedRow = -1;
@@ -59,8 +59,8 @@ public class DTreeView<N extends DTreeNode<N>> implements DComponent {
59 59
 	}
60 60
 
61 61
 	@Override
62
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
63
-		return dimensionPreferences;
62
+	public MutableLiveObject<DSizing> getSizing() {
63
+		return sizing;
64 64
 	}
65 65
 	
66 66
 	@Override
@@ -187,9 +187,8 @@ public class DTreeView<N extends DTreeNode<N>> implements DComponent {
187 187
 		}
188 188
 		
189 189
 		if (rows.size() != oldRowCount) {
190
-			DDimensionPreferences preferences = dimensionPreferences.getValue();
191
-			dimensionPreferences.setValue(
192
-					new DDimensionPreferences(
190
+			DSizing preferences = sizing.getValue();
191
+			sizing.setValue(new DSizing(
193 192
 							preferences.minimumWidth,
194 193
 							preferences.minimumHeight,
195 194
 							preferences.preferredWidth,
@@ -217,15 +216,17 @@ public class DTreeView<N extends DTreeNode<N>> implements DComponent {
217 216
 		// nothing to clean up
218 217
 	}
219 218
 	
220
-	private class Row implements Closeable, LiveBool.Listener {
219
+	private class Row implements Closeable, LiveBool.Listener, LiveList.Listener<N> {
221 220
 		private final int x;
222 221
 		private final N node;
223 222
 		private final ListenerHandle<LiveBool.Listener> collapseListener;
223
+		private final ListenerHandle<LiveList.Listener<N>> childListener;
224 224
 		
225 225
 		public Row(int x, N node) {
226 226
 			this.x = x;
227 227
 			this.node = node;
228 228
 			this.collapseListener = node.isCollapsed().addListener(this);
229
+			this.childListener = node.getChildren().addListener(this);
229 230
 		}
230 231
 
231 232
 		@Override
@@ -233,10 +234,29 @@ public class DTreeView<N extends DTreeNode<N>> implements DComponent {
233 234
 			updateLayout();
234 235
 			context.repaint(bounds);
235 236
 		}
237
+
238
+		@Override
239
+		public void onInserted(int index, N value) {
240
+			updateLayout();
241
+			context.repaint(bounds);
242
+		}
243
+
244
+		@Override
245
+		public void onChanged(int index, N oldValue, N newValue) {
246
+			updateLayout();
247
+			context.repaint(bounds);
248
+		}
249
+
250
+		@Override
251
+		public void onRemoved(int index, N oldValue) {
252
+			updateLayout();
253
+			context.repaint(bounds);
254
+		}
236 255
 		
237 256
 		@Override
238 257
 		public void close() {
239 258
 			collapseListener.close();
259
+			childListener.close();
240 260
 		}
241 261
 	}
242 262
 }

+ 4
- 0
IDE/src/main/java/org/openzen/zenscript/ide/host/IDEPackage.java 查看文件

@@ -17,4 +17,8 @@ public interface IDEPackage {
17 17
 	public LiveList<IDEPackage> getSubPackages();
18 18
 	
19 19
 	public LiveList<IDESourceFile> getSourceFiles();
20
+	
21
+	public IDEPackage createSubPackage(String name);
22
+	
23
+	public IDESourceFile createSourceFile(String name);
20 24
 }

+ 2
- 1
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalLibrary.java 查看文件

@@ -7,6 +7,7 @@ package org.openzen.zenscript.ide.host.local;
7 7
 
8 8
 import org.openzen.drawablegui.live.LiveArrayList;
9 9
 import org.openzen.drawablegui.live.LiveList;
10
+import org.openzen.drawablegui.live.MutableLiveList;
10 11
 import org.openzen.zenscript.constructor.Library;
11 12
 import org.openzen.zenscript.constructor.module.ModuleReference;
12 13
 import org.openzen.zenscript.ide.host.IDELibrary;
@@ -18,7 +19,7 @@ import org.openzen.zenscript.ide.host.IDEModule;
18 19
  */
19 20
 public class LocalLibrary implements IDELibrary {
20 21
 	private final Library library;
21
-	private final LiveList<IDEModule> modules;
22
+	private final MutableLiveList<IDEModule> modules;
22 23
 	
23 24
 	public LocalLibrary(Library library) {
24 25
 		this.library = library;

+ 3
- 1
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalModule.java 查看文件

@@ -15,9 +15,11 @@ import org.openzen.zenscript.ide.host.IDEPackage;
15 15
  */
16 16
 public class LocalModule implements IDEModule {
17 17
 	private final ModuleReference module;
18
+	private final LocalPackage rootPackage;
18 19
 	
19 20
 	public LocalModule(ModuleReference module) {
20 21
 		this.module = module;
22
+		rootPackage = new LocalPackage(module.getRootPackage());
21 23
 	}
22 24
 
23 25
 	@Override
@@ -27,6 +29,6 @@ public class LocalModule implements IDEModule {
27 29
 
28 30
 	@Override
29 31
 	public IDEPackage getRootPackage() {
30
-		return new LocalPackage(module.getRootPackage());
32
+		return rootPackage;
31 33
 	}
32 34
 }

+ 47
- 8
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalPackage.java 查看文件

@@ -5,9 +5,14 @@
5 5
  */
6 6
 package org.openzen.zenscript.ide.host.local;
7 7
 
8
+import java.io.File;
9
+import java.io.IOException;
8 10
 import java.util.Arrays;
9 11
 import org.openzen.drawablegui.live.LiveArrayList;
10 12
 import org.openzen.drawablegui.live.LiveList;
13
+import org.openzen.drawablegui.live.MutableLiveList;
14
+import org.openzen.drawablegui.live.SortedLiveList;
15
+import org.openzen.zenscript.constructor.module.SourceFile;
11 16
 import org.openzen.zenscript.constructor.module.SourcePackage;
12 17
 import org.openzen.zenscript.ide.host.IDEPackage;
13 18
 import org.openzen.zenscript.ide.host.IDESourceFile;
@@ -18,8 +23,11 @@ import org.openzen.zenscript.ide.host.IDESourceFile;
18 23
  */
19 24
 public class LocalPackage implements IDEPackage {
20 25
 	private final SourcePackage pkg;
21
-	private final LiveList<IDEPackage> subPackages = new LiveArrayList<>();
22
-	private final LiveList<IDESourceFile> sourceFiles = new LiveArrayList<>();
26
+	private final MutableLiveList<IDEPackage> subPackages = new LiveArrayList<>();
27
+	private final MutableLiveList<IDESourceFile> sourceFiles = new LiveArrayList<>();
28
+	
29
+	private final LiveList<IDEPackage> subPackagesSorted;
30
+	private final LiveList<IDESourceFile> sourceFilesSorted;
23 31
 	
24 32
 	public LocalPackage(SourcePackage pkg) {
25 33
 		this.pkg = pkg;
@@ -32,12 +40,15 @@ public class LocalPackage implements IDEPackage {
32 40
 				.toArray(new String[pkg.sourceFiles.size()]);
33 41
 		Arrays.sort(sourceFileKeys);
34 42
 		
35
-		for (String subKey : subPackageKeys) {
36
-			subPackages.add(new LocalPackage(pkg.subPackages.get(subKey)));
43
+		for (SourcePackage subPackage : pkg.subPackages.values()) {
44
+			subPackages.add(new LocalPackage(subPackage));
37 45
 		}
38
-		for (String sourceFileKey : sourceFileKeys) {
39
-			sourceFiles.add(new LocalSourceFile(pkg.sourceFiles.get(sourceFileKey)));
46
+		for (SourceFile sourceFile : pkg.sourceFiles.values()) {
47
+			sourceFiles.add(new LocalSourceFile(sourceFile));
40 48
 		}
49
+		
50
+		subPackagesSorted = new SortedLiveList<>(subPackages, (a, b) -> a.getName().compareTo(b.getName()));
51
+		sourceFilesSorted = new SortedLiveList<>(sourceFiles, (a, b) -> a.getName().compareTo(b.getName()));
41 52
 	}
42 53
 	
43 54
 	@Override
@@ -47,11 +58,39 @@ public class LocalPackage implements IDEPackage {
47 58
 
48 59
 	@Override
49 60
 	public LiveList<IDEPackage> getSubPackages() {
50
-		return subPackages;
61
+		return subPackagesSorted;
51 62
 	}
52 63
 
53 64
 	@Override
54 65
 	public LiveList<IDESourceFile> getSourceFiles() {
55
-		return sourceFiles;
66
+		return sourceFilesSorted;
67
+	}
68
+	
69
+	@Override
70
+	public IDEPackage createSubPackage(String name) {
71
+		File file = new File(this.pkg.directory, name);
72
+		file.mkdir();
73
+		
74
+		SourcePackage sourcePackage = new SourcePackage(file, name);
75
+		IDEPackage pkg = new LocalPackage(sourcePackage);
76
+		this.pkg.subPackages.put(name, sourcePackage);
77
+		subPackages.add(pkg);
78
+		return pkg;
79
+	}
80
+	
81
+	@Override
82
+	public IDESourceFile createSourceFile(String name) {
83
+		File file = new File(this.pkg.directory, name);
84
+		try {
85
+			file.createNewFile();
86
+		} catch (IOException ex) {
87
+			ex.printStackTrace(); // TODO
88
+		}
89
+		
90
+		SourceFile sourceFile = new SourceFile(name, file);
91
+		IDESourceFile localSourceFile = new LocalSourceFile(sourceFile);
92
+		this.pkg.sourceFiles.put(name, sourceFile);
93
+		sourceFiles.add(localSourceFile);
94
+		return localSourceFile;
56 95
 	}
57 96
 }

+ 4
- 4
IDE/src/main/java/org/openzen/zenscript/ide/host/local/LocalProjectDevelopmentHost.java 查看文件

@@ -5,9 +5,9 @@
5 5
  */
6 6
 package org.openzen.zenscript.ide.host.local;
7 7
 
8
-import java.util.List;
9 8
 import org.openzen.drawablegui.live.LiveArrayList;
10 9
 import org.openzen.drawablegui.live.LiveList;
10
+import org.openzen.drawablegui.live.MutableLiveList;
11 11
 import org.openzen.zenscript.constructor.Library;
12 12
 import org.openzen.zenscript.constructor.Project;
13 13
 import org.openzen.zenscript.constructor.module.ModuleReference;
@@ -23,9 +23,9 @@ import org.openzen.zenscript.ide.host.IDETarget;
23 23
  */
24 24
 public class LocalProjectDevelopmentHost implements DevelopmentHost {
25 25
 	private final Project project;
26
-	private final LiveList<IDEModule> modules;
27
-	private final LiveList<IDELibrary> libraries;
28
-	private final LiveList<IDETarget> targets;
26
+	private final MutableLiveList<IDEModule> modules;
27
+	private final MutableLiveList<IDELibrary> libraries;
28
+	private final MutableLiveList<IDETarget> targets;
29 29
 	
30 30
 	public LocalProjectDevelopmentHost(Project project) {
31 31
 		this.project = project;

+ 4
- 4
IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectBar.java 查看文件

@@ -6,8 +6,8 @@
6 6
 package org.openzen.zenscript.ide.ui;
7 7
 
8 8
 import org.openzen.drawablegui.live.LiveArrayList;
9
-import org.openzen.drawablegui.live.LiveList;
10
-import org.openzen.drawablegui.live.LiveObject;
9
+import org.openzen.drawablegui.live.MutableLiveList;
10
+import org.openzen.drawablegui.live.MutableLiveObject;
11 11
 import org.openzen.drawablegui.live.SimpleLiveObject;
12 12
 
13 13
 /**
@@ -15,6 +15,6 @@ import org.openzen.drawablegui.live.SimpleLiveObject;
15 15
  * @author Hoofdgebruiker
16 16
  */
17 17
 public class IDEAspectBar {
18
-	public final LiveList<IDEAspectToolbar> toolbars = new LiveArrayList<>();
19
-	public final LiveObject<IDEAspectToolbar> active = new SimpleLiveObject<>(null);
18
+	public final MutableLiveList<IDEAspectToolbar> toolbars = new LiveArrayList<>();
19
+	public final MutableLiveObject<IDEAspectToolbar> active = new SimpleLiveObject<>(null);
20 20
 }

+ 2
- 2
IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEAspectToolbar.java 查看文件

@@ -7,7 +7,7 @@ package org.openzen.zenscript.ide.ui;
7 7
 
8 8
 import org.openzen.drawablegui.DDrawable;
9 9
 import org.openzen.drawablegui.live.LiveArrayList;
10
-import org.openzen.drawablegui.live.LiveList;
10
+import org.openzen.drawablegui.live.MutableLiveList;
11 11
 
12 12
 /**
13 13
  *
@@ -18,7 +18,7 @@ public class IDEAspectToolbar {
18 18
 	public final DDrawable icon;
19 19
 	public final String title;
20 20
 	public final String description;
21
-	public final LiveList<IDEAspectBarControl> controls = new LiveArrayList<>();
21
+	public final MutableLiveList<IDEAspectBarControl> controls = new LiveArrayList<>();
22 22
 	
23 23
 	public IDEAspectToolbar(int order, DDrawable icon, String title, String description) {
24 24
 		this.order = order;

+ 12
- 33
IDE/src/main/java/org/openzen/zenscript/ide/ui/IDEWindow.java 查看文件

@@ -5,27 +5,18 @@
5 5
  */
6 6
 package org.openzen.zenscript.ide.ui;
7 7
 
8
-import org.openzen.drawablegui.DAnchor;
9
-import org.openzen.drawablegui.DComponent;
10
-import org.openzen.drawablegui.DEmptyView;
11
-import org.openzen.drawablegui.DIRectangle;
12
-import org.openzen.drawablegui.DInputField;
13
-import org.openzen.drawablegui.DUIWindow;
14
-import org.openzen.drawablegui.form.DForm;
15
-import org.openzen.drawablegui.form.DFormComponent;
16 8
 import org.openzen.drawablegui.live.LiveBool;
17
-import org.openzen.drawablegui.live.LiveObject;
18 9
 import org.openzen.drawablegui.live.LivePredicateBool;
19
-import org.openzen.drawablegui.live.SimpleLiveBool;
10
+import org.openzen.drawablegui.live.MutableLiveObject;
20 11
 import org.openzen.drawablegui.live.SimpleLiveObject;
21
-import org.openzen.drawablegui.live.SimpleLiveString;
22
-import org.openzen.drawablegui.style.DDpDimension;
23 12
 import org.openzen.drawablegui.style.DStyleClass;
24 13
 import org.openzen.zenscript.ide.host.DevelopmentHost;
25 14
 import org.openzen.zenscript.ide.host.IDEModule;
26 15
 import org.openzen.zenscript.ide.host.IDEPackage;
27 16
 import org.openzen.zenscript.ide.host.IDESourceFile;
28 17
 import org.openzen.zenscript.ide.host.IDETarget;
18
+import org.openzen.zenscript.ide.ui.dialog.CreatePackageDialog;
19
+import org.openzen.zenscript.ide.ui.dialog.CreateSourceFileDialog;
29 20
 import org.openzen.zenscript.ide.ui.icons.AddBoxIcon;
30 21
 import org.openzen.zenscript.ide.ui.icons.BuildIcon;
31 22
 import org.openzen.zenscript.ide.ui.icons.PlayIcon;
@@ -46,9 +37,9 @@ public class IDEWindow {
46 37
 	
47 38
 	public IDEAspectToolbar projectToolbar;
48 39
 	
49
-	private final LiveObject<IDEModule> contextModule = new SimpleLiveObject<>(null);
50
-	private final LiveObject<IDEPackage> contextPackage = new SimpleLiveObject<>(null);
51
-	private final LiveObject<IDESourceFile> contextFile = new SimpleLiveObject<>(null);
40
+	private final MutableLiveObject<IDEModule> contextModule = new SimpleLiveObject<>(null);
41
+	private final MutableLiveObject<IDEPackage> contextPackage = new SimpleLiveObject<>(null);
42
+	private final MutableLiveObject<IDESourceFile> contextFile = new SimpleLiveObject<>(null);
52 43
 	private final LiveBool addContentDisabled = new LivePredicateBool(contextPackage, pkg -> pkg == null);
53 44
 	
54 45
 	public IDEWindow(DevelopmentHost host) {
@@ -76,24 +67,12 @@ public class IDEWindow {
76 67
 	private void init() {
77 68
 		projectToolbar = new IDEAspectToolbar(0, ShadedProjectIcon.PURPLE, "Project", "Project management");
78 69
 		projectToolbar.controls.add(() -> new IconButtonControl(DStyleClass.EMPTY, AddBoxIcon.BLUE, AddBoxIcon.GRAY, addContentDisabled, e -> {
79
-			DComponent input = new DInputField(DStyleClass.EMPTY, new SimpleLiveString(""), new DDpDimension(100));
80
-			DForm root = new DForm(DStyleClass.EMPTY, new DFormComponent("Package name:", input));
81
-			
82
-			DUIWindow window = e.window;
83
-			DIRectangle rectangle = window.getWindowBounds();
84
-			DUIWindow newWindow = e.window.getContext().openDialog(rectangle.getCenterX(), rectangle.getCenterY(), DAnchor.MIDDLE_LEFT, "Create package", root);
85
-			
86
-			newWindow.focus(input);
70
+			CreatePackageDialog dialog = new CreatePackageDialog(this, contextModule.getValue(), contextPackage.getValue());
71
+			dialog.open(e.window);
87 72
 		}));
88 73
 		projectToolbar.controls.add(() -> new IconButtonControl(DStyleClass.EMPTY, AddBoxIcon.ORANGE, AddBoxIcon.GRAY, addContentDisabled, e -> {
89
-			DComponent input = new DInputField(DStyleClass.EMPTY, new SimpleLiveString(""), new DDpDimension(100));
90
-			DForm root = new DForm(DStyleClass.EMPTY, new DFormComponent("Filename:", input));
91
-			
92
-			DUIWindow window = e.window;
93
-			DIRectangle rectangle = window.getWindowBounds();
94
-			DUIWindow newWindow = e.window.getContext().openDialog(rectangle.getCenterX(), rectangle.getCenterY(), DAnchor.MIDDLE_LEFT, "Create file", root);
95
-			
96
-			newWindow.focus(input);
74
+			CreateSourceFileDialog dialog = new CreateSourceFileDialog(this, contextModule.getValue(), contextPackage.getValue());
75
+			dialog.open(e.window);
97 76
 		}));
98 77
 		projectToolbar.controls.add(() -> new IconButtonControl(DStyleClass.EMPTY, SettingsIcon.PURPLE, e -> {
99 78
 			
@@ -119,8 +98,8 @@ public class IDEWindow {
119 98
 		contextFile.setValue(null);
120 99
 	}
121 100
 	
122
-	public void setContextPackage(IDEPackage pkg) {
123
-		contextModule.setValue(null);
101
+	public void setContextPackage(IDEModule module, IDEPackage pkg) {
102
+		contextModule.setValue(module);
124 103
 		contextPackage.setValue(pkg);
125 104
 		contextFile.setValue(null);
126 105
 	}

+ 89
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/dialog/CreatePackageDialog.java 查看文件

@@ -0,0 +1,89 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.ui.dialog;
7
+
8
+import org.openzen.drawablegui.DAnchor;
9
+import org.openzen.drawablegui.DButton;
10
+import org.openzen.drawablegui.DComponent;
11
+import org.openzen.drawablegui.DHorizontalLayout;
12
+import org.openzen.drawablegui.DIRectangle;
13
+import org.openzen.drawablegui.DInputField;
14
+import org.openzen.drawablegui.DLabel;
15
+import org.openzen.drawablegui.DUIWindow;
16
+import org.openzen.drawablegui.DVerticalLayout;
17
+import org.openzen.drawablegui.form.DForm;
18
+import org.openzen.drawablegui.form.DFormComponent;
19
+import org.openzen.drawablegui.live.ImmutableLiveBool;
20
+import org.openzen.drawablegui.live.ImmutableLiveString;
21
+import org.openzen.drawablegui.live.SimpleLiveString;
22
+import org.openzen.drawablegui.style.DDpDimension;
23
+import org.openzen.drawablegui.style.DStyleClass;
24
+import org.openzen.zenscript.ide.host.IDEModule;
25
+import org.openzen.zenscript.ide.host.IDEPackage;
26
+import org.openzen.zenscript.ide.ui.IDEWindow;
27
+
28
+/**
29
+ *
30
+ * @author Hoofdgebruiker
31
+ */
32
+public class CreatePackageDialog {
33
+	private final IDEWindow ideWindow;
34
+	private final IDEModule module;
35
+	private final IDEPackage pkg;
36
+	
37
+	private final SimpleLiveString name;
38
+	
39
+	private final DComponent root;
40
+	private final DInputField input;
41
+	
42
+	private DUIWindow window;
43
+	
44
+	public CreatePackageDialog(IDEWindow ideWindow, IDEModule module, IDEPackage pkg) {
45
+		this.ideWindow = ideWindow;
46
+		this.module = module;
47
+		this.pkg = pkg;
48
+		
49
+		name = new SimpleLiveString("");
50
+		input = new DInputField(DStyleClass.EMPTY, name, new DDpDimension(100));
51
+		input.setOnEnter(this::ok);
52
+		input.setOnEscape(this::cancel);
53
+		
54
+		DForm form = new DForm(
55
+				DStyleClass.EMPTY,
56
+				new DFormComponent("Module:", new DLabel(DStyleClass.EMPTY, new ImmutableLiveString(module.getName()))),
57
+				new DFormComponent("Parent package:", new DLabel(DStyleClass.EMPTY, new ImmutableLiveString(pkg.getName().isEmpty() ? "(module root)" : pkg.getName()))),
58
+				new DFormComponent("Package name:", input));
59
+
60
+		DButton ok = new DButton(DStyleClass.EMPTY, new SimpleLiveString("Create"), ImmutableLiveBool.FALSE, this::ok);
61
+		DButton cancel = new DButton(DStyleClass.EMPTY, new SimpleLiveString("Cancel"), ImmutableLiveBool.FALSE, this::cancel);
62
+		DHorizontalLayout buttons = new DHorizontalLayout(
63
+				DStyleClass.EMPTY,
64
+				DHorizontalLayout.Alignment.RIGHT,
65
+				new DHorizontalLayout.Element(cancel, 0, 0, DHorizontalLayout.ElementAlignment.TOP),
66
+				new DHorizontalLayout.Element(ok, 0, 0, DHorizontalLayout.ElementAlignment.TOP));
67
+
68
+		root = new DVerticalLayout(
69
+				DStyleClass.EMPTY,
70
+				DVerticalLayout.Alignment.MIDDLE,
71
+				new DVerticalLayout.Element(form, 1, 1, DVerticalLayout.ElementAlignment.CENTER),
72
+				new DVerticalLayout.Element(buttons, 0, 0, DVerticalLayout.ElementAlignment.RIGHT));
73
+	}
74
+	
75
+	public void open(DUIWindow parent) {
76
+		DIRectangle rectangle = parent.getWindowBounds();
77
+		window = parent.getContext().openDialog(rectangle.getCenterX(), rectangle.getCenterY(), DAnchor.MIDDLE_LEFT, "Create package", root);
78
+		window.focus(input);
79
+	}
80
+	
81
+	private void cancel() {
82
+		window.close();
83
+	}
84
+	
85
+	private void ok() {
86
+		window.close();
87
+		pkg.createSubPackage(name.getValue());
88
+	}
89
+}

+ 91
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/dialog/CreateSourceFileDialog.java 查看文件

@@ -0,0 +1,91 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.ide.ui.dialog;
7
+
8
+import org.openzen.drawablegui.DAnchor;
9
+import org.openzen.drawablegui.DButton;
10
+import org.openzen.drawablegui.DComponent;
11
+import org.openzen.drawablegui.DHorizontalLayout;
12
+import org.openzen.drawablegui.DIRectangle;
13
+import org.openzen.drawablegui.DInputField;
14
+import org.openzen.drawablegui.DLabel;
15
+import org.openzen.drawablegui.DUIWindow;
16
+import org.openzen.drawablegui.DVerticalLayout;
17
+import org.openzen.drawablegui.form.DForm;
18
+import org.openzen.drawablegui.form.DFormComponent;
19
+import org.openzen.drawablegui.live.ImmutableLiveBool;
20
+import org.openzen.drawablegui.live.ImmutableLiveString;
21
+import org.openzen.drawablegui.live.SimpleLiveString;
22
+import org.openzen.drawablegui.style.DDpDimension;
23
+import org.openzen.drawablegui.style.DStyleClass;
24
+import org.openzen.zenscript.ide.host.IDEModule;
25
+import org.openzen.zenscript.ide.host.IDEPackage;
26
+import org.openzen.zenscript.ide.host.IDESourceFile;
27
+import org.openzen.zenscript.ide.ui.IDEWindow;
28
+
29
+/**
30
+ *
31
+ * @author Hoofdgebruiker
32
+ */
33
+public class CreateSourceFileDialog {
34
+	private final IDEWindow ideWindow;
35
+	private final IDEModule module;
36
+	private final IDEPackage pkg;
37
+	
38
+	private final SimpleLiveString name;
39
+	
40
+	private final DComponent root;
41
+	private final DInputField input;
42
+	
43
+	private DUIWindow window;
44
+	
45
+	public CreateSourceFileDialog(IDEWindow ideWindow, IDEModule module, IDEPackage pkg) {
46
+		this.ideWindow = ideWindow;
47
+		this.module = module;
48
+		this.pkg = pkg;
49
+		
50
+		name = new SimpleLiveString("");
51
+		input = new DInputField(DStyleClass.EMPTY, name, new DDpDimension(100));
52
+		input.setOnEnter(this::ok);
53
+		input.setOnEscape(this::cancel);
54
+		
55
+		DForm form = new DForm(
56
+				DStyleClass.EMPTY,
57
+				new DFormComponent("Module:", new DLabel(DStyleClass.EMPTY, new ImmutableLiveString(module.getName()))),
58
+				new DFormComponent("Package:", new DLabel(DStyleClass.EMPTY, new ImmutableLiveString(pkg.getName().isEmpty() ? "(module root)" : pkg.getName()))),
59
+				new DFormComponent("Filename:", input));
60
+
61
+		DButton ok = new DButton(DStyleClass.EMPTY, new SimpleLiveString("Create"), ImmutableLiveBool.FALSE, this::ok);
62
+		DButton cancel = new DButton(DStyleClass.EMPTY, new SimpleLiveString("Cancel"), ImmutableLiveBool.FALSE, this::cancel);
63
+		DHorizontalLayout buttons = new DHorizontalLayout(
64
+				DStyleClass.EMPTY,
65
+				DHorizontalLayout.Alignment.RIGHT,
66
+				new DHorizontalLayout.Element(cancel, 0, 0, DHorizontalLayout.ElementAlignment.TOP),
67
+				new DHorizontalLayout.Element(ok, 0, 0, DHorizontalLayout.ElementAlignment.TOP));
68
+
69
+		root = new DVerticalLayout(
70
+				DStyleClass.EMPTY,
71
+				DVerticalLayout.Alignment.MIDDLE,
72
+				new DVerticalLayout.Element(form, 1, 1, DVerticalLayout.ElementAlignment.CENTER),
73
+				new DVerticalLayout.Element(buttons, 0, 0, DVerticalLayout.ElementAlignment.RIGHT));
74
+	}
75
+	
76
+	public void open(DUIWindow parent) {
77
+		DIRectangle rectangle = parent.getWindowBounds();
78
+		window = parent.getContext().openDialog(rectangle.getCenterX(), rectangle.getCenterY(), DAnchor.MIDDLE_LEFT, "Create source file", root);
79
+		window.focus(input);
80
+	}
81
+	
82
+	private void cancel() {
83
+		window.close();
84
+	}
85
+	
86
+	private void ok() {
87
+		window.close();
88
+		IDESourceFile file = pkg.createSourceFile(name.getValue() + ".zs");
89
+		ideWindow.open(file);
90
+	}
91
+}

+ 5
- 5
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/IconButtonControl.java 查看文件

@@ -8,7 +8,7 @@ package org.openzen.zenscript.ide.ui.view;
8 8
 import java.util.function.Consumer;
9 9
 import org.openzen.drawablegui.DCanvas;
10 10
 import org.openzen.drawablegui.DComponent;
11
-import org.openzen.drawablegui.DDimensionPreferences;
11
+import org.openzen.drawablegui.DSizing;
12 12
 import org.openzen.drawablegui.DDrawable;
13 13
 import org.openzen.drawablegui.DMouseEvent;
14 14
 import org.openzen.drawablegui.DPath;
@@ -19,7 +19,7 @@ import org.openzen.drawablegui.listeners.ListenerHandle;
19 19
 import org.openzen.drawablegui.live.ImmutableLiveBool;
20 20
 import org.openzen.drawablegui.live.LiveBool;
21 21
 import org.openzen.drawablegui.live.LiveObject;
22
-import org.openzen.drawablegui.live.SimpleLiveObject;
22
+import org.openzen.drawablegui.live.MutableLiveObject;
23 23
 import org.openzen.drawablegui.style.DStyleClass;
24 24
 import org.openzen.drawablegui.style.DStylePath;
25 25
 
@@ -38,7 +38,7 @@ public class IconButtonControl implements DComponent {
38 38
 	private DUIContext context;
39 39
 	private IconButtonControlStyle style;
40 40
 	private DIRectangle bounds;
41
-	private final LiveObject<DDimensionPreferences> preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
41
+	private final MutableLiveObject<DSizing> preferences = DSizing.create();
42 42
 	private boolean hover;
43 43
 	private boolean press;
44 44
 	private DPath shape;
@@ -66,14 +66,14 @@ public class IconButtonControl implements DComponent {
66 66
 		int iconHeight = (int)(icon.getNominalWidth() * context.getScale() + 0.5f);
67 67
 		int width = iconWidth + 2 * style.padding + 2 * style.margin;
68 68
 		int height = iconHeight + 2 * style.padding + 2 * style.margin;
69
-		preferences.setValue(new DDimensionPreferences(width, height));
69
+		preferences.setValue(new DSizing(width, height));
70 70
 		
71 71
 		if (bounds != null)
72 72
 			setBounds(bounds);
73 73
 	}
74 74
 
75 75
 	@Override
76
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
76
+	public LiveObject<DSizing> getSizing() {
77 77
 		return preferences;
78 78
 	}
79 79
 

+ 4
- 4
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/StatusBarView.java 查看文件

@@ -7,7 +7,7 @@ package org.openzen.zenscript.ide.ui.view;
7 7
 
8 8
 import org.openzen.drawablegui.DCanvas;
9 9
 import org.openzen.drawablegui.DComponent;
10
-import org.openzen.drawablegui.DDimensionPreferences;
10
+import org.openzen.drawablegui.DSizing;
11 11
 import org.openzen.drawablegui.DFontMetrics;
12 12
 import org.openzen.drawablegui.DIRectangle;
13 13
 import org.openzen.drawablegui.live.LiveObject;
@@ -22,7 +22,7 @@ import org.openzen.drawablegui.style.DStylePath;
22 22
  * @author Hoofdgebruiker
23 23
  */
24 24
 public class StatusBarView implements DComponent {
25
-	private final SimpleLiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(new DDimensionPreferences(0, 0));
25
+	private final SimpleLiveObject<DSizing> dimensionPreferences = new SimpleLiveObject<>(new DSizing(0, 0));
26 26
 	
27 27
 	private final DStyleClass styleClass;
28 28
 	private final LiveString content;
@@ -44,11 +44,11 @@ public class StatusBarView implements DComponent {
44 44
 		style = new StatusBarStyle(context.getStylesheets().get(context, path));
45 45
 		fontMetrics = context.getFontMetrics(style.font);
46 46
 		
47
-		dimensionPreferences.setValue(new DDimensionPreferences(0, style.paddingTop + fontMetrics.getAscent() + fontMetrics.getDescent() + style.paddingBottom));
47
+		dimensionPreferences.setValue(new DSizing(0, style.paddingTop + fontMetrics.getAscent() + fontMetrics.getDescent() + style.paddingBottom));
48 48
 	}
49 49
 	
50 50
 	@Override
51
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
51
+	public LiveObject<DSizing> getSizing() {
52 52
 		return dimensionPreferences;
53 53
 	}
54 54
 	

+ 9
- 8
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedView.java 查看文件

@@ -10,15 +10,16 @@ import java.util.function.Predicate;
10 10
 import org.openzen.drawablegui.BaseComponentGroup;
11 11
 import org.openzen.drawablegui.DCanvas;
12 12
 import org.openzen.drawablegui.DComponent;
13
-import org.openzen.drawablegui.DDimensionPreferences;
13
+import org.openzen.drawablegui.DSizing;
14 14
 import org.openzen.drawablegui.DFontMetrics;
15 15
 import org.openzen.drawablegui.DIRectangle;
16 16
 import org.openzen.drawablegui.DUIContext;
17
-import org.openzen.drawablegui.live.ImmutableLiveObject;
18 17
 import org.openzen.drawablegui.live.LiveArrayList;
19 18
 import org.openzen.drawablegui.live.LiveList;
20 19
 import org.openzen.drawablegui.live.LiveMappedList;
21 20
 import org.openzen.drawablegui.live.LiveObject;
21
+import org.openzen.drawablegui.live.MutableLiveList;
22
+import org.openzen.drawablegui.live.MutableLiveObject;
22 23
 import org.openzen.drawablegui.live.SimpleLiveObject;
23 24
 import org.openzen.drawablegui.style.DStyleClass;
24 25
 import org.openzen.drawablegui.style.DStylePath;
@@ -29,9 +30,9 @@ import org.openzen.drawablegui.style.DStylePath;
29 30
  */
30 31
 public class TabbedView extends BaseComponentGroup {
31 32
 	private final DStyleClass styleClass;
32
-	public final LiveList<TabbedViewComponent> tabs = new LiveArrayList<>();
33
-	private final LiveObject<DDimensionPreferences> preferences = new ImmutableLiveObject<>(DDimensionPreferences.EMPTY);
34
-	public final LiveObject<TabbedViewComponent> currentTab = new SimpleLiveObject<>(null);
33
+	public final MutableLiveList<TabbedViewComponent> tabs = new LiveArrayList<>();
34
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
35
+	public final MutableLiveObject<TabbedViewComponent> currentTab = new SimpleLiveObject<>(null);
35 36
 	
36 37
 	private DUIContext context;
37 38
 	private DStylePath path;
@@ -81,8 +82,8 @@ public class TabbedView extends BaseComponentGroup {
81 82
 	}
82 83
 
83 84
 	@Override
84
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
85
-		return preferences;
85
+	public LiveObject<DSizing> getSizing() {
86
+		return sizing;
86 87
 	}
87 88
 
88 89
 	@Override
@@ -140,7 +141,7 @@ public class TabbedView extends BaseComponentGroup {
140 141
 		
141 142
 		int x = bounds.x + style.tabBarSpacingLeft;
142 143
 		for (DComponent tab : tabComponents) {
143
-			DDimensionPreferences preferences = tab.getDimensionPreferences().getValue();
144
+			DSizing preferences = tab.getSizing().getValue();
144 145
 			tab.setBounds(new DIRectangle(
145 146
 					x, bounds.y + totalTabHeight - preferences.preferredHeight, preferences.preferredWidth, preferences.preferredHeight));
146 147
 			

+ 11
- 11
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTab.java 查看文件

@@ -7,7 +7,7 @@ package org.openzen.zenscript.ide.ui.view;
7 7
 
8 8
 import org.openzen.drawablegui.DCanvas;
9 9
 import org.openzen.drawablegui.DComponent;
10
-import org.openzen.drawablegui.DDimensionPreferences;
10
+import org.openzen.drawablegui.DSizing;
11 11
 import org.openzen.drawablegui.DFontMetrics;
12 12
 import org.openzen.drawablegui.DIRectangle;
13 13
 import org.openzen.drawablegui.DMouseEvent;
@@ -15,7 +15,7 @@ import org.openzen.drawablegui.DPath;
15 15
 import org.openzen.drawablegui.DTransform2D;
16 16
 import org.openzen.drawablegui.DUIContext;
17 17
 import org.openzen.drawablegui.live.LiveObject;
18
-import org.openzen.drawablegui.live.SimpleLiveObject;
18
+import org.openzen.drawablegui.live.MutableLiveObject;
19 19
 import org.openzen.drawablegui.style.DStyleClass;
20 20
 import org.openzen.drawablegui.style.DStylePath;
21 21
 
@@ -25,8 +25,8 @@ import org.openzen.drawablegui.style.DStylePath;
25 25
  */
26 26
 public class TabbedViewTab implements DComponent {
27 27
 	private final TabbedViewComponent tab;
28
-	private final LiveObject<DDimensionPreferences> preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
29
-	private final LiveObject<TabbedViewComponent> currentTab;
28
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
29
+	private final MutableLiveObject<TabbedViewComponent> currentTab;
30 30
 	
31 31
 	private final TabbedView parent;
32 32
 	public final TabbedViewTabClose closeButton;
@@ -40,7 +40,7 @@ public class TabbedViewTab implements DComponent {
40 40
 	private boolean hover;
41 41
 	private boolean press;
42 42
 	
43
-	public TabbedViewTab(TabbedView parent, LiveObject<TabbedViewComponent> currentTab, TabbedViewComponent tab) {
43
+	public TabbedViewTab(TabbedView parent, MutableLiveObject<TabbedViewComponent> currentTab, TabbedViewComponent tab) {
44 44
 		this.parent = parent;
45 45
 		this.currentTab = currentTab;
46 46
 		this.tab = tab;
@@ -60,17 +60,17 @@ public class TabbedViewTab implements DComponent {
60 60
 		closeButton.setContext(path, context);
61 61
 		
62 62
 		textWidth = fontMetrics.getWidth(tab.title);
63
-		preferences.setValue(new DDimensionPreferences(
63
+		sizing.setValue(new DSizing(
64 64
 				style.paddingLeft + textWidth + style.paddingRight
65 65
 						+ style.closeIconPadding
66
-						+ closeButton.getDimensionPreferences().getValue().preferredWidth,
66
+						+ closeButton.getSizing().getValue().preferredWidth,
67 67
 				style.paddingTop + fontMetrics.getAscent() + fontMetrics.getDescent()
68 68
 						+ style.paddingBottom));
69 69
 	}
70 70
 
71 71
 	@Override
72
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
73
-		return preferences;
72
+	public LiveObject<DSizing> getSizing() {
73
+		return sizing;
74 74
 	}
75 75
 
76 76
 	@Override
@@ -87,7 +87,7 @@ public class TabbedViewTab implements DComponent {
87 87
 	public void setBounds(DIRectangle bounds) {
88 88
 		this.bounds = bounds;
89 89
 		
90
-		DDimensionPreferences close = closeButton.getDimensionPreferences().getValue();
90
+		DSizing close = closeButton.getSizing().getValue();
91 91
 		closeButton.setBounds(new DIRectangle(
92 92
 				bounds.x + bounds.width - close.preferredWidth - style.paddingRight,
93 93
 				bounds.y + (bounds.height - close.preferredHeight) / 2,
@@ -98,7 +98,7 @@ public class TabbedViewTab implements DComponent {
98 98
 	@Override
99 99
 	public void paint(DCanvas canvas) {
100 100
 		int width = style.paddingLeft + textWidth + style.paddingRight
101
-				+ closeButton.getDimensionPreferences().getValue().preferredWidth + style.closeIconPadding;
101
+				+ closeButton.getSizing().getValue().preferredWidth + style.closeIconPadding;
102 102
 
103 103
 		int color = style.tabColorNormal;
104 104
 		if (currentTab.getValue() == tab)

+ 6
- 8
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTabClose.java 查看文件

@@ -8,17 +8,15 @@ package org.openzen.zenscript.ide.ui.view;
8 8
 import org.openzen.drawablegui.DCanvas;
9 9
 import org.openzen.drawablegui.DColorableIcon;
10 10
 import org.openzen.drawablegui.DComponent;
11
-import org.openzen.drawablegui.DDimensionPreferences;
12
-import org.openzen.drawablegui.DDrawable;
11
+import org.openzen.drawablegui.DSizing;
13 12
 import org.openzen.drawablegui.DIRectangle;
14 13
 import org.openzen.drawablegui.DMouseEvent;
15 14
 import org.openzen.drawablegui.DTransform2D;
16 15
 import org.openzen.drawablegui.DUIContext;
17 16
 import org.openzen.drawablegui.live.LiveObject;
18
-import org.openzen.drawablegui.live.SimpleLiveObject;
17
+import org.openzen.drawablegui.live.MutableLiveObject;
19 18
 import org.openzen.drawablegui.style.DStyleClass;
20 19
 import org.openzen.drawablegui.style.DStylePath;
21
-import org.openzen.zenscript.ide.ui.icons.ColoredIcon;
22 20
 import org.openzen.zenscript.ide.ui.icons.ScalableCloseIcon;
23 21
 
24 22
 /**
@@ -27,7 +25,7 @@ import org.openzen.zenscript.ide.ui.icons.ScalableCloseIcon;
27 25
  */
28 26
 public class TabbedViewTabClose implements DComponent {
29 27
 	private final TabbedViewTab tab;
30
-	private final LiveObject<DDimensionPreferences> preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
28
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
31 29
 	
32 30
 	private DUIContext context;
33 31
 	private DIRectangle bounds;
@@ -47,13 +45,13 @@ public class TabbedViewTabClose implements DComponent {
47 45
 		
48 46
 		DStylePath path = parent.getChild("tabClose", DStyleClass.EMPTY);
49 47
 		style = new TabbedViewTabCloseStyle(context.getStylesheets().get(context, path));
50
-		preferences.setValue(new DDimensionPreferences(style.size, style.size));
48
+		sizing.setValue(new DSizing(style.size, style.size));
51 49
 		icon = new ScalableCloseIcon(style.size / 24);
52 50
 	}
53 51
 
54 52
 	@Override
55
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
56
-		return preferences;
53
+	public LiveObject<DSizing> getSizing() {
54
+		return sizing;
57 55
 	}
58 56
 
59 57
 	@Override

+ 2
- 2
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/WindowView.java 查看文件

@@ -5,7 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.ide.ui.view;
7 7
 
8
-import org.openzen.drawablegui.DDimensionPreferences;
8
+import org.openzen.drawablegui.DSizing;
9 9
 import org.openzen.drawablegui.DEmptyView;
10 10
 import org.openzen.drawablegui.scroll.DScrollPane;
11 11
 import org.openzen.drawablegui.DSideLayout;
@@ -36,7 +36,7 @@ public final class WindowView extends DSideLayout {
36 36
 		this.window = window;
37 37
 		
38 38
 		DTreeView projectView = new DTreeView(DTreeViewStyle.DEFAULT, new RootTreeNode(window, host), false);
39
-		projectView.getDimensionPreferences().setValue(new DDimensionPreferences(500, 500));
39
+		projectView.getSizing().setValue(new DSizing(500, 500));
40 40
 		setMain(tabs = new TabbedView(DStyleClass.EMPTY));
41 41
 		add(Side.LEFT, new DScrollPane(DStyleClass.forId("projectView"), projectView));
42 42
 		add(Side.BOTTOM, new StatusBarView(DStyleClass.EMPTY, status));

+ 17
- 8
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarSelectorButton.java 查看文件

@@ -8,17 +8,19 @@ package org.openzen.zenscript.ide.ui.view.aspectbar;
8 8
 import java.util.function.Consumer;
9 9
 import org.openzen.drawablegui.DCanvas;
10 10
 import org.openzen.drawablegui.DComponent;
11
-import org.openzen.drawablegui.DDimensionPreferences;
11
+import org.openzen.drawablegui.DSizing;
12 12
 import org.openzen.drawablegui.DDrawable;
13 13
 import org.openzen.drawablegui.DMouseEvent;
14 14
 import org.openzen.drawablegui.DPath;
15 15
 import org.openzen.drawablegui.DTransform2D;
16 16
 import org.openzen.drawablegui.DUIContext;
17 17
 import org.openzen.drawablegui.DIRectangle;
18
+import org.openzen.drawablegui.DSimpleTooltip;
18 19
 import org.openzen.drawablegui.listeners.ListenerHandle;
20
+import org.openzen.drawablegui.live.ImmutableLiveString;
19 21
 import org.openzen.drawablegui.live.LiveBool;
20 22
 import org.openzen.drawablegui.live.LiveObject;
21
-import org.openzen.drawablegui.live.SimpleLiveObject;
23
+import org.openzen.drawablegui.live.MutableLiveObject;
22 24
 import org.openzen.drawablegui.style.DShadow;
23 25
 import org.openzen.drawablegui.style.DStyleClass;
24 26
 import org.openzen.drawablegui.style.DStylePath;
@@ -28,12 +30,11 @@ import org.openzen.drawablegui.style.DStylePath;
28 30
  * @author Hoofdgebruiker
29 31
  */
30 32
 public class AspectBarSelectorButton implements DComponent {
31
-	
32 33
 	public final LiveBool active;
33 34
 	
34 35
 	private final DStyleClass styleClass;
35 36
 	private final DDrawable icon;
36
-	private final LiveObject<DDimensionPreferences> preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
37
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
37 38
 	private final Consumer<DMouseEvent> onClick;
38 39
 	private DUIContext context;
39 40
 	private AspectBarSelectorButtonStyle style;
@@ -41,14 +42,16 @@ public class AspectBarSelectorButton implements DComponent {
41 42
 	private DPath shape;
42 43
 	private boolean hovering;
43 44
 	private boolean pressing;
45
+	private DSimpleTooltip tooltip;
44 46
 	
45 47
 	private final ListenerHandle<LiveBool.Listener> activeListener;
46 48
 	
47
-	public AspectBarSelectorButton(DStyleClass styleClass, DDrawable icon, LiveBool active, Consumer<DMouseEvent> onClick) {
49
+	public AspectBarSelectorButton(DStyleClass styleClass, DDrawable icon, LiveBool active, String tooltip, Consumer<DMouseEvent> onClick) {
48 50
 		this.active = active;
49 51
 		this.styleClass = styleClass;
50 52
 		this.icon = icon;
51 53
 		this.onClick = onClick;
54
+		this.tooltip = new DSimpleTooltip(DStyleClass.EMPTY, new ImmutableLiveString(tooltip));
52 55
 		
53 56
 		activeListener = active.addListener((oldValue, newValue) -> repaint());
54 57
 	}
@@ -58,18 +61,20 @@ public class AspectBarSelectorButton implements DComponent {
58 61
 		this.context = context;
59 62
 		DStylePath path = parent.getChild("selectorbutton", styleClass);
60 63
 		style = new AspectBarSelectorButtonStyle(context.getStylesheets().get(context, path));
61
-		preferences.setValue(new DDimensionPreferences(style.width, style.height));
64
+		sizing.setValue(new DSizing(style.width, style.height));
62 65
 		shape = DPath.roundedRectangle(
63 66
 				0,
64 67
 				0,
65 68
 				style.width,
66 69
 				style.height,
67 70
 				style.roundingRadius);
71
+		
72
+		tooltip.setContext(parent, context);
68 73
 	}
69 74
 
70 75
 	@Override
71
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
72
-		return preferences;
76
+	public LiveObject<DSizing> getSizing() {
77
+		return sizing;
73 78
 	}
74 79
 
75 80
 	@Override
@@ -114,11 +119,13 @@ public class AspectBarSelectorButton implements DComponent {
114 119
 				bounds.x + (style.width - icon.getNominalWidth() * context.getScale()) / 2,
115 120
 				bounds.y + (style.height - icon.getNominalHeight() * context.getScale()) / 2,
116 121
 				context.getScale()));
122
+		tooltip.paint(canvas);
117 123
 	}
118 124
 	
119 125
 	@Override
120 126
 	public void onMouseEnter(DMouseEvent e) {
121 127
 		hovering = true;
128
+		tooltip.onTargetMouseEnter(e);
122 129
 		repaint();
123 130
 	}
124 131
 	
@@ -126,6 +133,7 @@ public class AspectBarSelectorButton implements DComponent {
126 133
 	public void onMouseExit(DMouseEvent e) {
127 134
 		hovering = false;
128 135
 		pressing = false;
136
+		tooltip.onTargetMouseExit(e);
129 137
 		repaint();
130 138
 	}
131 139
 	
@@ -147,6 +155,7 @@ public class AspectBarSelectorButton implements DComponent {
147 155
 	@Override
148 156
 	public void close() {
149 157
 		activeListener.close();
158
+		tooltip.close();
150 159
 	}
151 160
 	
152 161
 	private void repaint() {

+ 1
- 1
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarStyle.java 查看文件

@@ -40,7 +40,7 @@ public class AspectBarStyle {
40 40
 	public final DShadow windowControlShadow;
41 41
 	
42 42
 	public AspectBarStyle(DStyleDefinition style) {
43
-		height = style.getDimension("height", new DDpDimension(32));
43
+		height = style.getDimension("height", new DDpDimension(38));
44 44
 		aspectSelectorPaddingLeft = style.getDimension("aspectSelectorPaddingLeft", new DDpDimension(4));
45 45
 		aspectSelectorToToolbarSpacing = style.getDimension("aspectSelectorToToolbarSpacing", new DDpDimension(16));
46 46
 		toolbarTitleToControlsSpacing = style.getDimension("toolbarTitleToControlsSpacing", new DDpDimension(8));

+ 22
- 25
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarView.java 查看文件

@@ -12,13 +12,12 @@ import java.util.function.Predicate;
12 12
 import org.openzen.drawablegui.BaseComponentGroup;
13 13
 import org.openzen.drawablegui.DCanvas;
14 14
 import org.openzen.drawablegui.DComponent;
15
-import org.openzen.drawablegui.DDimensionPreferences;
15
+import org.openzen.drawablegui.DSizing;
16 16
 import org.openzen.drawablegui.DFontMetrics;
17 17
 import org.openzen.drawablegui.DPath;
18 18
 import org.openzen.drawablegui.DTransform2D;
19 19
 import org.openzen.drawablegui.DIRectangle;
20 20
 import org.openzen.drawablegui.live.LiveObject;
21
-import org.openzen.drawablegui.live.SimpleLiveObject;
22 21
 import org.openzen.zenscript.ide.ui.IDEAspectBar;
23 22
 import org.openzen.zenscript.ide.ui.IDEAspectToolbar;
24 23
 import org.openzen.drawablegui.DUIContext;
@@ -28,6 +27,7 @@ import org.openzen.drawablegui.live.LiveBool;
28 27
 import org.openzen.drawablegui.live.LiveList;
29 28
 import org.openzen.drawablegui.live.LiveMappedList;
30 29
 import org.openzen.drawablegui.live.LivePredicateBool;
30
+import org.openzen.drawablegui.live.MutableLiveObject;
31 31
 import org.openzen.drawablegui.style.DStyleClass;
32 32
 import org.openzen.drawablegui.style.DStylePath;
33 33
 import org.openzen.zenscript.ide.ui.IDEAspectBarControl;
@@ -40,10 +40,9 @@ import org.openzen.zenscript.ide.ui.icons.ScalableMinimizeIcon;
40 40
  * @author Hoofdgebruiker
41 41
  */
42 42
 public class AspectBarView extends BaseComponentGroup {
43
-	private final SimpleLiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(new DDimensionPreferences(0, 64));
43
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
44 44
 	private final DStyleClass styleClass;
45 45
 	private final IDEAspectBar aspectBar;
46
-	private final List<IDEAspectToolbar> contextBars = new ArrayList<>();
47 46
 	
48 47
 	private DIRectangle bounds;
49 48
 	private DUIContext context;
@@ -64,9 +63,9 @@ public class AspectBarView extends BaseComponentGroup {
64 63
 	private WindowActionButton maximizeRestore;
65 64
 	private WindowActionButton close;
66 65
 	
67
-	private final ListenerHandle<LiveObject.Listener<DDimensionPreferences>> minimizeRelayout;
68
-	private final ListenerHandle<LiveObject.Listener<DDimensionPreferences>> maximizeRestoreRelayout;
69
-	private final ListenerHandle<LiveObject.Listener<DDimensionPreferences>> closeRelayout;
66
+	private final ListenerHandle<LiveObject.Listener<DSizing>> minimizeRelayout;
67
+	private final ListenerHandle<LiveObject.Listener<DSizing>> maximizeRestoreRelayout;
68
+	private final ListenerHandle<LiveObject.Listener<DSizing>> closeRelayout;
70 69
 	
71 70
 	public AspectBarView(DStyleClass styleClass, IDEAspectBar aspectBar) {
72 71
 		this.styleClass = styleClass;
@@ -76,22 +75,22 @@ public class AspectBarView extends BaseComponentGroup {
76 75
 		listener = aspectBar.toolbars.addListener(new ToolbarListListener());
77 76
 		
78 77
 		minimize = new WindowActionButton(scale -> new ScalableMinimizeIcon(scale), e -> context.getWindow().minimize());
79
-		minimizeRelayout = minimize.getDimensionPreferences().addListener((a, b) -> layout());
78
+		minimizeRelayout = minimize.getSizing().addListener((a, b) -> layout());
80 79
 		maximizeRestore = new WindowActionButton(ScalableMaximizeIcon::new, e -> {
81 80
 			if (context.getWindow().getWindowState().getValue() == DUIWindow.State.MAXIMIZED)
82 81
 				context.getWindow().restore();
83 82
 			else
84 83
 				context.getWindow().maximize();
85 84
 		});
86
-		maximizeRestoreRelayout = maximizeRestore.getDimensionPreferences().addListener((a, b) -> layout());
85
+		maximizeRestoreRelayout = maximizeRestore.getSizing().addListener((a, b) -> layout());
87 86
 		close = new WindowActionButton(scale -> new ScalableCloseIcon(scale), e -> context.getWindow().close());
88
-		closeRelayout = close.getDimensionPreferences().addListener((a, b) -> layout());
87
+		closeRelayout = close.getSizing().addListener((a, b) -> layout());
89 88
 		
90 89
 		selectorButtons = new LiveMappedList<>(
91 90
 				aspectBar.toolbars,
92 91
 				bar -> {
93 92
 					LiveBool buttonActive = new LivePredicateBool<>(aspectBar.active, activeBar -> activeBar == bar);
94
-					AspectBarSelectorButton button = new AspectBarSelectorButton(DStyleClass.EMPTY, bar.icon, buttonActive, e -> aspectBar.active.setValue(bar));
93
+					AspectBarSelectorButton button = new AspectBarSelectorButton(DStyleClass.EMPTY, bar.icon, buttonActive, bar.description, e -> aspectBar.active.setValue(bar));
95 94
 					if (context != null)
96 95
 						button.setContext(path, context);
97 96
 					
@@ -111,14 +110,11 @@ public class AspectBarView extends BaseComponentGroup {
111 110
 		activeToolbarTitleFontMetrics = context.getFontMetrics(style.activeToolbarTitleFont);
112 111
 		showWindowControls = !context.getWindow().hasTitleBar();
113 112
 		
113
+		sizing.setValue(new DSizing(0, style.height));
114
+		
114 115
 		for (DComponent selectorButton : selectorButtons)
115 116
 			selectorButton.setContext(path, context);
116 117
 		
117
-		if (bounds != null) {
118
-			layout();
119
-			aspectBar.active.setValue(aspectBar.active.getValue());
120
-		}
121
-		
122 118
 		if (activeToolbarComponents != null)
123 119
 			for (DComponent component : activeToolbarComponents)
124 120
 				component.setContext(path, context);
@@ -129,8 +125,8 @@ public class AspectBarView extends BaseComponentGroup {
129 125
 	}
130 126
 	
131 127
 	@Override
132
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
133
-		return dimensionPreferences;
128
+	public LiveObject<DSizing> getSizing() {
129
+		return sizing;
134 130
 	}
135 131
 	
136 132
 	@Override
@@ -231,9 +227,9 @@ public class AspectBarView extends BaseComponentGroup {
231 227
 		layoutActiveToolbarComponents();
232 228
 		
233 229
 		int x = bounds.x + bounds.width;
234
-		DDimensionPreferences closeSize = close.getDimensionPreferences().getValue();
235
-		DDimensionPreferences maximizeRestoreSize = maximizeRestore.getDimensionPreferences().getValue();
236
-		DDimensionPreferences minimizeSize = minimize.getDimensionPreferences().getValue();
230
+		DSizing closeSize = close.getSizing().getValue();
231
+		DSizing maximizeRestoreSize = maximizeRestore.getSizing().getValue();
232
+		DSizing minimizeSize = minimize.getSizing().getValue();
237 233
 		
238 234
 		x -= closeSize.preferredWidth;
239 235
 		close.setBounds(new DIRectangle(x, bounds.y, closeSize.preferredWidth, closeSize.preferredHeight));
@@ -253,8 +249,8 @@ public class AspectBarView extends BaseComponentGroup {
253 249
 		int x = bounds.x + style.aspectSelectorPaddingLeft;
254 250
 		
255 251
 		for (DComponent component : selectorButtons) {
256
-			int width = component.getDimensionPreferences().getValue().preferredWidth;
257
-			int height = component.getDimensionPreferences().getValue().preferredHeight;
252
+			int width = component.getSizing().getValue().preferredWidth;
253
+			int height = component.getSizing().getValue().preferredHeight;
258 254
 			int y = bounds.y + (bounds.height - style.aspectSelectorBottomSize - height) / 2;
259 255
 			component.setBounds(new DIRectangle(x, y, width, height));
260 256
 			
@@ -265,7 +261,7 @@ public class AspectBarView extends BaseComponentGroup {
265 261
 	}
266 262
 	
267 263
 	private void layoutActiveToolbarComponents() {
268
-		if (bounds == null)
264
+		if (bounds == null || bounds.height < (style.aspectBarPaddingTop + style.controlPaddingTop + style.controlPaddingBottom))
269 265
 			return;
270 266
 		
271 267
 		int x = aspectSelectorEndX
@@ -275,8 +271,9 @@ public class AspectBarView extends BaseComponentGroup {
275 271
 		
276 272
 		int y = style.aspectBarPaddingTop + style.controlPaddingTop;
277 273
 		int height = bounds.height - y - style.controlPaddingBottom;
274
+		
278 275
 		for (DComponent toolbarComponent : activeToolbarComponents) {
279
-			int width = toolbarComponent.getDimensionPreferences().getValue().preferredWidth;
276
+			int width = toolbarComponent.getSizing().getValue().preferredWidth;
280 277
 			toolbarComponent.setBounds(
281 278
 					new DIRectangle(x, bounds.y + y, width, height));
282 279
 			x += width;

+ 6
- 6
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/WindowActionButton.java 查看文件

@@ -10,7 +10,7 @@ import java.util.function.Function;
10 10
 import org.openzen.drawablegui.DCanvas;
11 11
 import org.openzen.drawablegui.DColorableIcon;
12 12
 import org.openzen.drawablegui.DComponent;
13
-import org.openzen.drawablegui.DDimensionPreferences;
13
+import org.openzen.drawablegui.DSizing;
14 14
 import org.openzen.drawablegui.DMouseEvent;
15 15
 import org.openzen.drawablegui.DTransform2D;
16 16
 import org.openzen.drawablegui.DUIContext;
@@ -18,7 +18,7 @@ import org.openzen.drawablegui.DIRectangle;
18 18
 import org.openzen.drawablegui.listeners.ListenerHandle;
19 19
 import org.openzen.drawablegui.live.LiveBool;
20 20
 import org.openzen.drawablegui.live.LiveObject;
21
-import org.openzen.drawablegui.live.SimpleLiveObject;
21
+import org.openzen.drawablegui.live.MutableLiveObject;
22 22
 import org.openzen.drawablegui.style.DStylePath;
23 23
 import org.openzen.zenscript.ide.ui.icons.ScalableCloseIcon;
24 24
 
@@ -27,7 +27,7 @@ import org.openzen.zenscript.ide.ui.icons.ScalableCloseIcon;
27 27
  * @author Hoofdgebruiker
28 28
  */
29 29
 public class WindowActionButton implements DComponent {
30
-	private final SimpleLiveObject<DDimensionPreferences> preferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
30
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
31 31
 	
32 32
 	private final Function<Float, DColorableIcon> scalableIcon;
33 33
 	private final Consumer<DMouseEvent> action;
@@ -54,14 +54,14 @@ public class WindowActionButton implements DComponent {
54 54
 		windowFocusedListener = windowFocused.addListener((a, b) -> repaint());
55 55
 		
56 56
 		icon = scalableIcon == null ? null : scalableIcon.apply(context.getScale());
57
-		preferences.setValue(new DDimensionPreferences(
57
+		sizing.setValue(new DSizing(
58 58
 				(int)(48 * context.getScale()),
59 59
 				(int)(24 * context.getScale())));
60 60
 	}
61 61
 
62 62
 	@Override
63
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
64
-		return preferences;
63
+	public LiveObject<DSizing> getSizing() {
64
+		return sizing;
65 65
 	}
66 66
 
67 67
 	@Override

+ 38
- 9
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/editor/SourceEditor.java 查看文件

@@ -8,7 +8,7 @@ package org.openzen.zenscript.ide.ui.view.editor;
8 8
 import java.io.IOException;
9 9
 import org.openzen.drawablegui.DCanvas;
10 10
 import org.openzen.drawablegui.DComponent;
11
-import org.openzen.drawablegui.DDimensionPreferences;
11
+import org.openzen.drawablegui.DSizing;
12 12
 import org.openzen.drawablegui.DFont;
13 13
 import org.openzen.drawablegui.DFontFamily;
14 14
 import org.openzen.drawablegui.DFontMetrics;
@@ -29,6 +29,7 @@ import org.openzen.zenscript.lexer.ZSToken;
29 29
 import org.openzen.zenscript.lexer.ZSTokenParser;
30 30
 import org.openzen.zenscript.lexer.ZSTokenType;
31 31
 import org.openzen.drawablegui.DUIContext;
32
+import org.openzen.drawablegui.live.MutableLiveObject;
32 33
 import org.openzen.drawablegui.live.SimpleLiveBool;
33 34
 import org.openzen.drawablegui.style.DStyleClass;
34 35
 import org.openzen.drawablegui.style.DStylePath;
@@ -44,7 +45,7 @@ import org.openzen.zenscript.ide.ui.view.IconButtonControl;
44 45
 public class SourceEditor implements DComponent {
45 46
 	private final DStyleClass styleClass;
46 47
 	private final DFont font = new DFont(DFontFamily.CODE, false, false, false, 24);
47
-	private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(new DDimensionPreferences(0, 0));
48
+	private final MutableLiveObject<DSizing> sizing = DSizing.create();
48 49
 	private final String tab = "    ";
49 50
 	private final IDESourceFile sourceFile;
50 51
 	private final TokenModel tokens;
@@ -124,7 +125,7 @@ public class SourceEditor implements DComponent {
124 125
 		fullLineHeight = textLineHeight + fontMetrics.getLeading() + style.extraLineSpacing;
125 126
 		selectionLineHeight = textLineHeight + style.selectionPaddingTop + style.selectionPaddingBottom;
126 127
 		
127
-		dimensionPreferences.setValue(new DDimensionPreferences(0, fullLineHeight * tokens.getLineCount()));
128
+		sizing.setValue(new DSizing(0, fullLineHeight * tokens.getLineCount()));
128 129
 		
129 130
 		if (blinkTimer != null)
130 131
 			blinkTimer.close();
@@ -132,8 +133,8 @@ public class SourceEditor implements DComponent {
132 133
 	}
133 134
 
134 135
 	@Override
135
-	public LiveObject<DDimensionPreferences> getDimensionPreferences() {
136
-		return dimensionPreferences;
136
+	public LiveObject<DSizing> getSizing() {
137
+		return sizing;
137 138
 	}
138 139
 
139 140
 	@Override
@@ -464,6 +465,18 @@ public class SourceEditor implements DComponent {
464 465
 		if (deleteSelection())
465 466
 			return;
466 467
 		
468
+		if (cursorEnd.line > 0) {
469
+			String indent = tokens.getLine(cursorEnd.line - 1).getIndent(); // TODO: get nominal indent for current scope
470
+			if (cursorEnd.offset == indent.length()) {
471
+				// remove entire indent
472
+				SourcePosition deleteFrom = new SourcePosition(tokens, cursorEnd.line - 1, tokens.getLine(cursorEnd.line - 1).length());
473
+				tokens.delete(deleteFrom, cursorEnd);
474
+				unchanged.setValue(false);
475
+				setCursor(deleteFrom, deleteFrom);
476
+				return;
477
+			}
478
+		}
479
+		
467 480
 		if (cursorEnd.offset == 0) {
468 481
 			if (cursorEnd.line == 0)
469 482
 				return;
@@ -489,9 +502,25 @@ public class SourceEditor implements DComponent {
489 502
 	private void type(String value) {
490 503
 		deleteSelection();
491 504
 		
492
-		tokens.insert(cursorEnd, value);
493
-		SourcePosition position = new SourcePosition(tokens, cursorEnd.line, cursorEnd.offset + value.length());
494
-		setCursor(position, position);
505
+		if (value.equals("{")) {
506
+			String indent = tokens.getLine(cursorEnd.line).getIndent();
507
+			tokens.insert(cursorEnd, "{\n" + indent + "\t\n" + indent + "}");
508
+			
509
+			SourcePosition position = new SourcePosition(tokens, cursorEnd.line + 1, indent.length() + 1);
510
+			setCursor(position, position);
511
+		} else if (value.equals(";")) {
512
+			String indent = tokens.getLine(cursorEnd.line).getIndent();
513
+			tokens.insert(cursorEnd, ";\n" + indent);
514
+			
515
+			SourcePosition position = new SourcePosition(tokens, cursorEnd.line + 1, indent.length());
516
+			setCursor(position, position);
517
+		} else {
518
+			tokens.insert(cursorEnd, value);
519
+			
520
+			SourcePosition position = new SourcePosition(tokens, cursorEnd.line, cursorEnd.offset + value.length());
521
+			setCursor(position, position);
522
+		}
523
+		
495 524
 		unchanged.setValue(false);
496 525
 	}
497 526
 	
@@ -620,7 +649,7 @@ public class SourceEditor implements DComponent {
620 649
 	}
621 650
 	
622 651
 	private void onLinesUpdated() {
623
-		dimensionPreferences.setValue(new DDimensionPreferences(0, fullLineHeight * tokens.getLineCount()));
652
+		sizing.setValue(new DSizing(0, fullLineHeight * tokens.getLineCount()));
624 653
 		
625 654
 		if (bounds != null)
626 655
 			context.repaint(bounds);

+ 5
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/LibraryTreeNode.java 查看文件

@@ -26,6 +26,11 @@ public class LibraryTreeNode extends ProjectOverviewNode {
26 26
 		modules = new LiveMappedList<>(library.getModules(), module -> new ModuleTreeNode(window, module));
27 27
 	}
28 28
 	
29
+	@Override
30
+	public void close() {
31
+		modules.close();
32
+	}
33
+	
29 34
 	@Override
30 35
 	public DColorableIcon getIcon() {
31 36
 		return LibraryIcon.INSTANCE;

+ 1
- 5
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/ModuleTreeNode.java 查看文件

@@ -16,14 +16,10 @@ import org.openzen.zenscript.ide.ui.icons.ModuleIcon;
16 16
  * @author Hoofdgebruiker
17 17
  */
18 18
 public class ModuleTreeNode extends PackageTreeNode {
19
-	private final IDEModule module;
20
-	private final IDEWindow window;
21
-	
22 19
 	public ModuleTreeNode(IDEWindow window, IDEModule module) {
23 20
 		super(window, module.getRootPackage());
24 21
 		
25
-		this.module = module;
26
-		this.window = window;
22
+		init(module);
27 23
 	}
28 24
 
29 25
 	@Override

+ 28
- 2
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/PackageTreeNode.java 查看文件

@@ -6,9 +6,11 @@
6 6
 package org.openzen.zenscript.ide.ui.view.project;
7 7
 
8 8
 import org.openzen.drawablegui.DColorableIcon;
9
+import org.openzen.drawablegui.DMouseEvent;
9 10
 import org.openzen.drawablegui.live.LiveConcatList;
10 11
 import org.openzen.drawablegui.live.LiveList;
11 12
 import org.openzen.drawablegui.live.LiveMappedList;
13
+import org.openzen.zenscript.ide.host.IDEModule;
12 14
 import org.openzen.zenscript.ide.host.IDEPackage;
13 15
 import org.openzen.zenscript.ide.ui.IDEWindow;
14 16
 import org.openzen.zenscript.ide.ui.icons.FolderIcon;
@@ -18,17 +20,36 @@ import org.openzen.zenscript.ide.ui.icons.FolderIcon;
18 20
  * @author Hoofdgebruiker
19 21
  */
20 22
 public class PackageTreeNode extends ProjectOverviewNode {
23
+	protected final IDEWindow window;
24
+	protected IDEModule module;
21 25
 	private final IDEPackage pkg;
22
-	private final LiveList<ProjectOverviewNode> contents;
26
+	private LiveList<ProjectOverviewNode> contents;
23 27
 	
24 28
 	public PackageTreeNode(IDEWindow window, IDEPackage pkg) {
29
+		this.window = window;
30
+		this.pkg = pkg;
31
+	}
32
+	
33
+	public PackageTreeNode(IDEWindow window, IDEModule module, IDEPackage pkg) {
34
+		this.window = window;
35
+		this.module = module;
25 36
 		this.pkg = pkg;
26 37
 		
38
+		init(module);
39
+	}
40
+	
41
+	protected final void init(IDEModule module) {
42
+		this.module = module;
27 43
 		contents = new LiveConcatList<>(
28
-				new LiveMappedList<>(pkg.getSubPackages(), sub -> new PackageTreeNode(window, sub)),
44
+				new LiveMappedList<>(pkg.getSubPackages(), sub -> new PackageTreeNode(window, module, sub)),
29 45
 				new LiveMappedList<>(pkg.getSourceFiles(), source -> new SourceFileTreeNode(window, source))
30 46
 		);
31 47
 	}
48
+	
49
+	@Override
50
+	public void close() {
51
+		contents.close();
52
+	}
32 53
 
33 54
 	@Override
34 55
 	public LiveList<ProjectOverviewNode> getChildren() {
@@ -54,4 +75,9 @@ public class PackageTreeNode extends ProjectOverviewNode {
54 75
 	public boolean isLeaf() {
55 76
 		return false;
56 77
 	}
78
+	
79
+	@Override
80
+	public void onMouseClick(DMouseEvent e) {
81
+		window.setContextPackage(module, pkg);
82
+	}
57 83
 }

+ 3
- 3
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/ProjectOverviewNode.java 查看文件

@@ -5,7 +5,7 @@
5 5
  */
6 6
 package org.openzen.zenscript.ide.ui.view.project;
7 7
 
8
-import org.openzen.drawablegui.live.LiveBool;
8
+import org.openzen.drawablegui.live.MutableLiveBool;
9 9
 import org.openzen.drawablegui.live.SimpleLiveBool;
10 10
 import org.openzen.drawablegui.tree.DTreeNode;
11 11
 
@@ -14,12 +14,12 @@ import org.openzen.drawablegui.tree.DTreeNode;
14 14
  * @author Hoofdgebruiker
15 15
  */
16 16
 public abstract class ProjectOverviewNode implements DTreeNode<ProjectOverviewNode> {
17
-	private final LiveBool collapsed = new SimpleLiveBool();
17
+	private final MutableLiveBool collapsed = new SimpleLiveBool();
18 18
 	
19 19
 	public abstract Kind getKind();
20 20
 	
21 21
 	@Override
22
-	public LiveBool isCollapsed() {
22
+	public MutableLiveBool isCollapsed() {
23 23
 		return collapsed;
24 24
 	}
25 25
 	

+ 5
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/ProjectTreeNode.java 查看文件

@@ -29,6 +29,11 @@ public class ProjectTreeNode extends ProjectOverviewNode {
29 29
 		modules = new LiveMappedList<>(host.getModules(), module -> new ModuleTreeNode(window, module));
30 30
 	}
31 31
 	
32
+	@Override
33
+	public void close(){
34
+		modules.close();
35
+	}
36
+	
32 37
 	@Override
33 38
 	public DColorableIcon getIcon() {
34 39
 		return ProjectIcon.INSTANCE;

+ 5
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/RootTreeNode.java 查看文件

@@ -29,6 +29,11 @@ public class RootTreeNode extends ProjectOverviewNode {
29 29
 				new LiveMappedList<>(host.getLibraries(), library -> new LibraryTreeNode(window, library)));
30 30
 	}
31 31
 	
32
+	@Override
33
+	public void close() {
34
+		children.close();
35
+	}
36
+	
32 37
 	@Override
33 38
 	public DColorableIcon getIcon() {
34 39
 		return ProjectIcon.INSTANCE;

+ 5
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/project/SourceFileTreeNode.java 查看文件

@@ -25,6 +25,11 @@ public class SourceFileTreeNode extends ProjectOverviewNode {
25 25
 		this.window = window;
26 26
 		this.sourceFile = sourceFile;
27 27
 	}
28
+	
29
+	@Override
30
+	public void close() {
31
+		
32
+	}
28 33
 
29 34
 	@Override
30 35
 	public Kind getKind() {

+ 1
- 1
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedCallArguments.java 查看文件

@@ -131,7 +131,7 @@ public class ParsedCallArguments {
131 131
 			innerScope = scope.forCall(candidates.get(0));
132 132
 		} else {
133 133
 			candidates = candidates.stream()
134
-					.filter(candidate -> candidate.typeParameters == null)
134
+					.filter(candidate -> candidate.getNumberOfTypeParameters() == 0)
135 135
 					.collect(Collectors.toList());
136 136
 			
137 137
 			if (candidates.isEmpty()) {

+ 2
- 1
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionFunction.java 查看文件

@@ -78,7 +78,8 @@ public class ParsedExpressionFunction extends ParsedExpression {
78 78
 		}
79 79
 		
80 80
 		FunctionTypeID functionType = scope.getTypeRegistry().getFunction(genericHeader.withGenericArguments(new GenericMapper(scope.getTypeRegistry(), scope.genericInferenceMap)));
81
-		return new FunctionExpression(position, functionType, closure, statements);
81
+		definedHeader = definedHeader.forLambda(functionType.header);
82
+		return new FunctionExpression(position, functionType, closure, definedHeader, statements);
82 83
 	}
83 84
 	
84 85
 	@Override

+ 1
- 1
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedExpressionVariable.java 查看文件

@@ -49,7 +49,7 @@ public class ParsedExpressionVariable extends ParsedExpression {
49 49
 
50 50
 	@Override
51 51
 	public IPartialExpression compile(ExpressionScope scope) {
52
-		ITypeID[] genericArguments = null;
52
+		ITypeID[] genericArguments = ITypeID.NONE;
53 53
 		if (genericParameters != null) {
54 54
 			genericArguments = new ITypeID[genericParameters.size()];
55 55
 			for (int i = 0; i < genericParameters.size(); i++) {

+ 1
- 1
Parser/src/main/java/org/openzen/zenscript/parser/type/IParsedType.java 查看文件

@@ -206,7 +206,7 @@ public interface IParsedType {
206 206
 	}
207 207
 	
208 208
 	public static ITypeID[] compileList(List<IParsedType> typeParameters, BaseScope scope) {
209
-		ITypeID[] result = null;
209
+		ITypeID[] result = ITypeID.NONE;
210 210
 		if (typeParameters != null) {
211 211
 			result = new ITypeID[typeParameters.size()];
212 212
 			for (int i = 0; i < typeParameters.size(); i++) {

Loading…
取消
儲存