Browse Source

- renamed setSurface to mount, and added unmount method

- Continued drawing optimizations, refactoring paint methods to mount methods.
- Removed the paint methods
Stan Hebben 6 years ago
parent
commit
49db3dfe47
83 changed files with 1978 additions and 819 deletions
  1. 81
    31
      DrawableGui/src/main/java/org/openzen/drawablegui/DButton.java
  2. 4
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIcon.java
  3. 104
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DColorableIconInstance.java
  4. 3
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/DComponent.java
  5. 8
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DCompositeIcon.java
  6. 4
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DDrawable.java
  7. 94
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/DDrawableInstance.java
  8. 6
    6
      DrawableGui/src/main/java/org/openzen/drawablegui/DEmptyView.java
  9. 28
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/DIRectangle.java
  10. 89
    41
      DrawableGui/src/main/java/org/openzen/drawablegui/DInputField.java
  11. 6
    19
      DrawableGui/src/main/java/org/openzen/drawablegui/DInputFieldStyle.java
  12. 30
    7
      DrawableGui/src/main/java/org/openzen/drawablegui/DLabel.java
  13. 7
    4
      DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltipComponent.java
  14. 5
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DBorder.java
  15. 6
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCompositeBorder.java
  16. 58
    34
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java
  17. 5
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java
  18. 6
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java
  19. 5
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DPaddedBorder.java
  20. 12
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/border/DSideBorder.java
  21. 1
    22
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawSurface.java
  22. 37
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawTarget.java
  23. 14
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnColorableElement.java
  24. 23
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnElement.java
  25. 1
    7
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnRectangle.java
  26. 1
    9
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnShape.java
  27. 7
    7
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnText.java
  28. 9
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/draw/DSubSurface.java
  29. 36
    20
      DrawableGui/src/main/java/org/openzen/drawablegui/form/DForm.java
  30. 10
    9
      DrawableGui/src/main/java/org/openzen/drawablegui/layout/DLinearLayout.java
  31. 17
    14
      DrawableGui/src/main/java/org/openzen/drawablegui/layout/DSideLayout.java
  32. 3
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/live/LiveMappedList.java
  33. 47
    19
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java
  34. 13
    21
      DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java
  35. 16
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/style/DBaseStyle.java
  36. 36
    7
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawSurface.java
  37. 8
    3
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnElement.java
  38. 19
    5
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnRectangle.java
  39. 25
    10
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnText.java
  40. 25
    10
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingFilledPath.java
  41. 2
    2
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingGraphicsContext.java
  42. 4
    7
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingRoot.java
  43. 24
    9
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingShadowedPath.java
  44. 28
    17
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingStrokedPath.java
  45. 32
    14
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingSubSurface.java
  46. 1
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingWindow.java
  47. 6
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/CollapsedArrow.java
  48. 6
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/ColoredCollapsedArrow.java
  49. 128
    70
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeView.java
  50. 5
    1
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeViewStyle.java
  51. 6
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedArrow.java
  52. 6
    0
      DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedColoredArrow.java
  53. 8
    0
      DrawableGuiIconConverter/src/main/java/org/openzen/drawablegui/iconconverter/Main.java
  54. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/AddBoxIcon.java
  55. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/BuildIcon.java
  56. 8
    2
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ChevronRight.java
  57. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/CloseIcon.java
  58. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/CodeIcon.java
  59. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ColoredIcon.java
  60. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/FolderIcon.java
  61. 8
    2
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/LibraryIcon.java
  62. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ModuleIcon.java
  63. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/PlayIcon.java
  64. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ProjectIcon.java
  65. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/SaveIcon.java
  66. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ScalableCloseIcon.java
  67. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ScalableMaximizeIcon.java
  68. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ScalableMinimizeIcon.java
  69. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/SettingsIcon.java
  70. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ShadedCodeIcon.java
  71. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ShadedProjectIcon.java
  72. 6
    0
      IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ShadedSaveIcon.java
  73. 85
    37
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/IconButtonControl.java
  74. 14
    11
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/StatusBarView.java
  75. 22
    15
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedView.java
  76. 67
    40
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTab.java
  77. 37
    15
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTabClose.java
  78. 6
    17
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTabStyle.java
  79. 82
    38
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarSelectorButton.java
  80. 120
    71
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarView.java
  81. 67
    32
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/WindowActionButton.java
  82. 179
    93
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/editor/SourceEditor.java
  83. 16
    14
      IDE/src/main/java/org/openzen/zenscript/ide/ui/view/output/OutputView.java

+ 81
- 31
DrawableGui/src/main/java/org/openzen/drawablegui/DButton.java View File

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

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

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

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

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

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

15
  * @author Hoofdgebruiker
15
  * @author Hoofdgebruiker
16
  */
16
  */
17
 public interface DComponent extends Closeable {
17
 public interface DComponent extends Closeable {
18
-	void setSurface(DStylePath parent, int z, DDrawSurface surface);
18
+	void mount(DStylePath parent, int z, DDrawSurface surface);
19
+	
20
+	void unmount();
19
 	
21
 	
20
 	LiveObject<DSizing> getSizing();
22
 	LiveObject<DSizing> getSizing();
21
 	
23
 	
25
 	
27
 	
26
 	void setBounds(DIRectangle bounds);
28
 	void setBounds(DIRectangle bounds);
27
 	
29
 	
28
-	void paint(DCanvas canvas);
29
-	
30
 	default void onMounted() {}
30
 	default void onMounted() {}
31
 	
31
 	
32
 	default void onUnmounted() {}
32
 	default void onUnmounted() {}

+ 8
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/DCompositeIcon.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui;
6
 package org.openzen.drawablegui;
7
 
7
 
8
+import org.openzen.drawablegui.draw.DDrawTarget;
9
+
8
 /**
10
 /**
9
  *
11
  *
10
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
25
 		base.draw(canvas, transform, color);
27
 		base.draw(canvas, transform, color);
26
 		addition.draw(canvas, transform.mul(additionTransform), color);
28
 		addition.draw(canvas, transform.mul(additionTransform), color);
27
 	}
29
 	}
30
+	
31
+	@Override
32
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
33
+		base.draw(target, z, transform, color);
34
+		addition.draw(target, z + 1, transform.mul(additionTransform), color);
35
+	}
28
 
36
 
29
 	@Override
37
 	@Override
30
 	public float getNominalWidth() {
38
 	public float getNominalWidth() {

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

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

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

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

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

22
 	private DEmptyView() {}
22
 	private DEmptyView() {}
23
 
23
 
24
 	@Override
24
 	@Override
25
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
25
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
26
+		
27
+	}
28
+	
29
+	@Override
30
+	public void unmount() {
26
 		
31
 		
27
 	}
32
 	}
28
 	
33
 	
46
 		
51
 		
47
 	}
52
 	}
48
 
53
 
49
-	@Override
50
-	public void paint(DCanvas canvas) {
51
-		
52
-	}
53
-
54
 	@Override
54
 	@Override
55
 	public void close() {
55
 	public void close() {
56
 		// nothing to clean up
56
 		// nothing to clean up

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

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

+ 89
- 41
DrawableGui/src/main/java/org/openzen/drawablegui/DInputField.java View File

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

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

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

+ 30
- 7
DrawableGui/src/main/java/org/openzen/drawablegui/DLabel.java View File

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

+ 7
- 4
DrawableGui/src/main/java/org/openzen/drawablegui/DSimpleTooltipComponent.java View File

50
 				bounds.y,
50
 				bounds.y,
51
 				style.border.getPaddingLeft() + fontMetrics.getWidth(tooltip.getValue()) + style.border.getPaddingRight(),
51
 				style.border.getPaddingLeft() + fontMetrics.getWidth(tooltip.getValue()) + style.border.getPaddingRight(),
52
 				style.border.getPaddingTop() + fontMetrics.getAscent() + fontMetrics.getDescent() + style.border.getPaddingBottom());
52
 				style.border.getPaddingTop() + fontMetrics.getAscent() + fontMetrics.getDescent() + style.border.getPaddingBottom());
53
-		surface.repaint(bounds);
54
 		
53
 		
55
 		if (text != null)
54
 		if (text != null)
56
 			text.close();
55
 			text.close();
93
 	}
92
 	}
94
 	
93
 	
95
 	@Override
94
 	@Override
96
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
95
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
97
 		this.surface = surface;
96
 		this.surface = surface;
98
 		this.z = z;
97
 		this.z = z;
99
 		
98
 		
106
 	}
105
 	}
107
 	
106
 	
108
 	@Override
107
 	@Override
109
-	public void paint(DCanvas canvas) {
110
-		
108
+	public void unmount() {
109
+		if (background != null)
110
+			background.close();
111
+		if (text != null)
112
+			text.close();
111
 	}
113
 	}
112
 	
114
 	
113
 	@Override
115
 	@Override
114
 	public void close() {
116
 	public void close() {
115
 		tooltipListener.close();
117
 		tooltipListener.close();
118
+		unmount();
116
 	}
119
 	}
117
 	
120
 	
118
 	private void calculateSize() {
121
 	private void calculateSize() {

+ 5
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/border/DBorder.java View File

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

+ 6
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCompositeBorder.java View File

62
 			total += border.getPaddingBottom();
62
 			total += border.getPaddingBottom();
63
 		return total;
63
 		return total;
64
 	}
64
 	}
65
+	
66
+	@Override
67
+	public void close() {
68
+		for (DBorder border : borders)
69
+			border.close();
70
+	}
65
 }
71
 }

+ 58
- 34
DrawableGui/src/main/java/org/openzen/drawablegui/border/DCustomWindowBorder.java View File

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

+ 5
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DEmptyBorder.java View File

43
 	public int getPaddingBottom() {
43
 	public int getPaddingBottom() {
44
 		return 0;
44
 		return 0;
45
 	}
45
 	}
46
+
47
+	@Override
48
+	public void close() {
49
+		
50
+	}
46
 }
51
 }

+ 6
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DLineBorder.java View File

58
 	public int getPaddingBottom() {
58
 	public int getPaddingBottom() {
59
 		return borderWidth;
59
 		return borderWidth;
60
 	}
60
 	}
61
+
62
+	@Override
63
+	public void close() {
64
+		if (shape != null)
65
+			shape.close();
66
+	}
61
 }
67
 }

+ 5
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/border/DPaddedBorder.java View File

54
 	public int getPaddingBottom() {
54
 	public int getPaddingBottom() {
55
 		return bottom;
55
 		return bottom;
56
 	}
56
 	}
57
+
58
+	@Override
59
+	public void close() {
60
+		
61
+	}
57
 }
62
 }

+ 12
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/border/DSideBorder.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.border;
6
 package org.openzen.drawablegui.border;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DIRectangle;
8
 import org.openzen.drawablegui.DIRectangle;
10
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
11
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
93
 	public int getPaddingBottom() {
92
 	public int getPaddingBottom() {
94
 		return bottomWidth;
93
 		return bottomWidth;
95
 	}
94
 	}
95
+
96
+	@Override
97
+	public void close() {
98
+		if (left != null)
99
+			left.close();
100
+		if (top != null)
101
+			top.close();
102
+		if (right != null)
103
+			right.close();
104
+		if (bottom != null)
105
+			bottom.close();
106
+	}
96
 }
107
 }

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

5
  */
5
  */
6
 package org.openzen.drawablegui.draw;
6
 package org.openzen.drawablegui.draw;
7
 
7
 
8
-import org.openzen.drawablegui.DFont;
9
-import org.openzen.drawablegui.DFontMetrics;
10
 import org.openzen.drawablegui.DIRectangle;
8
 import org.openzen.drawablegui.DIRectangle;
11
-import org.openzen.drawablegui.DPath;
12
-import org.openzen.drawablegui.DTransform2D;
13
 import org.openzen.drawablegui.DUIContext;
9
 import org.openzen.drawablegui.DUIContext;
14
-import org.openzen.drawablegui.style.DShadow;
15
 import org.openzen.drawablegui.style.DStyleDefinition;
10
 import org.openzen.drawablegui.style.DStyleDefinition;
16
 import org.openzen.drawablegui.style.DStylePath;
11
 import org.openzen.drawablegui.style.DStylePath;
17
 
12
 
19
  *
14
  *
20
  * @author Hoofdgebruiker
15
  * @author Hoofdgebruiker
21
  */
16
  */
22
-public interface DDrawSurface {
17
+public interface DDrawSurface extends DDrawTarget {
23
 	DUIContext getContext();
18
 	DUIContext getContext();
24
 	
19
 	
25
 	DStyleDefinition getStylesheet(DStylePath path);
20
 	DStyleDefinition getStylesheet(DStylePath path);
26
 	
21
 	
27
-	DFontMetrics getFontMetrics(DFont font);
28
-	
29
-	float getScale();
30
-	
31
-	float getTextScale();
32
-	
33
-	DDrawnText drawText(int z, DFont font, int color, float x, float y, String text);
34
-	
35
-	DDrawnRectangle fillRect(int z, DIRectangle rectangle, int color);
36
-	
37
-	DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth);
38
-	
39
-	DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color);
40
-	
41
-	DDrawnShape shadowPath(int z, DPath path, DTransform2D transform, int color, DShadow shadow);
42
-	
43
 	DSubSurface createSubSurface(int z);
22
 	DSubSurface createSubSurface(int z);
44
 	
23
 	
45
 	void repaint(int x, int y, int width, int height);
24
 	void repaint(int x, int y, int width, int height);

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

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.drawablegui.draw;
7
+
8
+import org.openzen.drawablegui.DFont;
9
+import org.openzen.drawablegui.DFontMetrics;
10
+import org.openzen.drawablegui.DIRectangle;
11
+import org.openzen.drawablegui.DPath;
12
+import org.openzen.drawablegui.DTransform2D;
13
+import org.openzen.drawablegui.style.DShadow;
14
+
15
+/**
16
+ *
17
+ * @author Hoofdgebruiker
18
+ */
19
+public interface DDrawTarget {
20
+	public static final int INSTANCE_COLOR = 1;
21
+	
22
+	DFontMetrics getFontMetrics(DFont font);
23
+	
24
+	float getScale();
25
+	
26
+	float getTextScale();
27
+	
28
+	DDrawnText drawText(int z, DFont font, int color, float x, float y, String text);
29
+	
30
+	DDrawnRectangle fillRect(int z, DIRectangle rectangle, int color);
31
+	
32
+	DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth);
33
+	
34
+	DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color);
35
+	
36
+	DDrawnShape shadowPath(int z, DPath path, DTransform2D transform, int color, DShadow shadow);
37
+}

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

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

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

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

+ 1
- 7
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnRectangle.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.draw;
6
 package org.openzen.drawablegui.draw;
7
 
7
 
8
-import java.io.Closeable;
9
 import org.openzen.drawablegui.DIRectangle;
8
 import org.openzen.drawablegui.DIRectangle;
10
 
9
 
11
 /**
10
 /**
12
  *
11
  *
13
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
14
  */
13
  */
15
-public interface DDrawnRectangle extends Closeable {
14
+public interface DDrawnRectangle extends DDrawnColorableElement {
16
 	void setRectangle(DIRectangle rectangle);
15
 	void setRectangle(DIRectangle rectangle);
17
-	
18
-	void setColor(int color);
19
-	
20
-	@Override
21
-	void close();
22
 }
16
 }

+ 1
- 9
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DDrawnShape.java View File

5
  */
5
  */
6
 package org.openzen.drawablegui.draw;
6
 package org.openzen.drawablegui.draw;
7
 
7
 
8
-import java.io.Closeable;
9
-import org.openzen.drawablegui.DTransform2D;
10
-
11
 /**
8
 /**
12
  *
9
  *
13
  * @author Hoofdgebruiker
10
  * @author Hoofdgebruiker
14
  */
11
  */
15
-public interface DDrawnShape extends Closeable {
16
-	public void setTransform(DTransform2D transform);
17
-	
18
-	public void setColor(int color);
12
+public interface DDrawnShape extends DDrawnColorableElement {
19
 	
13
 	
20
-	@Override
21
-	public void close();
22
 }
14
 }

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

5
  */
5
  */
6
 package org.openzen.drawablegui.draw;
6
 package org.openzen.drawablegui.draw;
7
 
7
 
8
-import java.io.Closeable;
8
+import org.openzen.drawablegui.DTransform2D;
9
 
9
 
10
 /**
10
 /**
11
  *
11
  *
12
  * @author Hoofdgebruiker
12
  * @author Hoofdgebruiker
13
  */
13
  */
14
-public interface DDrawnText extends Closeable {
15
-	void setPosition(float x, float y);
16
-	
17
-	void setColor(int color);
18
-	
14
+public interface DDrawnText extends DDrawnColorableElement {
19
 	@Override
15
 	@Override
20
-	void close();
16
+	default void setTransform(DTransform2D transform) { // only uses position, not scaling or rotation
17
+		setPosition(transform.xx, transform.yy);
18
+	}
19
+	
20
+	void setPosition(float x, float y);
21
 }
21
 }

+ 9
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/draw/DSubSurface.java View File

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

+ 36
- 20
DrawableGui/src/main/java/org/openzen/drawablegui/form/DForm.java View File

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

+ 10
- 9
DrawableGui/src/main/java/org/openzen/drawablegui/layout/DLinearLayout.java View File

75
 	}
75
 	}
76
 
76
 
77
 	@Override
77
 	@Override
78
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
78
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
79
 		this.surface = surface;
79
 		this.surface = surface;
80
 		this.z = z;
80
 		this.z = z;
81
 		
81
 		
83
 		style = new DLinearLayoutStyle(surface.getStylesheet(path));
83
 		style = new DLinearLayoutStyle(surface.getStylesheet(path));
84
 		
84
 		
85
 		for (Element element : components)
85
 		for (Element element : components)
86
-			element.component.setSurface(parent, z + 1, surface);
86
+			element.component.mount(parent, z + 1, surface);
87
+	}
88
+	
89
+	@Override
90
+	public void unmount() {
91
+		for (Element element : components)
92
+			element.component.unmount();
87
 	}
93
 	}
88
 
94
 
89
 	@Override
95
 	@Override
116
 		layout();
122
 		layout();
117
 	}
123
 	}
118
 
124
 
119
-	@Override
120
-	public void paint(DCanvas canvas) {
121
-		for (Element element : components) {
122
-			element.component.paint(canvas);
123
-		}
124
-	}
125
-
126
 	@Override
125
 	@Override
127
 	public void close() {
126
 	public void close() {
128
 		for (ListenerHandle<LiveObject.Listener<DSizing>> listener : componentSizeListeners) {
127
 		for (ListenerHandle<LiveObject.Listener<DSizing>> listener : componentSizeListeners) {
129
 			listener.close();
128
 			listener.close();
130
 		}
129
 		}
130
+		for (Element element : components)
131
+			element.component.close();
131
 	}
132
 	}
132
 	
133
 	
133
 	private int getInnerWidth() {
134
 	private int getInnerWidth() {

+ 17
- 14
DrawableGui/src/main/java/org/openzen/drawablegui/layout/DSideLayout.java View File

49
 	
49
 	
50
 	public void add(Side side, DComponent component) {
50
 	public void add(Side side, DComponent component) {
51
 		if (surface != null)
51
 		if (surface != null)
52
-			component.setSurface(path, z + 1, surface);
52
+			component.mount(path, z + 1, surface);
53
 		
53
 		
54
 		sides.add(new SideComponent(side, component));
54
 		sides.add(new SideComponent(side, component));
55
 	}
55
 	}
61
 		this.main = component;
61
 		this.main = component;
62
 		
62
 		
63
 		if (surface != null && bounds != null) {
63
 		if (surface != null && bounds != null) {
64
-			main.setSurface(path, z + 1, surface);
64
+			main.mount(path, z + 1, surface);
65
 			setBounds(bounds);
65
 			setBounds(bounds);
66
 			surface.repaint(bounds);
66
 			surface.repaint(bounds);
67
 		}
67
 		}
68
 	}
68
 	}
69
 
69
 
70
 	@Override
70
 	@Override
71
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
71
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
72
 		this.surface = surface;
72
 		this.surface = surface;
73
 		this.z = z;
73
 		this.z = z;
74
 		this.path = parent.getChild("sidelayout", styleClass);
74
 		this.path = parent.getChild("sidelayout", styleClass);
75
 		style = new DSideLayoutStyle(surface.getStylesheet(path));
75
 		style = new DSideLayoutStyle(surface.getStylesheet(path));
76
 		
76
 		
77
-		main.setSurface(path, z + 1, surface);
77
+		main.mount(path, z + 1, surface);
78
 		for (SideComponent side : sides)
78
 		for (SideComponent side : sides)
79
-			side.component.setSurface(path, z + 1, surface);
79
+			side.component.mount(path, z + 1, surface);
80
 		
80
 		
81
+		if (background != null)
82
+			background.close();
81
 		background = surface.fillRect(z, DIRectangle.EMPTY, style.backgroundColor);
83
 		background = surface.fillRect(z, DIRectangle.EMPTY, style.backgroundColor);
82
 	}
84
 	}
83
 	
85
 	
86
+	@Override
87
+	public void unmount() {
88
+		main.unmount();
89
+		for (SideComponent side : sides)
90
+			side.component.unmount();
91
+		
92
+		background.close();
93
+		background = null;
94
+	}
95
+	
84
 	@Override
96
 	@Override
85
 	public DIRectangle getBounds() {
97
 	public DIRectangle getBounds() {
86
 		return bounds;
98
 		return bounds;
182
 		
194
 		
183
 		main.setBounds(new DIRectangle(left, top, right - left, bottom - top));
195
 		main.setBounds(new DIRectangle(left, top, right - left, bottom - top));
184
 	}
196
 	}
185
-
186
-	@Override
187
-	public void paint(DCanvas canvas) {
188
-		//canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.backgroundColor);
189
-		main.paint(canvas);
190
-		
191
-		for (SideComponent component : sides)
192
-			component.component.paint(canvas);
193
-	}
194
 	
197
 	
195
 	private void recalculateSize() {
198
 	private void recalculateSize() {
196
 		DSizing mainPreferences = main.getSizing().getValue();
199
 		DSizing mainPreferences = main.getSizing().getValue();

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

80
 		@Override
80
 		@Override
81
 		public void onRemoved(int index, T oldValue) {
81
 		public void onRemoved(int index, T oldValue) {
82
 			U oldMappedValue = mapped.remove(index);
82
 			U oldMappedValue = mapped.remove(index);
83
+			if (oldMappedValue instanceof AutoCloseable) {
84
+				try { ((AutoCloseable) oldMappedValue).close(); } catch (Exception ex) {}
85
+			}
83
 			listeners.accept(listener -> listener.onRemoved(index, oldMappedValue));
86
 			listeners.accept(listener -> listener.onRemoved(index, oldMappedValue));
84
 		}
87
 		}
85
 	}
88
 	}

+ 47
- 19
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollBar.java View File

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

+ 13
- 21
DrawableGui/src/main/java/org/openzen/drawablegui/scroll/DScrollPane.java View File

102
 	}
102
 	}
103
 
103
 
104
 	@Override
104
 	@Override
105
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
105
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
106
 		this.surface = surface;
106
 		this.surface = surface;
107
 		
107
 		
108
 		DStylePath path = parent.getChild("scrollpane", styleClass);
108
 		DStylePath path = parent.getChild("scrollpane", styleClass);
109
 		subSurface = surface.createSubSurface(z + 1);
109
 		subSurface = surface.createSubSurface(z + 1);
110
-		contents.setSurface(path, 0, subSurface);
111
-		scrollBar.setSurface(path, z + 2, surface);
110
+		contents.mount(path, 0, subSurface);
111
+		scrollBar.mount(path, z + 2, surface);
112
 		style = new DScrollPaneStyle(surface.getStylesheet(path));
112
 		style = new DScrollPaneStyle(surface.getStylesheet(path));
113
 	}
113
 	}
114
+	
115
+	@Override
116
+	public void unmount() {
117
+		subSurface.close();
118
+		
119
+		contents.unmount();
120
+		scrollBar.unmount();
121
+	}
114
 
122
 
115
 	@Override
123
 	@Override
116
 	public LiveObject<DSizing> getSizing() {
124
 	public LiveObject<DSizing> getSizing() {
151
 		subSurface.setClip(new DIRectangle(
159
 		subSurface.setClip(new DIRectangle(
152
 				bounds.x + style.border.getPaddingLeft(),
160
 				bounds.x + style.border.getPaddingLeft(),
153
 				bounds.y + style.border.getPaddingTop(),
161
 				bounds.y + style.border.getPaddingTop(),
154
-				bounds.width - style.border.getPaddingLeft() - style.border.getPaddingTop() - scrollBar.getBounds().width,
155
-				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom()));
156
-	}
157
-
158
-	@Override
159
-	public void paint(DCanvas canvas) {
160
-		scrollBar.paint(canvas);
161
-		
162
-		canvas.pushBounds(new DIRectangle(
163
-				bounds.x + style.border.getPaddingLeft(),
164
-				bounds.y + style.border.getPaddingTop(),
165
-				bounds.width - style.border.getPaddingLeft() - style.border.getPaddingTop() - scrollBar.getBounds().width,
162
+				bounds.width - style.border.getPaddingLeft() - style.border.getPaddingTop(),
166
 				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom()));
163
 				bounds.height - style.border.getPaddingTop() - style.border.getPaddingBottom()));
167
-		canvas.pushOffset(bounds.x - offsetX.getValue(), bounds.y - offsetY.getValue());
168
-		contents.paint(canvas);
169
-		canvas.popOffset();
170
-		canvas.popBounds();
171
 	}
164
 	}
172
 	
165
 	
173
 	@Override
166
 	@Override
235
 	@Override
228
 	@Override
236
 	public void close() {
229
 	public void close() {
237
 		contents.close();
230
 		contents.close();
231
+		unmount();
238
 	}
232
 	}
239
 	
233
 	
240
 	private DMouseEvent forward(DComponent target, DMouseEvent e) {
234
 	private DMouseEvent forward(DComponent target, DMouseEvent e) {
374
 			
368
 			
375
 			if (value != offsetY.getValue())
369
 			if (value != offsetY.getValue())
376
 				offsetY.setValue(value);
370
 				offsetY.setValue(value);
377
-			if (surface != null && bounds != null)
378
-				surface.repaint(bounds);
379
 			
371
 			
380
 			subSurface.setOffset(bounds.x - offsetX.getValue(), bounds.y - offsetY.getValue());
372
 			subSurface.setOffset(bounds.x - offsetX.getValue(), bounds.y - offsetY.getValue());
381
 		}
373
 		}

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

26
 		shape = style.getShape("shape", DRectangleShape.ELEMENT);
26
 		shape = style.getShape("shape", DRectangleShape.ELEMENT);
27
 		shadow = style.getShadow("shadow", DShadow.NONE_ELEMENT);
27
 		shadow = style.getShadow("shadow", DShadow.NONE_ELEMENT);
28
 	}
28
 	}
29
+	
30
+	public DBaseStyle(DStyleDefinition style, DBorderElement defaultBorder, int defaultBackgroundColor) {
31
+		border = style.getBorder("border", defaultBorder);
32
+		backgroundColor = style.getColor("backgroundColor", defaultBackgroundColor);
33
+		margin = style.getMargin("margin", DMargin.EMPTY_ELEMENT);
34
+		shape = style.getShape("shape", DRectangleShape.ELEMENT);
35
+		shadow = style.getShadow("shadow", DShadow.NONE_ELEMENT);
36
+	}
37
+	
38
+	public DBaseStyle(DStyleDefinition style, DBorderElement defaultBorder, int defaultBackgroundColor, DShapeElement defaultShape, DShadowElement defaultShadow) {
39
+		border = style.getBorder("border", defaultBorder);
40
+		backgroundColor = style.getColor("backgroundColor", defaultBackgroundColor);
41
+		margin = style.getMargin("margin", DMargin.EMPTY_ELEMENT);
42
+		shape = style.getShape("shape", defaultShape);
43
+		shadow = style.getShadow("shadow", defaultShadow);
44
+	}
29
 }
45
 }

+ 36
- 7
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawSurface.java View File

6
 package org.openzen.drawablegui.swing;
6
 package org.openzen.drawablegui.swing;
7
 
7
 
8
 import java.awt.Graphics2D;
8
 import java.awt.Graphics2D;
9
+import java.awt.Rectangle;
9
 import java.util.ArrayList;
10
 import java.util.ArrayList;
10
 import java.util.List;
11
 import java.util.List;
11
 import org.openzen.drawablegui.DFont;
12
 import org.openzen.drawablegui.DFont;
30
 public class SwingDrawSurface implements DDrawSurface {
31
 public class SwingDrawSurface implements DDrawSurface {
31
 	private final List<SwingDrawnElement> elements = new ArrayList<>();
32
 	private final List<SwingDrawnElement> elements = new ArrayList<>();
32
 	private final SwingGraphicsContext context;
33
 	private final SwingGraphicsContext context;
34
+	public int offsetX;
35
+	public int offsetY;
33
 	
36
 	
34
-	public SwingDrawSurface(SwingGraphicsContext context) {
37
+	public SwingDrawSurface(SwingGraphicsContext context, int offsetX, int offsetY) {
35
 		this.context = context;
38
 		this.context = context;
39
+		this.offsetX = offsetX;
40
+		this.offsetY = offsetY;
36
 	}
41
 	}
37
 	
42
 	
38
-	public void paint(Graphics2D g) {
43
+	public void setOffset(int offsetX, int offsetY) {
44
+		this.offsetX = offsetX;
45
+		this.offsetY = offsetY;
46
+	}
47
+	
48
+	public void paint(Graphics2D g, DIRectangle clip) {
39
 		for (SwingDrawnElement element : elements)
49
 		for (SwingDrawnElement element : elements)
40
-			element.paint(g);
50
+			if (clip == null || clip.overlaps(element.getBounds()))
51
+				element.paint(g, clip);
52
+	}
53
+	
54
+	public DIRectangle calculateBounds() {
55
+		if (elements.isEmpty())
56
+			return DIRectangle.EMPTY;
57
+		
58
+		DIRectangle result = elements.get(0).getBounds();
59
+		for (SwingDrawnElement element : elements)
60
+			result = result.union(element.getBounds());
61
+		return result;
41
 	}
62
 	}
42
 
63
 
43
 	@Override
64
 	@Override
67
 
88
 
68
 	@Override
89
 	@Override
69
 	public DDrawnText drawText(int z, DFont font, int color, float x, float y, String text) {
90
 	public DDrawnText drawText(int z, DFont font, int color, float x, float y, String text) {
70
-		return addElement(new SwingDrawnText(this, z, x, y, color, font, text));
91
+		DFontMetrics fontMetrics = context.getFontMetrics(font);
92
+		return addElement(new SwingDrawnText(this, z, x, y, color, font, text, fontMetrics.getAscent(), fontMetrics.getDescent(), fontMetrics.getWidth(text)));
71
 	}
93
 	}
72
 
94
 
73
 	@Override
95
 	@Override
74
 	public DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth) {
96
 	public DDrawnShape strokePath(int z, DPath path, DTransform2D transform, int color, float lineWidth) {
75
-		return addElement(new SwingStrokedPath(this, z, transform, color, context.getPath(path), lineWidth));
97
+		return addElement(new SwingStrokedPath(this, z, transform, color, path, context.getPath(path), lineWidth));
76
 	}
98
 	}
77
 	
99
 	
78
 	@Override
100
 	@Override
82
 
104
 
83
 	@Override
105
 	@Override
84
 	public DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color) {
106
 	public DDrawnShape fillPath(int z, DPath path, DTransform2D transform, int color) {
85
-		return addElement(new SwingFilledPath(this, z, transform, context.getPath(path), color));
107
+		return addElement(new SwingFilledPath(this, z, transform, path, context.getPath(path), color));
86
 	}
108
 	}
87
 
109
 
88
 	@Override
110
 	@Override
101
 	
123
 	
102
 	public void remove(SwingDrawnElement element) {
124
 	public void remove(SwingDrawnElement element) {
103
 		elements.remove(element);
125
 		elements.remove(element);
126
+		repaint(element.getBounds());
104
 	}
127
 	}
105
 
128
 
106
 	@Override
129
 	@Override
107
 	public void repaint(int x, int y, int width, int height) {
130
 	public void repaint(int x, int y, int width, int height) {
108
-		context.repaint(x, y, width, height);
131
+		context.repaint(x + offsetX, y + offsetY, width, height);
132
+	}
133
+	
134
+	@Override
135
+	public void repaint(DIRectangle rectangle) {
136
+		context.repaint(rectangle.offset(offsetX, offsetY));
109
 	}
137
 	}
110
 	
138
 	
111
 	private <T extends SwingDrawnElement> T addElement(T element) {
139
 	private <T extends SwingDrawnElement> T addElement(T element) {
114
 			index--;
142
 			index--;
115
 		
143
 		
116
 		elements.add(index, element);
144
 		elements.add(index, element);
145
+		repaint(element.getBounds());
117
 		return element;
146
 		return element;
118
 	}
147
 	}
119
 }
148
 }

+ 8
- 3
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnElement.java View File

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

+ 19
- 5
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnRectangle.java View File

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

+ 25
- 10
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingDrawnText.java View File

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

+ 25
- 10
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingFilledPath.java View File

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

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

165
 		
165
 		
166
 		Point rootLocation = swingWindow.swingComponent.getLocationOnScreen();
166
 		Point rootLocation = swingWindow.swingComponent.getLocationOnScreen();
167
 		
167
 		
168
-		root.setSurface(DStylePathRoot.INSTANCE, 0, windowContext.surface);
168
+		root.mount(DStylePathRoot.INSTANCE, 0, windowContext.surface);
169
 		DSizing dimension = root.getSizing().getValue();
169
 		DSizing dimension = root.getSizing().getValue();
170
 		int tx = (int)(x + rootLocation.x - anchor.alignX * dimension.preferredWidth);
170
 		int tx = (int)(x + rootLocation.x - anchor.alignX * dimension.preferredWidth);
171
 		int ty = (int)(y + rootLocation.y - anchor.alignY * dimension.preferredHeight);
171
 		int ty = (int)(y + rootLocation.y - anchor.alignY * dimension.preferredHeight);
187
 		windowContext.graphics = this.graphics; // help a little...
187
 		windowContext.graphics = this.graphics; // help a little...
188
 		windowContext.setSurface(window.swingComponent.surface);
188
 		windowContext.setSurface(window.swingComponent.surface);
189
 		
189
 		
190
-		root.setSurface(DStylePathRoot.INSTANCE, 0, windowContext.surface);
190
+		root.mount(DStylePathRoot.INSTANCE, 0, windowContext.surface);
191
 		DSizing dimension = root.getSizing().getValue();
191
 		DSizing dimension = root.getSizing().getValue();
192
 		
192
 		
193
 		Point rootLocation = swingWindow.swingComponent.getLocationOnScreen();
193
 		Point rootLocation = swingWindow.swingComponent.getLocationOnScreen();

+ 4
- 7
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingRoot.java View File

50
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
50
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
51
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
51
 				Toolkit.getDefaultToolkit().getScreenResolution() / 96.0f,
52
 				this);
52
 				this);
53
-		surface = new SwingDrawSurface(context);
53
+		surface = new SwingDrawSurface(context, 0, 0);
54
 		context.setSurface(surface);
54
 		context.setSurface(surface);
55
 		
55
 		
56
 		addComponentListener(this);
56
 		addComponentListener(this);
79
 	public void paint(Graphics g) {
79
 	public void paint(Graphics g) {
80
 		if (firstPaint) {
80
 		if (firstPaint) {
81
 			firstPaint = false;
81
 			firstPaint = false;
82
-			component.setSurface(DStylePathRoot.INSTANCE, 0, surface);
82
+			component.mount(DStylePathRoot.INSTANCE, 0, surface);
83
 			component.setBounds(new DIRectangle(0, 0, getWidth(), getHeight()));
83
 			component.setBounds(new DIRectangle(0, 0, getWidth(), getHeight()));
84
 		}
84
 		}
85
 		
85
 		
89
 		Graphics2D g2d = (Graphics2D) g;
89
 		Graphics2D g2d = (Graphics2D) g;
90
 		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
90
 		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
91
 		g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
91
 		g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
92
+		surface.paint(g2d, clipBounds2);
92
 		
93
 		
93
-		surface.paint(g2d);
94
-		SwingCanvas canvas = new SwingCanvas(g2d, context, clipBounds2);
95
-		component.paint(canvas);
96
-		
97
-		System.out.println("Paint in " + (System.currentTimeMillis() - start) + " ms");
94
+		System.out.println("Paint in " + (System.currentTimeMillis() - start) + " ms, bounds: " + clipBounds.toString());
98
 	}
95
 	}
99
 
96
 
100
 	@Override
97
 	@Override

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

25
  * @author Hoofdgebruiker
25
  * @author Hoofdgebruiker
26
  */
26
  */
27
 public class SwingShadowedPath extends SwingDrawnElement implements DDrawnShape {
27
 public class SwingShadowedPath extends SwingDrawnElement implements DDrawnShape {
28
+	private final DPath originalPath;
28
 	private final GeneralPath path;
29
 	private final GeneralPath path;
29
 	private final BufferedImage shadowImage;
30
 	private final BufferedImage shadowImage;
30
 	private final DIRectangle shadowBounds;
31
 	private final DIRectangle shadowBounds;
31
 	private final int shadowOffset;
32
 	private final int shadowOffset;
32
 	
33
 	
33
-	private int color;
34
-	private DTransform2D transform;
34
+	private Color awtColor;
35
+	private AffineTransform transform;
36
+	private DIRectangle bounds;
35
 	
37
 	
36
 	public SwingShadowedPath(
38
 	public SwingShadowedPath(
37
 			SwingDrawSurface target,
39
 			SwingDrawSurface target,
43
 			DShadow shadow) {
45
 			DShadow shadow) {
44
 		super(target, z);
46
 		super(target, z);
45
 		
47
 		
46
-		this.transform = transform;
48
+		this.transform = getTransform(transform);
49
+		this.originalPath = originalPath;
47
 		this.path = path;
50
 		this.path = path;
48
-		this.color = color;
51
+		this.awtColor = new Color(color, true);
49
 		
52
 		
50
 		shadowBounds = DPathBoundsCalculator.getBounds(originalPath, transform.offset(shadow.offsetX, shadow.offsetY));
53
 		shadowBounds = DPathBoundsCalculator.getBounds(originalPath, transform.offset(shadow.offsetX, shadow.offsetY));
51
 		shadowOffset = 2 * (int)Math.ceil(shadow.radius);
54
 		shadowOffset = 2 * (int)Math.ceil(shadow.radius);
61
 		image = getGaussianBlurFilter((int)Math.ceil(shadow.radius), true).filter(image, null);
64
 		image = getGaussianBlurFilter((int)Math.ceil(shadow.radius), true).filter(image, null);
62
 		image = getGaussianBlurFilter((int)Math.ceil(shadow.radius), false).filter(image, null);
65
 		image = getGaussianBlurFilter((int)Math.ceil(shadow.radius), false).filter(image, null);
63
 		shadowImage = image;
66
 		shadowImage = image;
67
+		
68
+		bounds = new DIRectangle(
69
+				shadowBounds.x - shadowOffset,
70
+				shadowBounds.y - shadowOffset,
71
+				shadowBounds.width + 2 * shadowOffset,
72
+				shadowBounds.height + 2 * shadowOffset);
64
 	}
73
 	}
65
 
74
 
66
 	@Override
75
 	@Override
67
 	public void setTransform(DTransform2D transform) {
76
 	public void setTransform(DTransform2D transform) {
68
-		this.transform = transform;
77
+		this.transform = getTransform(transform);
78
+	}
79
+	
80
+	@Override
81
+	public DIRectangle getBounds() {
82
+		return bounds;
69
 	}
83
 	}
70
 
84
 
71
 	@Override
85
 	@Override
72
 	public void setColor(int color) {
86
 	public void setColor(int color) {
73
-		this.color = color;
87
+		this.awtColor = new Color(color, true);
88
+		invalidate();
74
 	}
89
 	}
75
 
90
 
76
 	@Override
91
 	@Override
77
-	public void paint(Graphics2D g) {
92
+	public void paint(Graphics2D g, DIRectangle clip) {
78
 		g.drawImage(shadowImage, shadowBounds.x - shadowOffset, shadowBounds.y - shadowOffset, null);
93
 		g.drawImage(shadowImage, shadowBounds.x - shadowOffset, shadowBounds.y - shadowOffset, null);
79
 		
94
 		
80
 		AffineTransform old = g.getTransform();
95
 		AffineTransform old = g.getTransform();
81
-		g.setColor(new Color(color, true));
82
-		g.transform(getTransform(transform));
96
+		g.setColor(awtColor);
97
+		g.transform(transform);
83
 		g.fill(path);
98
 		g.fill(path);
84
 		g.setTransform(old);
99
 		g.setTransform(old);
85
 	}
100
 	}

+ 28
- 17
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingStrokedPath.java View File

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

+ 32
- 14
DrawableGui/src/main/java/org/openzen/drawablegui/swing/SwingSubSurface.java View File

29
 public class SwingSubSurface extends SwingDrawnElement implements DSubSurface {
29
 public class SwingSubSurface extends SwingDrawnElement implements DSubSurface {
30
 	private final SwingDrawSurface surface;
30
 	private final SwingDrawSurface surface;
31
 	
31
 	
32
-	private int offsetX = 0;
33
-	private int offsetY = 0;
34
 	private DIRectangle clip = null;
32
 	private DIRectangle clip = null;
35
 	
33
 	
36
 	public SwingSubSurface(SwingDrawSurface parent, int z) {
34
 	public SwingSubSurface(SwingDrawSurface parent, int z) {
37
 		super(parent, z);
35
 		super(parent, z);
38
 		
36
 		
39
-		this.surface = new SwingDrawSurface(parent.getContext());
37
+		this.surface = new SwingDrawSurface(parent.getContext(), 0, 0);
40
 	}
38
 	}
41
 	
39
 	
42
 	@Override
40
 	@Override
43
-	public void paint(Graphics2D g) {
41
+	public void paint(Graphics2D g, DIRectangle clip) {
44
 		Rectangle clipBounds = g.getClipBounds();
42
 		Rectangle clipBounds = g.getClipBounds();
45
-		if (clip != null) {
46
-			g.setClip(clip.x, clip.y, clip.width, clip.height);
43
+		if (this.clip != null) {
44
+			g.setClip(this.clip.x, this.clip.y, this.clip.width, this.clip.height);
47
 		}
45
 		}
48
 		
46
 		
49
 		AffineTransform oldTransform = g.getTransform();
47
 		AffineTransform oldTransform = g.getTransform();
50
-		g.transform(AffineTransform.getTranslateInstance(offsetX, offsetY));
51
-		surface.paint(g);
48
+		g.transform(AffineTransform.getTranslateInstance(surface.offsetX, surface.offsetY));
49
+		DIRectangle newClip = this.clip == null ? clip : clip.offset(-surface.offsetX, -surface.offsetY).intersect(this.clip.offset(-surface.offsetX, -surface.offsetY));
50
+		surface.paint(g, newClip);
52
 		g.setTransform(oldTransform);
51
 		g.setTransform(oldTransform);
53
 		g.setClip(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
52
 		g.setClip(clipBounds.x, clipBounds.y, clipBounds.width, clipBounds.height);
54
 	}
53
 	}
54
+	
55
+	@Override
56
+	public void setTransform(DTransform2D transform) {
57
+		setOffset((int)transform.xx, (int)transform.yy);
58
+	}
55
 
59
 
56
 	@Override
60
 	@Override
57
 	public void setOffset(int x, int y) {
61
 	public void setOffset(int x, int y) {
58
-		offsetX = x;
59
-		offsetY = y;
62
+		surface.setOffset(x, y);
63
+		repaint();
60
 	}
64
 	}
61
 
65
 
62
 	@Override
66
 	@Override
68
 	public DUIContext getContext() {
72
 	public DUIContext getContext() {
69
 		return surface.getContext();
73
 		return surface.getContext();
70
 	}
74
 	}
75
+	
76
+	@Override
77
+	public DIRectangle getBounds() {
78
+		return surface.calculateBounds();
79
+	}
71
 
80
 
72
 	@Override
81
 	@Override
73
 	public DStyleDefinition getStylesheet(DStylePath path) {
82
 	public DStyleDefinition getStylesheet(DStylePath path) {
138
 
147
 
139
 		target.repaint(left, top, right - left, bottom - top);
148
 		target.repaint(left, top, right - left, bottom - top);
140
 	}
149
 	}
150
+	
151
+	@Override
152
+	public void repaint() {
153
+		DIRectangle bounds = surface.calculateBounds().offset(surface.offsetX, surface.offsetY);
154
+		if (clip != null)
155
+			bounds = bounds.intersect(clip);
156
+		
157
+		target.repaint(bounds);
158
+	}
141
 
159
 
142
 	private int toGlobalX(int x) {
160
 	private int toGlobalX(int x) {
143
-		return x + offsetX;
161
+		return x + surface.offsetX;
144
 	}
162
 	}
145
 
163
 
146
 	private int toGlobalY(int y) {
164
 	private int toGlobalY(int y) {
147
-		return y + offsetY;
165
+		return y + surface.offsetY;
148
 	}
166
 	}
149
 
167
 
150
 	private int toLocalX(int x) {
168
 	private int toLocalX(int x) {
151
-		return x - offsetX;
169
+		return x - surface.offsetX;
152
 	}
170
 	}
153
 
171
 
154
 	private int toLocalY(int y) {
172
 	private int toLocalY(int y) {
155
-		return y - offsetY;
173
+		return y - surface.offsetY;
156
 	}
174
 	}
157
 }
175
 }

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

174
 	private void updateBounds() {
174
 	private void updateBounds() {
175
 		state.setValue(getStateFromWindowState());
175
 		state.setValue(getStateFromWindowState());
176
 		bounds.setValue(new DIRectangle(getX(), getY(), getWidth(), getHeight()));
176
 		bounds.setValue(new DIRectangle(getX(), getY(), getWidth(), getHeight()));
177
+		swingComponent.repaint();
177
 	}
178
 	}
178
 	
179
 	
179
 	private State getStateFromWindowState() {
180
 	private State getStateFromWindowState() {

+ 6
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/CollapsedArrow.java View File

8
 import org.openzen.drawablegui.DCanvas;
8
 import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DDrawable;
9
 import org.openzen.drawablegui.DDrawable;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
+import org.openzen.drawablegui.draw.DDrawTarget;
11
 
12
 
12
 /**
13
 /**
13
  *
14
  *
22
 	public void draw(DCanvas canvas, DTransform2D transform) {
23
 	public void draw(DCanvas canvas, DTransform2D transform) {
23
 		ColoredCollapsedArrow.INSTANCE.draw(canvas, transform, 0xFF000000);
24
 		ColoredCollapsedArrow.INSTANCE.draw(canvas, transform, 0xFF000000);
24
 	}
25
 	}
26
+	
27
+	@Override
28
+	public void draw(DDrawTarget target, int z, DTransform2D transform) {
29
+		ColoredCollapsedArrow.INSTANCE.draw(target, z, transform, 0xFF000000);
30
+	}
25
 
31
 
26
 	@Override
32
 	@Override
27
 	public float getNominalWidth() {
33
 	public float getNominalWidth() {

+ 6
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/ColoredCollapsedArrow.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ColoredCollapsedArrow implements DColorableIcon {
14
 public class ColoredCollapsedArrow implements DColorableIcon {
14
 	public static final ColoredCollapsedArrow INSTANCE = new ColoredCollapsedArrow();
15
 	public static final ColoredCollapsedArrow INSTANCE = new ColoredCollapsedArrow();
26
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
27
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
27
 		canvas.fillPath(PATH_0, transform, color);
28
 		canvas.fillPath(PATH_0, transform, color);
28
 	}
29
 	}
30
+	
31
+	@Override
32
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
33
+		target.fillPath(z, PATH_0, transform, color);
34
+	}
29
 
35
 
30
 	@Override
36
 	@Override
31
 	public float getNominalWidth() {
37
 	public float getNominalWidth() {

+ 128
- 70
DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeView.java View File

8
 import java.io.Closeable;
8
 import java.io.Closeable;
9
 import java.util.ArrayList;
9
 import java.util.ArrayList;
10
 import java.util.List;
10
 import java.util.List;
11
-import org.openzen.drawablegui.DCanvas;
11
+import org.openzen.drawablegui.DColorableIconInstance;
12
 import org.openzen.drawablegui.DComponent;
12
 import org.openzen.drawablegui.DComponent;
13
 import org.openzen.drawablegui.DSizing;
13
 import org.openzen.drawablegui.DSizing;
14
 import org.openzen.drawablegui.DDrawable;
14
 import org.openzen.drawablegui.DDrawable;
16
 import org.openzen.drawablegui.DMouseEvent;
16
 import org.openzen.drawablegui.DMouseEvent;
17
 import org.openzen.drawablegui.DTransform2D;
17
 import org.openzen.drawablegui.DTransform2D;
18
 import org.openzen.drawablegui.DIRectangle;
18
 import org.openzen.drawablegui.DIRectangle;
19
+import org.openzen.drawablegui.DDrawableInstance;
19
 import org.openzen.drawablegui.listeners.ListenerHandle;
20
 import org.openzen.drawablegui.listeners.ListenerHandle;
20
 import org.openzen.drawablegui.live.LiveBool;
21
 import org.openzen.drawablegui.live.LiveBool;
21
 import org.openzen.drawablegui.draw.DDrawSurface;
22
 import org.openzen.drawablegui.draw.DDrawSurface;
23
+import org.openzen.drawablegui.draw.DDrawnRectangle;
24
+import org.openzen.drawablegui.draw.DDrawnText;
22
 import org.openzen.drawablegui.live.LiveList;
25
 import org.openzen.drawablegui.live.LiveList;
23
 import org.openzen.drawablegui.live.MutableLiveObject;
26
 import org.openzen.drawablegui.live.MutableLiveObject;
24
 import org.openzen.drawablegui.style.DStyleClass;
27
 import org.openzen.drawablegui.style.DStyleClass;
31
 public class DTreeView<N extends DTreeNode<N>> implements DComponent {
34
 public class DTreeView<N extends DTreeNode<N>> implements DComponent {
32
 	private final DStyleClass styleClass;
35
 	private final DStyleClass styleClass;
33
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
36
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
34
-	private DIRectangle bounds;
37
+	private DIRectangle bounds = DIRectangle.EMPTY;
38
+	private int z;
35
 	
39
 	
36
 	private int selectedRow = -1;
40
 	private int selectedRow = -1;
37
 	private N selectedNode = null;
41
 	private N selectedNode = null;
47
 	private final boolean showRoot;
51
 	private final boolean showRoot;
48
 	private final List<Row> rows = new ArrayList<>();
52
 	private final List<Row> rows = new ArrayList<>();
49
 	
53
 	
54
+	private DDrawnRectangle background;
55
+	private DDrawnRectangle selectedBackground;
56
+	
50
 	public DTreeView(
57
 	public DTreeView(
51
 			DStyleClass styleClass,
58
 			DStyleClass styleClass,
52
 			DDrawable nodeOpenedIcon,
59
 			DDrawable nodeOpenedIcon,
63
 	}
70
 	}
64
 
71
 
65
 	@Override
72
 	@Override
66
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
73
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
67
 		this.surface = surface;
74
 		this.surface = surface;
68
 		style = new DTreeViewStyle(surface.getStylesheet(parent.getChild("tree", styleClass)));
75
 		style = new DTreeViewStyle(surface.getStylesheet(parent.getChild("tree", styleClass)));
69
 		fontMetrics = surface.getFontMetrics(style.font);
76
 		fontMetrics = surface.getFontMetrics(style.font);
70
 		
77
 		
78
+		background = surface.fillRect(z, DIRectangle.EMPTY, style.backgroundColor);
79
+		selectedBackground = surface.fillRect(z + 1, DIRectangle.EMPTY, 0);
80
+		
71
 		updateLayout();
81
 		updateLayout();
72
 	}
82
 	}
83
+	
84
+	@Override
85
+	public void unmount() {
86
+		background.close();
87
+		background = null;
88
+		selectedBackground.close();
89
+		selectedBackground = null;
90
+		
91
+		for (Row row : rows)
92
+			row.close();
93
+	}
73
 
94
 
74
 	@Override
95
 	@Override
75
 	public MutableLiveObject<DSizing> getSizing() {
96
 	public MutableLiveObject<DSizing> getSizing() {
89
 	@Override
110
 	@Override
90
 	public void setBounds(DIRectangle bounds) {
111
 	public void setBounds(DIRectangle bounds) {
91
 		this.bounds = bounds;
112
 		this.bounds = bounds;
92
-	}
93
-
94
-	@Override
95
-	public void paint(DCanvas canvas) {
96
-		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.backgroundColor);
113
+		background.setRectangle(bounds);
97
 		
114
 		
98
-		int drawX = bounds.x + style.padding;
99
-		int drawY = bounds.y + style.padding;
100
-		if (showRoot) {
101
-			paintNode(canvas, root, drawX, drawY);
102
-		} else {
103
-			for (N child : root.getChildren()) {
104
-				drawY = paintNode(canvas, child, drawX, drawY);
105
-				drawY += style.rowSpacing;
106
-			}
107
-		}
115
+		for (Row row : rows)
116
+			row.setBounds(bounds);
108
 	}
117
 	}
109
 	
118
 	
110
 	@Override
119
 	@Override
111
 	public void onMouseClick(DMouseEvent e) {
120
 	public void onMouseClick(DMouseEvent e) {
112
-		int row = yToRow(e.y);
113
-		if (row >= 0 && row < rows.size()) {
114
-			Row rowEntry = rows.get(row);
121
+		int rowIndex = yToRow(e.y);
122
+		if (rowIndex >= 0 && rowIndex < rows.size()) {
123
+			Row rowEntry = rows.get(rowIndex);
115
 			if (e.x >= rowEntry.x && e.x < (rowEntry.x + nodeOpenedIcon.getNominalWidth())) {
124
 			if (e.x >= rowEntry.x && e.x < (rowEntry.x + nodeOpenedIcon.getNominalWidth())) {
116
 				if (!rowEntry.node.isLeaf())
125
 				if (!rowEntry.node.isLeaf())
117
 					rowEntry.node.isCollapsed().toggle();
126
 					rowEntry.node.isCollapsed().toggle();
120
 			
129
 			
121
 			rowEntry.node.onMouseClick(e);
130
 			rowEntry.node.onMouseClick(e);
122
 			
131
 			
123
-			if (e.isSingleClick()) {
124
-				int oldRow = selectedRow;
125
-				selectedRow = row;
126
-				selectedNode = rows.get(row).node;
127
-
128
-				if (oldRow >= 0)
132
+			if (e.isSingleClick() && rowIndex != selectedRow) {
133
+				int oldRowIndex = selectedRow;
134
+				
135
+				selectedRow = rowIndex;
136
+				Row row = rows.get(rowIndex);
137
+				selectedNode = row.node;
138
+				
139
+				int selectionX = bounds.x + style.padding + row.x - style.selectedPaddingLeft;
140
+				int selectionY = bounds.y + style.padding + rowIndex * (style.rowSpacing + fontMetrics.getAscent() + fontMetrics.getDescent()) - style.selectedPaddingTop;
141
+				int selectionWidth = (int)(fontMetrics.getWidth(row.node.getTitle())
142
+						+ style.iconTextSpacing
143
+						+ row.icon.getNominalWidth()
144
+						+ style.iconTextSpacing
145
+						+ row.node.getIcon().getNominalWidth()
146
+						+ style.selectedPaddingLeft
147
+						+ style.selectedPaddingRight);
148
+				int selectionHeight = fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom;
149
+				
150
+				if (row.node.isLeaf()) {
151
+					int delta = (int)(row.icon.getNominalWidth() + style.iconTextSpacing);
152
+					selectionX += delta;
153
+					selectionWidth -= delta;
154
+				}
155
+				
156
+				selectedBackground.setRectangle(new DIRectangle(
157
+						selectionX,
158
+						selectionY,
159
+						selectionWidth,
160
+						selectionHeight));
161
+				selectedBackground.setColor(style.selectedBackgroundColor);
162
+				row.text.setColor(style.selectedNodeTextColor);
163
+				row.nodeIcon.setColor(style.selectedNodeTextColor);
164
+				
165
+				if (oldRowIndex >= 0) {
129
 					surface.repaint(
166
 					surface.repaint(
130
 							bounds.x,
167
 							bounds.x,
131
-							rowToY(oldRow) - style.selectedPaddingTop,
168
+							rowToY(oldRowIndex) - style.selectedPaddingTop,
132
 							bounds.width,
169
 							bounds.width,
133
 							fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom);
170
 							fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom);
171
+					Row oldRow = rows.get(oldRowIndex);
172
+					oldRow.text.setColor(style.nodeTextColor);
173
+					oldRow.nodeIcon.setColor(style.nodeTextColor);
174
+				}
134
 				surface.repaint(
175
 				surface.repaint(
135
 						bounds.x,
176
 						bounds.x,
136
-						rowToY(row) - style.selectedPaddingTop,
177
+						rowToY(rowIndex) - style.selectedPaddingTop,
137
 						bounds.width,
178
 						bounds.width,
138
 						fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom);
179
 						fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom);
139
 			}
180
 			}
148
 		return (y - bounds.y - style.padding) / (style.rowSpacing + fontMetrics.getAscent() + fontMetrics.getDescent());
189
 		return (y - bounds.y - style.padding) / (style.rowSpacing + fontMetrics.getAscent() + fontMetrics.getDescent());
149
 	}
190
 	}
150
 	
191
 	
151
-	private int paintNode(DCanvas canvas, N node, int drawX, int drawY) {
152
-		int textColor = style.nodeTextColor;
153
-		if (node == selectedNode) {
154
-			textColor = style.selectedNodeTextColor;
155
-			canvas.fillRectangle(
156
-					bounds.x,
157
-					drawY - style.selectedPaddingTop,
158
-					bounds.width,
159
-					fontMetrics.getAscent() + fontMetrics.getDescent() + style.selectedPaddingTop + style.selectedPaddingBottom,
160
-					style.selectedBackgroundColor);
161
-		}
162
-		
163
-		int drawingX = drawX;
164
-		if (!node.isLeaf()) {
165
-			DDrawable icon = node.isCollapsed().getValue() ? nodeClosedIcon : nodeOpenedIcon;
166
-			icon.draw(canvas, DTransform2D.translate(drawingX, drawY + fontMetrics.getAscent() + fontMetrics.getDescent() - icon.getNominalHeight()));
167
-			drawingX += style.iconTextSpacing + icon.getNominalWidth();
168
-		} else {
169
-			drawingX += style.iconTextSpacing + nodeClosedIcon.getNominalWidth();
170
-		}
171
-		node.getIcon().draw(canvas, DTransform2D.translate(drawingX, drawY + fontMetrics.getAscent() + fontMetrics.getDescent() - node.getIcon().getNominalHeight()), textColor);
172
-		drawingX += style.iconTextSpacing + node.getIcon().getNominalWidth();
173
-		canvas.drawText(style.font, textColor, drawingX, drawY + fontMetrics.getAscent(), node.getTitle());
174
-		drawY += fontMetrics.getAscent() + fontMetrics.getDescent();
175
-		
176
-		if (!node.isCollapsed().getValue()) {
177
-			for (N child : node.getChildren()) {
178
-				drawY += style.rowSpacing;
179
-				drawY = paintNode(canvas, child, drawX + style.indent, drawY);
180
-			}
181
-		}
182
-		
183
-		return drawY;
184
-	}
185
-	
186
 	private void updateLayout() {
192
 	private void updateLayout() {
187
 		int oldRowCount = rows.size();
193
 		int oldRowCount = rows.size();
188
 		
194
 		
215
 	}
221
 	}
216
 	
222
 	
217
 	private void updateLayout(N node, int x) {
223
 	private void updateLayout(N node, int x) {
218
-		rows.add(new Row(x, node));
224
+		rows.add(new Row(x, rows.size(), node));
219
 		
225
 		
220
 		if (!node.isCollapsed().getValue()) {
226
 		if (!node.isCollapsed().getValue()) {
221
 			for (N child : node.getChildren()) {
227
 			for (N child : node.getChildren()) {
231
 	
237
 	
232
 	private class Row implements Closeable, LiveBool.Listener, LiveList.Listener<N> {
238
 	private class Row implements Closeable, LiveBool.Listener, LiveList.Listener<N> {
233
 		private final int x;
239
 		private final int x;
240
+		private final int index;
234
 		private final N node;
241
 		private final N node;
242
+		private final DDrawable icon;
235
 		private final ListenerHandle<LiveBool.Listener> collapseListener;
243
 		private final ListenerHandle<LiveBool.Listener> collapseListener;
236
 		private final ListenerHandle<LiveList.Listener<N>> childListener;
244
 		private final ListenerHandle<LiveList.Listener<N>> childListener;
237
 		
245
 		
238
-		public Row(int x, N node) {
246
+		private DDrawnText text;
247
+		private DDrawableInstance collapseIcon = null;
248
+		private DColorableIconInstance nodeIcon;
249
+		
250
+		public Row(int x, int index, N node) {
239
 			this.x = x;
251
 			this.x = x;
252
+			this.index = index;
240
 			this.node = node;
253
 			this.node = node;
241
 			this.collapseListener = node.isCollapsed().addListener(this);
254
 			this.collapseListener = node.isCollapsed().addListener(this);
242
 			this.childListener = node.getChildren().addListener(this);
255
 			this.childListener = node.getChildren().addListener(this);
256
+			
257
+			int baseX = bounds.x + style.padding + x;
258
+			int baseY = (int)(bounds.y + style.padding + index * (fontMetrics.getAscent() + fontMetrics.getDescent() + style.rowSpacing));
259
+			
260
+			icon = node.isCollapsed().getValue() ? nodeClosedIcon : nodeOpenedIcon;
261
+			nodeIcon = new DColorableIconInstance(
262
+					surface,
263
+					z + 2,
264
+					node.getIcon(),
265
+					DTransform2D.translate(baseX + icon.getNominalWidth() + style.iconTextSpacing, baseY + fontMetrics.getAscent() + fontMetrics.getDescent() - icon.getNominalHeight()),
266
+					style.nodeTextColor);
267
+			
268
+			if (!node.isLeaf())
269
+				collapseIcon = new DDrawableInstance(
270
+						surface, 
271
+						z + 2,
272
+						icon,
273
+						DTransform2D.translate(baseX, baseY + fontMetrics.getAscent() + fontMetrics.getDescent() - icon.getNominalHeight()));
274
+			
275
+			text = surface.drawText(
276
+					z + 2,
277
+					style.font,
278
+					style.nodeTextColor,
279
+					baseX + style.iconTextSpacing + icon.getNominalWidth() + style.iconTextSpacing + node.getIcon().getNominalWidth(),
280
+					baseY + fontMetrics.getAscent(),
281
+					node.getTitle());
282
+		}
283
+		
284
+		public void setBounds(DIRectangle bounds) {
285
+			int baseX = bounds.x + style.padding + x;
286
+			int baseY = (int)(bounds.y + style.padding + index * (fontMetrics.getAscent() + fontMetrics.getDescent() + style.rowSpacing));
287
+			
288
+			if (collapseIcon != null) {
289
+				collapseIcon.setTransform(DTransform2D.translate(
290
+						baseX,
291
+						baseY + fontMetrics.getAscent() + fontMetrics.getDescent() - icon.getNominalHeight()));
292
+			}
293
+			nodeIcon.setTransform(DTransform2D.translate(
294
+					baseX + icon.getNominalWidth() + style.iconTextSpacing,
295
+					baseY + fontMetrics.getAscent() + fontMetrics.getDescent() - icon.getNominalHeight()));
296
+			text.setPosition(
297
+					baseX + style.iconTextSpacing + icon.getNominalWidth() + style.iconTextSpacing + node.getIcon().getNominalWidth(),
298
+					baseY + fontMetrics.getAscent());
243
 		}
299
 		}
244
 
300
 
245
 		@Override
301
 		@Override
246
 		public void onChanged(boolean oldValue, boolean newValue) {
302
 		public void onChanged(boolean oldValue, boolean newValue) {
247
 			updateLayout();
303
 			updateLayout();
248
-			surface.repaint(bounds);
249
 		}
304
 		}
250
 
305
 
251
 		@Override
306
 		@Override
252
 		public void onInserted(int index, N value) {
307
 		public void onInserted(int index, N value) {
253
 			updateLayout();
308
 			updateLayout();
254
-			surface.repaint(bounds);
255
 		}
309
 		}
256
 
310
 
257
 		@Override
311
 		@Override
258
 		public void onChanged(int index, N oldValue, N newValue) {
312
 		public void onChanged(int index, N oldValue, N newValue) {
259
 			updateLayout();
313
 			updateLayout();
260
-			surface.repaint(bounds);
261
 		}
314
 		}
262
 
315
 
263
 		@Override
316
 		@Override
264
 		public void onRemoved(int index, N oldValue) {
317
 		public void onRemoved(int index, N oldValue) {
265
 			updateLayout();
318
 			updateLayout();
266
-			surface.repaint(bounds);
267
 		}
319
 		}
268
 		
320
 		
269
 		@Override
321
 		@Override
270
 		public void close() {
322
 		public void close() {
271
 			collapseListener.close();
323
 			collapseListener.close();
272
 			childListener.close();
324
 			childListener.close();
325
+			
326
+			text.close();
327
+			nodeIcon.close();
328
+			
329
+			if (collapseIcon != null)
330
+				collapseIcon.close();
273
 		}
331
 		}
274
 	}
332
 	}
275
 }
333
 }

+ 5
- 1
DrawableGui/src/main/java/org/openzen/drawablegui/tree/DTreeViewStyle.java View File

30
 	public final int selectedBackgroundColor;
30
 	public final int selectedBackgroundColor;
31
 	public final int selectedPaddingTop;
31
 	public final int selectedPaddingTop;
32
 	public final int selectedPaddingBottom;
32
 	public final int selectedPaddingBottom;
33
+	public final int selectedPaddingLeft;
34
+	public final int selectedPaddingRight;
33
 
35
 
34
 	public DTreeViewStyle(DStyleDefinition style) {
36
 	public DTreeViewStyle(DStyleDefinition style) {
35
 		backgroundColor = style.getColor("backgroundColor", 0);
37
 		backgroundColor = style.getColor("backgroundColor", 0);
36
 		borderColor = style.getColor("borderColor", 0xFF888888);
38
 		borderColor = style.getColor("borderColor", 0xFF888888);
37
 		padding = style.getDimension("padding", new DDpDimension(3));
39
 		padding = style.getDimension("padding", new DDpDimension(3));
38
 		rowSpacing = style.getDimension("rowSpacing", new DDpDimension(2));
40
 		rowSpacing = style.getDimension("rowSpacing", new DDpDimension(2));
39
-		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, context.sp(12.5f)));
41
+		font = style.getFont("font", context -> new DFont(DFontFamily.UI, false, false, false, context.sp(13)));
40
 		indent = style.getDimension("indent", new DDpDimension(12));
42
 		indent = style.getDimension("indent", new DDpDimension(12));
41
 		iconTextSpacing = style.getDimension("iconTextSpacing", new DDpDimension(2));
43
 		iconTextSpacing = style.getDimension("iconTextSpacing", new DDpDimension(2));
42
 		nodeTextColor = style.getColor("nodeTextColor", 0xFF000000);
44
 		nodeTextColor = style.getColor("nodeTextColor", 0xFF000000);
44
 		selectedBackgroundColor = style.getColor("selectedBackgroundColor", 0xFF007ACC);
46
 		selectedBackgroundColor = style.getColor("selectedBackgroundColor", 0xFF007ACC);
45
 		selectedPaddingTop = style.getDimension("selectedPaddingTop", new DDpDimension(1));
47
 		selectedPaddingTop = style.getDimension("selectedPaddingTop", new DDpDimension(1));
46
 		selectedPaddingBottom = style.getDimension("selectedPaddingBottom", new DDpDimension(1));
48
 		selectedPaddingBottom = style.getDimension("selectedPaddingBottom", new DDpDimension(1));
49
+		selectedPaddingLeft = style.getDimension("selectedPaddingLeft", new DDpDimension(2));
50
+		selectedPaddingRight = style.getDimension("selectedPaddingRight", new DDpDimension(2));
47
 	}
51
 	}
48
 }
52
 }

+ 6
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedArrow.java View File

8
 import org.openzen.drawablegui.DCanvas;
8
 import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DDrawable;
9
 import org.openzen.drawablegui.DDrawable;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
+import org.openzen.drawablegui.draw.DDrawTarget;
11
 
12
 
12
 /**
13
 /**
13
  *
14
  *
23
 		ExpandedColoredArrow.INSTANCE.draw(canvas, transform, 0xFF000000);
24
 		ExpandedColoredArrow.INSTANCE.draw(canvas, transform, 0xFF000000);
24
 	}
25
 	}
25
 
26
 
27
+	@Override
28
+	public void draw(DDrawTarget target, int z, DTransform2D transform) {
29
+		ExpandedColoredArrow.INSTANCE.draw(target, z, transform, 0xFF000000);
30
+	}
31
+
26
 	@Override
32
 	@Override
27
 	public float getNominalWidth() {
33
 	public float getNominalWidth() {
28
 		return 24;
34
 		return 24;

+ 6
- 0
DrawableGui/src/main/java/org/openzen/drawablegui/tree/ExpandedColoredArrow.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ExpandedColoredArrow implements DColorableIcon {
14
 public class ExpandedColoredArrow implements DColorableIcon {
14
 	public static final ExpandedColoredArrow INSTANCE = new ExpandedColoredArrow();
15
 	public static final ExpandedColoredArrow INSTANCE = new ExpandedColoredArrow();
26
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
27
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
27
 		canvas.fillPath(PATH_0, transform, color);
28
 		canvas.fillPath(PATH_0, transform, color);
28
 	}
29
 	}
30
+	
31
+	@Override
32
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
33
+		target.fillPath(z, PATH_0, transform, color);
34
+	}
29
 
35
 
30
 	@Override
36
 	@Override
31
 	public float getNominalWidth() {
37
 	public float getNominalWidth() {

+ 8
- 0
DrawableGuiIconConverter/src/main/java/org/openzen/drawablegui/iconconverter/Main.java View File

45
 		output.append("import org.openzen.drawablegui.DPath;\n");
45
 		output.append("import org.openzen.drawablegui.DPath;\n");
46
 		output.append("import org.openzen.drawablegui.DTransform2D;\n");
46
 		output.append("import org.openzen.drawablegui.DTransform2D;\n");
47
 		output.append("import org.openzen.drawablegui.DColorableIcon;\n");
47
 		output.append("import org.openzen.drawablegui.DColorableIcon;\n");
48
+		output.append("import org.openzen.drawablegui.draw.DDrawTarget;\n");
48
 		output.append("\n");
49
 		output.append("\n");
49
 		output.append("public class ").append(className).append(" implements DColorableIcon {\n");
50
 		output.append("public class ").append(className).append(" implements DColorableIcon {\n");
50
 		output.append("\tpublic static final ").append(className).append(" INSTANCE = new ").append(className).append("();\n");
51
 		output.append("\tpublic static final ").append(className).append(" INSTANCE = new ").append(className).append("();\n");
78
 		output.append("\t}\n");
79
 		output.append("\t}\n");
79
 		output.append("\n");
80
 		output.append("\n");
80
 		output.append("\t@Override\n");
81
 		output.append("\t@Override\n");
82
+		output.append("\tpublic void draw(DDrawTarget target, int z, DTransform2D transform) {\n");
83
+		for (String pathName : pathNames) {
84
+			output.append("\t\target.fillPath(z, ").append(pathName).append(", transform, DDrawTarget.INSTANCE_COLOR);\n");
85
+		}
86
+		output.append("\t}\n");
87
+		output.append("\n");
88
+		output.append("\t@Override\n");
81
 		output.append("\tpublic float getNominalWidth() {\n");
89
 		output.append("\tpublic float getNominalWidth() {\n");
82
 		output.append("\t\treturn ").append(width).append(";\n");
90
 		output.append("\t\treturn ").append(width).append(";\n");
83
 		output.append("\t}\n");
91
 		output.append("\t}\n");

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/AddBoxIcon.java View File

8
 import org.openzen.drawablegui.DPath;
8
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DTransform2D;
9
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DColorableIcon;
10
 import org.openzen.drawablegui.DColorableIcon;
11
+import org.openzen.drawablegui.draw.DDrawTarget;
11
 import org.openzen.drawablegui.style.DShadow;
12
 import org.openzen.drawablegui.style.DShadow;
12
 
13
 
13
 public class AddBoxIcon implements DColorableIcon {
14
 public class AddBoxIcon implements DColorableIcon {
51
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
52
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
52
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFF999999, 0, 1, 6));
53
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFF999999, 0, 1, 6));
53
 	}
54
 	}
55
+	
56
+	@Override
57
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
58
+		target.fillPath(z, PATH, transform, color);
59
+	}
54
 
60
 
55
 	@Override
61
 	@Override
56
 	public float getNominalWidth() {
62
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/BuildIcon.java View File

8
 import org.openzen.drawablegui.DPath;
8
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DTransform2D;
9
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DColorableIcon;
10
 import org.openzen.drawablegui.DColorableIcon;
11
+import org.openzen.drawablegui.draw.DDrawTarget;
11
 import org.openzen.drawablegui.style.DShadow;
12
 import org.openzen.drawablegui.style.DShadow;
12
 
13
 
13
 public class BuildIcon implements DColorableIcon {
14
 public class BuildIcon implements DColorableIcon {
38
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
39
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
39
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
40
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
40
 	}
41
 	}
42
+	
43
+	@Override
44
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
45
+		target.shadowPath(z, PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
46
+	}
41
 
47
 
42
 	@Override
48
 	@Override
43
 	public float getNominalWidth() {
49
 	public float getNominalWidth() {

+ 8
- 2
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ChevronRight.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ChevronRight implements DColorableIcon {
14
 public class ChevronRight implements DColorableIcon {
14
 	public static final ChevronRight INSTANCE = new ChevronRight();
15
 	public static final ChevronRight INSTANCE = new ChevronRight();
15
 	
16
 	
16
 	private ChevronRight() {}
17
 	private ChevronRight() {}
17
 	
18
 	
18
-	private static final DPath PATH_0 = tracer -> {
19
+	private static final DPath PATH = tracer -> {
19
 		tracer.moveTo(10f, 6f);
20
 		tracer.moveTo(10f, 6f);
20
 		tracer.lineTo(8.59f, 7.41f);
21
 		tracer.lineTo(8.59f, 7.41f);
21
 		tracer.lineTo(13.17f, 12f);
22
 		tracer.lineTo(13.17f, 12f);
27
 	
28
 	
28
 	@Override
29
 	@Override
29
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
30
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
30
-		canvas.fillPath(PATH_0, transform, color);
31
+		canvas.fillPath(PATH, transform, color);
32
+	}
33
+	
34
+	@Override
35
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
36
+		target.fillPath(z, PATH, transform, color);
31
 	}
37
 	}
32
 
38
 
33
 	@Override
39
 	@Override

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/CloseIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class CloseIcon implements DColorableIcon {
14
 public class CloseIcon implements DColorableIcon {
14
 	public static final CloseIcon INSTANCE = new CloseIcon();
15
 	public static final CloseIcon INSTANCE = new CloseIcon();
35
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
36
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
36
 		canvas.fillPath(PATH, transform, color);
37
 		canvas.fillPath(PATH, transform, color);
37
 	}
38
 	}
39
+	
40
+	@Override
41
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
42
+		target.fillPath(z, PATH, transform, color);
43
+	}
38
 
44
 
39
 	@Override
45
 	@Override
40
 	public float getNominalWidth() {
46
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/CodeIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class CodeIcon implements DColorableIcon {
14
 public class CodeIcon implements DColorableIcon {
14
 	public static final CodeIcon INSTANCE = new CodeIcon();
15
 	public static final CodeIcon INSTANCE = new CodeIcon();
40
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
41
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
41
 		canvas.fillPath(PATH, transform, color);
42
 		canvas.fillPath(PATH, transform, color);
42
 	}
43
 	}
44
+	
45
+	@Override
46
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
47
+		target.fillPath(z, PATH, transform, color);
48
+	}
43
 
49
 
44
 	@Override
50
 	@Override
45
 	public float getNominalWidth() {
51
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ColoredIcon.java View File

9
 import org.openzen.drawablegui.DColorableIcon;
9
 import org.openzen.drawablegui.DColorableIcon;
10
 import org.openzen.drawablegui.DDrawable;
10
 import org.openzen.drawablegui.DDrawable;
11
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DTransform2D;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 /**
14
 /**
14
  *
15
  *
28
 		icon.draw(canvas, transform, color);
29
 		icon.draw(canvas, transform, color);
29
 	}
30
 	}
30
 
31
 
32
+	@Override
33
+	public void draw(DDrawTarget target, int z, DTransform2D transform) {
34
+		icon.draw(target, z, transform, color);
35
+	}
36
+
31
 	@Override
37
 	@Override
32
 	public float getNominalWidth() {
38
 	public float getNominalWidth() {
33
 		return icon.getNominalWidth();
39
 		return icon.getNominalWidth();

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/FolderIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class FolderIcon implements DColorableIcon {
14
 public class FolderIcon implements DColorableIcon {
14
 	public static final FolderIcon INSTANCE = new FolderIcon();
15
 	public static final FolderIcon INSTANCE = new FolderIcon();
35
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
36
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
36
 		canvas.fillPath(PATH, transform, color);
37
 		canvas.fillPath(PATH, transform, color);
37
 	}
38
 	}
39
+	
40
+	@Override
41
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
42
+		target.fillPath(z, PATH, transform, color);
43
+	}
38
 
44
 
39
 	@Override
45
 	@Override
40
 	public float getNominalWidth() {
46
 	public float getNominalWidth() {

+ 8
- 2
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/LibraryIcon.java View File

13
 import org.openzen.drawablegui.DPath;
13
 import org.openzen.drawablegui.DPath;
14
 import org.openzen.drawablegui.DTransform2D;
14
 import org.openzen.drawablegui.DTransform2D;
15
 import org.openzen.drawablegui.DColorableIcon;
15
 import org.openzen.drawablegui.DColorableIcon;
16
+import org.openzen.drawablegui.draw.DDrawTarget;
16
 
17
 
17
 public class LibraryIcon implements DColorableIcon {
18
 public class LibraryIcon implements DColorableIcon {
18
 	public static final LibraryIcon INSTANCE = new LibraryIcon();
19
 	public static final LibraryIcon INSTANCE = new LibraryIcon();
20
 	
21
 	
21
 	private LibraryIcon() {}
22
 	private LibraryIcon() {}
22
 	
23
 	
23
-	private static final DPath PATH_0 = tracer -> {
24
+	private static final DPath PATH = tracer -> {
24
 		tracer.moveTo(20.54f, 5.23f);
25
 		tracer.moveTo(20.54f, 5.23f);
25
 		tracer.lineTo(19.15f, 3.55f);
26
 		tracer.lineTo(19.15f, 3.55f);
26
 		tracer.bezierCubic(18.88f, 3.21f, 18.47f, 3.0f, 18.0f, 3.0f);
27
 		tracer.bezierCubic(18.88f, 3.21f, 18.47f, 3.0f, 18.0f, 3.0f);
45
 	
46
 	
46
 	@Override
47
 	@Override
47
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
48
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
48
-		canvas.fillPath(PATH_0, transform, color);
49
+		canvas.fillPath(PATH, transform, color);
50
+	}
51
+	
52
+	@Override
53
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
54
+		target.fillPath(z, PATH, transform, color);
49
 	}
55
 	}
50
 
56
 
51
 	@Override
57
 	@Override

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ModuleIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ModuleIcon implements DColorableIcon {
14
 public class ModuleIcon implements DColorableIcon {
14
 	public static final ModuleIcon INSTANCE = new ModuleIcon();
15
 	public static final ModuleIcon INSTANCE = new ModuleIcon();
41
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
42
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
42
 		canvas.fillPath(PATH, transform, color);
43
 		canvas.fillPath(PATH, transform, color);
43
 	}
44
 	}
45
+	
46
+	@Override
47
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
48
+		target.fillPath(z, PATH, transform, color);
49
+	}
44
 
50
 
45
 	@Override
51
 	@Override
46
 	public float getNominalWidth() {
52
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/PlayIcon.java View File

8
 import org.openzen.drawablegui.DPath;
8
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DTransform2D;
9
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DColorableIcon;
10
 import org.openzen.drawablegui.DColorableIcon;
11
+import org.openzen.drawablegui.draw.DDrawTarget;
11
 import org.openzen.drawablegui.style.DShadow;
12
 import org.openzen.drawablegui.style.DShadow;
12
 
13
 
13
 public class PlayIcon implements DColorableIcon {
14
 public class PlayIcon implements DColorableIcon {
28
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
29
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
29
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
30
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
30
 	}
31
 	}
32
+	
33
+	@Override
34
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
35
+		target.shadowPath(z, PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
36
+	}
31
 
37
 
32
 	@Override
38
 	@Override
33
 	public float getNominalWidth() {
39
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ProjectIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ProjectIcon implements DColorableIcon {
14
 public class ProjectIcon implements DColorableIcon {
14
 	public static final ProjectIcon INSTANCE = new ProjectIcon();
15
 	public static final ProjectIcon INSTANCE = new ProjectIcon();
48
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
49
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
49
 		canvas.fillPath(PATH, transform, color);
50
 		canvas.fillPath(PATH, transform, color);
50
 	}
51
 	}
52
+	
53
+	@Override
54
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
55
+		target.fillPath(z, PATH, transform, color);
56
+	}
51
 
57
 
52
 	@Override
58
 	@Override
53
 	public float getNominalWidth() {
59
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/SaveIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class SaveIcon implements DColorableIcon {
14
 public class SaveIcon implements DColorableIcon {
14
 	public static final SaveIcon INSTANCE = new SaveIcon();
15
 	public static final SaveIcon INSTANCE = new SaveIcon();
46
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
47
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
47
 		canvas.fillPath(PATH, transform, color);
48
 		canvas.fillPath(PATH, transform, color);
48
 	}
49
 	}
50
+	
51
+	@Override
52
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
53
+		target.fillPath(z, PATH, transform, color);
54
+	}
49
 
55
 
50
 	@Override
56
 	@Override
51
 	public float getNominalWidth() {
57
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ScalableCloseIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ScalableCloseIcon implements DColorableIcon {
14
 public class ScalableCloseIcon implements DColorableIcon {
14
 	private final DPath path;
15
 	private final DPath path;
28
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
29
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
29
 		canvas.strokePath(path, transform, color, 1);
30
 		canvas.strokePath(path, transform, color, 1);
30
 	}
31
 	}
32
+	
33
+	@Override
34
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
35
+		target.strokePath(z, path, transform, color, 1);
36
+	}
31
 
37
 
32
 	@Override
38
 	@Override
33
 	public float getNominalWidth() {
39
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ScalableMaximizeIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ScalableMaximizeIcon implements DColorableIcon {
14
 public class ScalableMaximizeIcon implements DColorableIcon {
14
 	private final DPath path;
15
 	private final DPath path;
29
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
30
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
30
 		canvas.strokePath(path, transform, color, 1);
31
 		canvas.strokePath(path, transform, color, 1);
31
 	}
32
 	}
33
+	
34
+	@Override
35
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
36
+		target.strokePath(z, path, transform, color, 1);
37
+	}
32
 
38
 
33
 	@Override
39
 	@Override
34
 	public float getNominalWidth() {
40
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ScalableMinimizeIcon.java View File

9
 import org.openzen.drawablegui.DColorableIcon;
9
 import org.openzen.drawablegui.DColorableIcon;
10
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DPath;
11
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DTransform2D;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 /**
14
 /**
14
  *
15
  *
30
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
31
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
31
 		canvas.strokePath(path, transform, color, 1);
32
 		canvas.strokePath(path, transform, color, 1);
32
 	}
33
 	}
34
+	
35
+	@Override
36
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
37
+		target.strokePath(z, path, transform, color, 1);
38
+	}
33
 
39
 
34
 	@Override
40
 	@Override
35
 	public float getNominalWidth() {
41
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/SettingsIcon.java View File

8
 import org.openzen.drawablegui.DPath;
8
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DTransform2D;
9
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DColorableIcon;
10
 import org.openzen.drawablegui.DColorableIcon;
11
+import org.openzen.drawablegui.draw.DDrawTarget;
11
 import org.openzen.drawablegui.style.DShadow;
12
 import org.openzen.drawablegui.style.DShadow;
12
 
13
 
13
 public class SettingsIcon implements DColorableIcon {
14
 public class SettingsIcon implements DColorableIcon {
70
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
71
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
71
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFF888888, 0, 1, 4));
72
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFF888888, 0, 1, 4));
72
 	}
73
 	}
74
+	
75
+	@Override
76
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
77
+		target.fillPath(z, PATH, transform, color);
78
+	}
73
 
79
 
74
 	@Override
80
 	@Override
75
 	public float getNominalWidth() {
81
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ShadedCodeIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ShadedCodeIcon implements DColorableIcon {
14
 public class ShadedCodeIcon implements DColorableIcon {
14
 	public static final ShadedCodeIcon INSTANCE = new ShadedCodeIcon();
15
 	public static final ShadedCodeIcon INSTANCE = new ShadedCodeIcon();
40
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
41
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
41
 		canvas.fillPath(PATH, transform, color);
42
 		canvas.fillPath(PATH, transform, color);
42
 	}
43
 	}
44
+	
45
+	@Override
46
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
47
+		target.fillPath(z, PATH, transform, color);
48
+	}
43
 
49
 
44
 	@Override
50
 	@Override
45
 	public float getNominalWidth() {
51
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ShadedProjectIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 
13
 
13
 public class ShadedProjectIcon implements DColorableIcon {
14
 public class ShadedProjectIcon implements DColorableIcon {
14
 	public static final ShadedProjectIcon INSTANCE = new ShadedProjectIcon();
15
 	public static final ShadedProjectIcon INSTANCE = new ShadedProjectIcon();
48
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
49
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
49
 		canvas.fillPath(PATH, transform, color);
50
 		canvas.fillPath(PATH, transform, color);
50
 	}
51
 	}
52
+	
53
+	@Override
54
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
55
+		target.fillPath(z, PATH, transform, color);
56
+	}
51
 
57
 
52
 	@Override
58
 	@Override
53
 	public float getNominalWidth() {
59
 	public float getNominalWidth() {

+ 6
- 0
IDE/src/main/java/org/openzen/zenscript/ide/ui/icons/ShadedSaveIcon.java View File

9
 import org.openzen.drawablegui.DPath;
9
 import org.openzen.drawablegui.DPath;
10
 import org.openzen.drawablegui.DTransform2D;
10
 import org.openzen.drawablegui.DTransform2D;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.draw.DDrawTarget;
12
 import org.openzen.drawablegui.style.DShadow;
13
 import org.openzen.drawablegui.style.DShadow;
13
 
14
 
14
 public class ShadedSaveIcon implements DColorableIcon {
15
 public class ShadedSaveIcon implements DColorableIcon {
47
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
48
 	public void draw(DCanvas canvas, DTransform2D transform, int color) {
48
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
49
 		canvas.shadowPath(PATH, transform, color, new DShadow(0xFFCCCCCC, 0, 1, 4));
49
 	}
50
 	}
51
+	
52
+	@Override
53
+	public void draw(DDrawTarget target, int z, DTransform2D transform, int color) {
54
+		target.fillPath(z, PATH, transform, color);
55
+	}
50
 
56
 
51
 	@Override
57
 	@Override
52
 	public float getNominalWidth() {
58
 	public float getNominalWidth() {

+ 85
- 37
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/IconButtonControl.java View File

10
 import org.openzen.drawablegui.DComponent;
10
 import org.openzen.drawablegui.DComponent;
11
 import org.openzen.drawablegui.DSizing;
11
 import org.openzen.drawablegui.DSizing;
12
 import org.openzen.drawablegui.DDrawable;
12
 import org.openzen.drawablegui.DDrawable;
13
+import org.openzen.drawablegui.DDrawableInstance;
13
 import org.openzen.drawablegui.DMouseEvent;
14
 import org.openzen.drawablegui.DMouseEvent;
14
 import org.openzen.drawablegui.DPath;
15
 import org.openzen.drawablegui.DPath;
15
 import org.openzen.drawablegui.DTransform2D;
16
 import org.openzen.drawablegui.DTransform2D;
16
-import org.openzen.drawablegui.DUIContext;
17
 import org.openzen.drawablegui.DIRectangle;
17
 import org.openzen.drawablegui.DIRectangle;
18
 import org.openzen.drawablegui.DSimpleTooltip;
18
 import org.openzen.drawablegui.DSimpleTooltip;
19
 import org.openzen.drawablegui.draw.DDrawSurface;
19
 import org.openzen.drawablegui.draw.DDrawSurface;
20
+import org.openzen.drawablegui.draw.DDrawnShape;
20
 import org.openzen.drawablegui.listeners.ListenerHandle;
21
 import org.openzen.drawablegui.listeners.ListenerHandle;
21
 import org.openzen.drawablegui.live.ImmutableLiveBool;
22
 import org.openzen.drawablegui.live.ImmutableLiveBool;
22
 import org.openzen.drawablegui.live.LiveBool;
23
 import org.openzen.drawablegui.live.LiveBool;
23
 import org.openzen.drawablegui.live.LiveObject;
24
 import org.openzen.drawablegui.live.LiveObject;
24
 import org.openzen.drawablegui.live.LiveString;
25
 import org.openzen.drawablegui.live.LiveString;
25
 import org.openzen.drawablegui.live.MutableLiveObject;
26
 import org.openzen.drawablegui.live.MutableLiveObject;
27
+import org.openzen.drawablegui.style.DShadow;
26
 import org.openzen.drawablegui.style.DStyleClass;
28
 import org.openzen.drawablegui.style.DStyleClass;
27
 import org.openzen.drawablegui.style.DStylePath;
29
 import org.openzen.drawablegui.style.DStylePath;
28
 
30
 
40
 	private final DSimpleTooltip tooltip;
42
 	private final DSimpleTooltip tooltip;
41
 	
43
 	
42
 	private DDrawSurface surface;
44
 	private DDrawSurface surface;
45
+	private int z;
43
 	private IconButtonControlStyle style;
46
 	private IconButtonControlStyle style;
44
 	private DIRectangle bounds;
47
 	private DIRectangle bounds;
45
 	private final MutableLiveObject<DSizing> preferences = DSizing.create();
48
 	private final MutableLiveObject<DSizing> preferences = DSizing.create();
46
 	private boolean hover;
49
 	private boolean hover;
47
 	private boolean press;
50
 	private boolean press;
48
-	private DPath shape;
51
+	
52
+	private DShadow shadow;
53
+	private DDrawnShape shape;
54
+	private DDrawableInstance drawnIcon;
49
 	
55
 	
50
 	public IconButtonControl(DStyleClass styleClass, DDrawable icon, DDrawable iconDisabled, LiveBool disabled, LiveString tooltip, Consumer<DMouseEvent> onClick) {
56
 	public IconButtonControl(DStyleClass styleClass, DDrawable icon, DDrawable iconDisabled, LiveBool disabled, LiveString tooltip, Consumer<DMouseEvent> onClick) {
51
 		this.styleClass = styleClass;
57
 		this.styleClass = styleClass;
54
 		this.onClick = onClick;
60
 		this.onClick = onClick;
55
 		this.disabled = disabled;
61
 		this.disabled = disabled;
56
 		this.tooltip = new DSimpleTooltip(DStyleClass.EMPTY, tooltip);
62
 		this.tooltip = new DSimpleTooltip(DStyleClass.EMPTY, tooltip);
57
-		disabledListener = disabled.addListener((oldValue, newValue) -> repaint());
63
+		disabledListener = disabled.addListener((oldValue, newValue) -> onDisabledChanged(newValue));
58
 	}
64
 	}
59
 	
65
 	
60
 	public IconButtonControl(DStyleClass styleClass, DDrawable icon, LiveString tooltip, Consumer<DMouseEvent> onClick) {
66
 	public IconButtonControl(DStyleClass styleClass, DDrawable icon, LiveString tooltip, Consumer<DMouseEvent> onClick) {
62
 	}
68
 	}
63
 
69
 
64
 	@Override
70
 	@Override
65
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
71
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
66
 		this.surface = surface;
72
 		this.surface = surface;
73
+		this.z = z;
74
+		
67
 		tooltip.setContext(surface.getContext());
75
 		tooltip.setContext(surface.getContext());
68
 		
76
 		
69
 		DStylePath path = parent.getChild("iconbutton", styleClass);
77
 		DStylePath path = parent.getChild("iconbutton", styleClass);
78
 		if (bounds != null)
86
 		if (bounds != null)
79
 			setBounds(bounds);
87
 			setBounds(bounds);
80
 	}
88
 	}
89
+	
90
+	@Override
91
+	public void unmount() {
92
+		if (shape != null)
93
+			shape.close();
94
+		if (drawnIcon != null)
95
+			drawnIcon.close();
96
+	}
81
 
97
 
82
 	@Override
98
 	@Override
83
 	public LiveObject<DSizing> getSizing() {
99
 	public LiveObject<DSizing> getSizing() {
98
 	public void setBounds(DIRectangle bounds) {
114
 	public void setBounds(DIRectangle bounds) {
99
 		this.bounds = bounds;
115
 		this.bounds = bounds;
100
 		
116
 		
101
-		if (surface != null)
102
-			shape = DPath.roundedRectangle(
103
-					bounds.x + style.margin,
104
-					bounds.y + style.margin,
105
-					bounds.width - 2 * style.margin,
106
-					bounds.height - 2 * style.margin,
107
-					style.roundingRadius);
108
-	}
109
-
110
-	@Override
111
-	public void paint(DCanvas canvas) {
112
-		if (disabled.getValue()) {
113
-			canvas.shadowPath(shape, DTransform2D.IDENTITY, style.colorDisabled, style.shadowDisabled);
114
-		} else if (press) {
115
-			canvas.shadowPath(shape, DTransform2D.IDENTITY, style.colorPress, style.shadowPress);
116
-		} else if (hover) {
117
-			canvas.shadowPath(shape, DTransform2D.IDENTITY, style.colorHover, style.shadowHover);
118
-		} else {
119
-			canvas.shadowPath(shape, DTransform2D.IDENTITY, style.colorNormal, style.shadowNormal);
120
-		}
117
+		if (shape != null)
118
+			shape.close();
121
 		
119
 		
122
-		DDrawable icon = disabled.getValue() ? iconDisabled : this.icon;
123
-		icon.draw(canvas, DTransform2D.scaleAndTranslate(
124
-				bounds.x + (bounds.width - icon.getNominalWidth() * surface.getScale()) / 2,
125
-				bounds.y + (bounds.height - icon.getNominalHeight() * surface.getScale()) / 2,
126
-				surface.getScale()));
120
+		shadow = getShadow();
121
+		shape = surface.shadowPath(z, DPath.roundedRectangle(
122
+				bounds.x + style.margin,
123
+				bounds.y + style.margin,
124
+				bounds.width - 2 * style.margin,
125
+				bounds.height - 2 * style.margin,
126
+				style.roundingRadius), DTransform2D.IDENTITY, getColor(), shadow);
127
+		
128
+		onDisabledChanged(disabled.getValue());
127
 	}
129
 	}
128
 
130
 
129
 	@Override
131
 	@Override
130
 	public void close() {
132
 	public void close() {
131
 		disabledListener.close();
133
 		disabledListener.close();
134
+		unmount();
132
 	}
135
 	}
133
 	
136
 	
134
 	@Override
137
 	@Override
135
 	public void onMouseEnter(DMouseEvent e) {
138
 	public void onMouseEnter(DMouseEvent e) {
136
 		hover = true;
139
 		hover = true;
137
-		repaint();
140
+		update();
138
 		tooltip.onTargetMouseEnter(e);
141
 		tooltip.onTargetMouseEnter(e);
139
 	}
142
 	}
140
 	
143
 	
142
 	public void onMouseExit(DMouseEvent e) {
145
 	public void onMouseExit(DMouseEvent e) {
143
 		hover = false;
146
 		hover = false;
144
 		press = false;
147
 		press = false;
145
-		repaint();
148
+		update();
146
 		tooltip.onTargetMouseExit(e);
149
 		tooltip.onTargetMouseExit(e);
147
 	}
150
 	}
148
 	
151
 	
154
 	@Override
157
 	@Override
155
 	public void onMouseDown(DMouseEvent e) {
158
 	public void onMouseDown(DMouseEvent e) {
156
 		press = true;
159
 		press = true;
157
-		repaint();
160
+		update();
158
 	}
161
 	}
159
 	
162
 	
160
 	@Override
163
 	@Override
161
 	public void onMouseRelease(DMouseEvent e) {
164
 	public void onMouseRelease(DMouseEvent e) {
162
 		press = false;
165
 		press = false;
163
-		repaint();
166
+		update();
164
 	}
167
 	}
165
 	
168
 	
166
 	@Override
169
 	@Override
168
 		onClick.accept(e);
171
 		onClick.accept(e);
169
 	}
172
 	}
170
 	
173
 	
171
-	private void repaint() {
172
-		if (surface == null || bounds == null)
173
-			return;
174
+	private void onDisabledChanged(boolean disabled) {
175
+		DDrawable icon = disabled ? iconDisabled : this.icon;
176
+		
177
+		if (drawnIcon != null)
178
+			drawnIcon.close();
179
+		
180
+		drawnIcon = new DDrawableInstance(surface, z + 1, icon, DTransform2D.scaleAndTranslate(
181
+				bounds.x + (bounds.width - icon.getNominalWidth() * surface.getScale()) / 2,
182
+				bounds.y + (bounds.height - icon.getNominalHeight() * surface.getScale()) / 2,
183
+				surface.getScale()));
184
+	}
185
+	
186
+	private void update() {
187
+		DShadow newShadow = getShadow();
188
+		if (newShadow != shadow) {
189
+			if (shape != null)
190
+				shape.close();
191
+			
192
+			shadow = newShadow;
193
+			shape = surface.shadowPath(z, DPath.roundedRectangle(
194
+					bounds.x + style.margin,
195
+					bounds.y + style.margin,
196
+					bounds.width - 2 * style.margin,
197
+					bounds.height - 2 * style.margin,
198
+					style.roundingRadius), DTransform2D.IDENTITY, getColor(), shadow);
199
+		} else {
200
+			shape.setColor(getColor());
201
+		}
202
+	}
203
+	
204
+	private int getColor() {
205
+		if (disabled.getValue())
206
+			return style.colorDisabled;
207
+		if (press)
208
+			return style.colorPress;
209
+		if (hover)
210
+			return style.colorHover;
211
+		
212
+		return style.colorNormal;
213
+	}
214
+	
215
+	private DShadow getShadow() {
216
+		if (disabled.getValue())
217
+			return style.shadowDisabled;
218
+		if (press)
219
+			return style.shadowPress;
220
+		if (hover)
221
+			return style.shadowHover;
174
 		
222
 		
175
-		surface.repaint(bounds);
223
+		return style.shadowNormal;
176
 	}
224
 	}
177
 }
225
 }

+ 14
- 11
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/StatusBarView.java View File

16
 import org.openzen.drawablegui.live.SimpleLiveObject;
16
 import org.openzen.drawablegui.live.SimpleLiveObject;
17
 import org.openzen.drawablegui.draw.DDrawSurface;
17
 import org.openzen.drawablegui.draw.DDrawSurface;
18
 import org.openzen.drawablegui.draw.DDrawnShape;
18
 import org.openzen.drawablegui.draw.DDrawnShape;
19
+import org.openzen.drawablegui.draw.DDrawnText;
19
 import org.openzen.drawablegui.live.LiveString;
20
 import org.openzen.drawablegui.live.LiveString;
20
 import org.openzen.drawablegui.style.DStyleClass;
21
 import org.openzen.drawablegui.style.DStyleClass;
21
 import org.openzen.drawablegui.style.DStylePath;
22
 import org.openzen.drawablegui.style.DStylePath;
36
 	private DFontMetrics fontMetrics;
37
 	private DFontMetrics fontMetrics;
37
 
38
 
38
 	private DDrawnShape shape;
39
 	private DDrawnShape shape;
40
+	private DDrawnText text;
39
 	
41
 	
40
 	public StatusBarView(DStyleClass styleClass, LiveString content) {
42
 	public StatusBarView(DStyleClass styleClass, LiveString content) {
41
 		this.styleClass = styleClass;
43
 		this.styleClass = styleClass;
43
 	}
45
 	}
44
 	
46
 	
45
 	@Override
47
 	@Override
46
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
48
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
47
 		this.surface = surface;
49
 		this.surface = surface;
48
 		this.z = z;
50
 		this.z = z;
49
 		
51
 		
52
 		fontMetrics = surface.getFontMetrics(style.font);
54
 		fontMetrics = surface.getFontMetrics(style.font);
53
 		
55
 		
54
 		dimensionPreferences.setValue(new DSizing(0, style.paddingTop + fontMetrics.getAscent() + fontMetrics.getDescent() + style.paddingBottom));
56
 		dimensionPreferences.setValue(new DSizing(0, style.paddingTop + fontMetrics.getAscent() + fontMetrics.getDescent() + style.paddingBottom));
57
+		text = surface.drawText(z + 1, style.font, style.textColor, 0, 0, content.getValue());
58
+	}
59
+	
60
+	@Override
61
+	public void unmount() {
62
+		if (shape != null)
63
+			shape.close();
64
+		if (text != null)
65
+			text.close();
55
 	}
66
 	}
56
 	
67
 	
57
 	@Override
68
 	@Override
76
 		if (shape != null)
87
 		if (shape != null)
77
 			shape.close();
88
 			shape.close();
78
 		shape = surface.shadowPath(z, DPath.rectangle(bounds.x, bounds.y, bounds.width, bounds.height), DTransform2D.IDENTITY, style.backgroundColor, style.shadow);
89
 		shape = surface.shadowPath(z, DPath.rectangle(bounds.x, bounds.y, bounds.width, bounds.height), DTransform2D.IDENTITY, style.backgroundColor, style.shadow);
79
-	}
80
-
81
-	@Override
82
-	public void paint(DCanvas canvas) {
83
-		canvas.drawText(
84
-				style.font,
85
-				style.textColor,
86
-				bounds.x + style.paddingLeft,
87
-				bounds.y + style.paddingTop + fontMetrics.getAscent(), content.getValue());
90
+		text.setPosition(bounds.x + style.paddingLeft, bounds.y + style.paddingTop + fontMetrics.getAscent());
88
 	}
91
 	}
89
 
92
 
90
 	@Override
93
 	@Override
91
 	public void close() {
94
 	public void close() {
92
-		// nothing to clean up
95
+		unmount();
93
 	}
96
 	}
94
 }
97
 }

+ 22
- 15
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedView.java View File

15
 import org.openzen.drawablegui.DSizing;
15
 import org.openzen.drawablegui.DSizing;
16
 import org.openzen.drawablegui.DFontMetrics;
16
 import org.openzen.drawablegui.DFontMetrics;
17
 import org.openzen.drawablegui.DIRectangle;
17
 import org.openzen.drawablegui.DIRectangle;
18
-import org.openzen.drawablegui.DUIContext;
19
 import org.openzen.drawablegui.draw.DDrawSurface;
18
 import org.openzen.drawablegui.draw.DDrawSurface;
20
 import org.openzen.drawablegui.listeners.ListenerHandle;
19
 import org.openzen.drawablegui.listeners.ListenerHandle;
21
 import org.openzen.drawablegui.live.LiveArrayList;
20
 import org.openzen.drawablegui.live.LiveArrayList;
51
 	private final LiveList<TabbedViewTab> tabComponents = new LiveMappedList<>(tabs, tab -> {
50
 	private final LiveList<TabbedViewTab> tabComponents = new LiveMappedList<>(tabs, tab -> {
52
 		TabbedViewTab result = new TabbedViewTab(this, currentTab, tab);
51
 		TabbedViewTab result = new TabbedViewTab(this, currentTab, tab);
53
 		if (surface != null)
52
 		if (surface != null)
54
-			result.setSurface(path, z + 2, surface);
53
+			result.mount(path, z + 2, surface);
55
 		
54
 		
56
 		tabSizeListeners.put(result, result.getSizing().addListener((oldSize, newSize) -> layoutTabs()));
55
 		tabSizeListeners.put(result, result.getSizing().addListener((oldSize, newSize) -> layoutTabs()));
57
 		return result;
56
 		return result;
62
 		tabs.addListener(new TabListListener());
61
 		tabs.addListener(new TabListListener());
63
 		
62
 		
64
 		currentTab.addListener((oldValue, newValue) -> {
63
 		currentTab.addListener((oldValue, newValue) -> {
65
-			if (oldValue != null)
64
+			if (oldValue != null) {
66
 				oldValue.content.onUnmounted();
65
 				oldValue.content.onUnmounted();
67
-			if (newValue != null)
66
+				oldValue.content.unmount();
67
+			}
68
+			if (newValue != null) {
68
 				newValue.content.onMounted();
69
 				newValue.content.onMounted();
70
+				newValue.content.mount(path, z + 1, surface);
71
+			}
69
 			
72
 			
70
 			if (newValue != null && bounds != null) {
73
 			if (newValue != null && bounds != null) {
71
 				DIRectangle contentBounds = new DIRectangle(
74
 				DIRectangle contentBounds = new DIRectangle(
79
 	}
82
 	}
80
 	
83
 	
81
 	@Override
84
 	@Override
82
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
85
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
83
 		this.surface = surface;
86
 		this.surface = surface;
84
 		this.z = z;
87
 		this.z = z;
85
 		
88
 		
91
 		for (TabbedViewComponent tab : tabs)
94
 		for (TabbedViewComponent tab : tabs)
92
 			prepare(tab);
95
 			prepare(tab);
93
 	}
96
 	}
97
+	
98
+	@Override
99
+	public void unmount() {
100
+		for (TabbedViewComponent tab : tabs)
101
+			tab.content.unmount();
102
+		for (TabbedViewTab tab : tabComponents)
103
+			tab.unmount();
104
+	}
94
 
105
 
95
 	@Override
106
 	@Override
96
 	public LiveObject<DSizing> getSizing() {
107
 	public LiveObject<DSizing> getSizing() {
121
 		layoutTabs();
132
 		layoutTabs();
122
 	}
133
 	}
123
 
134
 
124
-	@Override
125
-	public void paint(DCanvas canvas) {
126
-		for (DComponent component : tabComponents)
127
-			component.paint(canvas);
128
-		
129
-		if (currentTab.getValue() != null)
130
-			currentTab.getValue().content.paint(canvas);
131
-	}
132
-
133
 	@Override
135
 	@Override
134
 	public void close() {
136
 	public void close() {
135
 		for (Map.Entry<TabbedViewTab, ListenerHandle<LiveObject.Listener<DSizing>>> entry : tabSizeListeners.entrySet()) {
137
 		for (Map.Entry<TabbedViewTab, ListenerHandle<LiveObject.Listener<DSizing>>> entry : tabSizeListeners.entrySet()) {
136
 			entry.getValue().close();
138
 			entry.getValue().close();
137
 		}
139
 		}
140
+		
141
+		for (TabbedViewComponent tab : tabs)
142
+			tab.content.close();
143
+		for (TabbedViewTab tab : tabComponents)
144
+			tab.close();
138
 	}
145
 	}
139
 	
146
 	
140
 	private void repaintTabs() {
147
 	private void repaintTabs() {
142
 	}
149
 	}
143
 	
150
 	
144
 	private void prepare(TabbedViewComponent tab) {
151
 	private void prepare(TabbedViewComponent tab) {
145
-		tab.content.setSurface(path, z + 1, surface);
152
+		tab.content.mount(path, z + 1, surface);
146
 	}
153
 	}
147
 	
154
 	
148
 	private void layoutTabs() {
155
 	private void layoutTabs() {

+ 67
- 40
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTab.java View File

14
 import org.openzen.drawablegui.DPath;
14
 import org.openzen.drawablegui.DPath;
15
 import org.openzen.drawablegui.DTransform2D;
15
 import org.openzen.drawablegui.DTransform2D;
16
 import org.openzen.drawablegui.draw.DDrawSurface;
16
 import org.openzen.drawablegui.draw.DDrawSurface;
17
+import org.openzen.drawablegui.draw.DDrawnShape;
18
+import org.openzen.drawablegui.draw.DDrawnText;
17
 import org.openzen.drawablegui.listeners.ListenerHandle;
19
 import org.openzen.drawablegui.listeners.ListenerHandle;
18
 import org.openzen.drawablegui.live.LiveBool;
20
 import org.openzen.drawablegui.live.LiveBool;
19
 import org.openzen.drawablegui.live.LiveObject;
21
 import org.openzen.drawablegui.live.LiveObject;
35
 	public final TabbedViewTabClose closeButton;
37
 	public final TabbedViewTabClose closeButton;
36
 	
38
 	
37
 	private DDrawSurface surface;
39
 	private DDrawSurface surface;
40
+	private int z;
38
 	private TabbedViewTabStyle style;
41
 	private TabbedViewTabStyle style;
39
 	private DFontMetrics fontMetrics;
42
 	private DFontMetrics fontMetrics;
40
 	private int textWidth;
43
 	private int textWidth;
42
 	
45
 	
43
 	private final ListenerHandle<LiveString.Listener> titleListener;
46
 	private final ListenerHandle<LiveString.Listener> titleListener;
44
 	private final ListenerHandle<LiveBool.Listener> updatedListener;
47
 	private final ListenerHandle<LiveBool.Listener> updatedListener;
48
+	private final ListenerHandle<LiveObject.Listener<TabbedViewComponent>> currentTabListener;
45
 	
49
 	
46
 	private boolean hover;
50
 	private boolean hover;
47
 	private boolean press;
51
 	private boolean press;
48
 	
52
 	
53
+	private DDrawnShape shape;
54
+	private DDrawnShape updated;
55
+	private DDrawnText text;
56
+	
49
 	public TabbedViewTab(TabbedView parent, MutableLiveObject<TabbedViewComponent> currentTab, TabbedViewComponent tab) {
57
 	public TabbedViewTab(TabbedView parent, MutableLiveObject<TabbedViewComponent> currentTab, TabbedViewComponent tab) {
50
 		this.parent = parent;
58
 		this.parent = parent;
51
 		this.currentTab = currentTab;
59
 		this.currentTab = currentTab;
54
 		
62
 		
55
 		titleListener = tab.title.addListener((oldValue, newValue) -> calculateSizing());
63
 		titleListener = tab.title.addListener((oldValue, newValue) -> calculateSizing());
56
 		updatedListener = tab.updated.addListener((oldValue, newValue) -> calculateSizing());
64
 		updatedListener = tab.updated.addListener((oldValue, newValue) -> calculateSizing());
65
+		currentTabListener = currentTab.addListener((oldTab, newTab) -> update());
57
 	}
66
 	}
58
 	
67
 	
59
 	public void closeTab() {
68
 	public void closeTab() {
61
 	}
70
 	}
62
 
71
 
63
 	@Override
72
 	@Override
64
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
73
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
65
 		this.surface = surface;
74
 		this.surface = surface;
75
+		this.z = z;
76
+		
66
 		DStylePath path = parent.getChild("tab", DStyleClass.EMPTY);
77
 		DStylePath path = parent.getChild("tab", DStyleClass.EMPTY);
67
 		style = new TabbedViewTabStyle(surface.getStylesheet(path));
78
 		style = new TabbedViewTabStyle(surface.getStylesheet(path));
68
 		fontMetrics = surface.getFontMetrics(style.tabFont);
79
 		fontMetrics = surface.getFontMetrics(style.tabFont);
69
-		closeButton.setSurface(path, z + 1, surface);
80
+		closeButton.mount(path, z + 1, surface);
70
 		
81
 		
82
+		text = surface.drawText(z + 1, style.tabFont, style.tabFontColor, 0, 0, tab.title.getValue());
71
 		calculateSizing();
83
 		calculateSizing();
72
 	}
84
 	}
73
 	
85
 	
86
+	@Override
87
+	public void unmount() {
88
+		if (shape != null)
89
+			shape.close();
90
+		if (updated != null)
91
+			updated.close();
92
+		if (text != null)
93
+			text.close();
94
+		
95
+		closeButton.close();
96
+		style.border.close();
97
+	}
98
+	
74
 	private void calculateSizing() {
99
 	private void calculateSizing() {
75
 		textWidth = fontMetrics.getWidth(tab.title.getValue());
100
 		textWidth = fontMetrics.getWidth(tab.title.getValue());
76
 		
101
 		
77
-		int width = style.paddingLeft + textWidth + style.paddingRight
102
+		int width = style.border.getPaddingHorizontal() + textWidth
78
 						+ style.closeIconPadding
103
 						+ style.closeIconPadding
79
 						+ closeButton.getSizing().getValue().preferredWidth;
104
 						+ closeButton.getSizing().getValue().preferredWidth;
80
-		
81
 		if (tab.updated.getValue()) {
105
 		if (tab.updated.getValue()) {
82
 			width += style.updatedDiameter + style.updatedPadding;
106
 			width += style.updatedDiameter + style.updatedPadding;
83
 		}
107
 		}
84
 		
108
 		
85
 		sizing.setValue(new DSizing(
109
 		sizing.setValue(new DSizing(
86
 				width,
110
 				width,
87
-				style.paddingTop + fontMetrics.getAscent() + fontMetrics.getDescent()
88
-						+ style.paddingBottom));
111
+				style.border.getPaddingHorizontal() + fontMetrics.getAscent() + fontMetrics.getDescent()));
89
 	}
112
 	}
90
 
113
 
91
 	@Override
114
 	@Override
108
 		this.bounds = bounds;
131
 		this.bounds = bounds;
109
 		
132
 		
110
 		DSizing close = closeButton.getSizing().getValue();
133
 		DSizing close = closeButton.getSizing().getValue();
134
+		style.border.update(surface, z + 1, style.margin.apply(bounds));
135
+		
111
 		closeButton.setBounds(new DIRectangle(
136
 		closeButton.setBounds(new DIRectangle(
112
-				bounds.x + bounds.width - close.preferredWidth - style.paddingRight,
137
+				bounds.x + bounds.width - close.preferredWidth - style.border.getPaddingRight(),
113
 				bounds.y + (bounds.height - close.preferredHeight) / 2,
138
 				bounds.y + (bounds.height - close.preferredHeight) / 2,
114
 				close.preferredWidth,
139
 				close.preferredWidth,
115
 				close.preferredHeight));
140
 				close.preferredHeight));
116
-	}
117
-
118
-	@Override
119
-	public void paint(DCanvas canvas) {
120
-		int width = style.paddingLeft + textWidth + style.paddingRight
121
-				+ closeButton.getSizing().getValue().preferredWidth + style.closeIconPadding;
122
-		
123
-		if (tab.updated.getValue())
124
-			width += style.updatedDiameter + style.updatedPadding;
125
-
126
-		int color = style.tabColorNormal;
127
-		if (currentTab.getValue() == tab)
128
-			color = style.tabColorActive;
129
-		else if (press)
130
-			color = style.tabColorPress;
131
-		else if (hover)
132
-			color = style.tabColorHover;
133
-
134
-		canvas.fillRectangle(bounds.x, bounds.y, width, bounds.height, color);
135
-		canvas.strokePath(DPath.rectangle(bounds.x, bounds.y, width, bounds.height), DTransform2D.IDENTITY, style.borderColor, style.borderWidth);
136
 		
141
 		
137
-		canvas.drawText(style.tabFont, style.tabFontColor, bounds.x + style.paddingLeft, bounds.y + style.paddingTop + fontMetrics.getAscent(), tab.title.getValue());
142
+		if (shape != null)
143
+			shape.close();
144
+		shape = surface.shadowPath(z, style.shape.instance(style.margin.apply(bounds)), DTransform2D.IDENTITY, style.backgroundColor, style.shadow);
145
+		text.setPosition(
146
+				bounds.x + style.margin.left + style.border.getPaddingLeft(),
147
+				bounds.y + style.margin.top + style.border.getPaddingTop() + fontMetrics.getAscent());
138
 		
148
 		
139
 		if (tab.updated.getValue()) {
149
 		if (tab.updated.getValue()) {
140
-			canvas.fillPath(
150
+			if (updated != null)
151
+				updated.close();
152
+			updated = surface.fillPath(
153
+					z + 1,
141
 					DPath.circle(
154
 					DPath.circle(
142
-						bounds.x + bounds.width - style.paddingRight - closeButton.getBounds().width - style.closeIconPadding - style.updatedDiameter / 2,
143
-						bounds.y + style.paddingTop + ((bounds.height - style.paddingTop - style.paddingBottom) / 2), style.updatedDiameter / 2),
155
+						bounds.x + bounds.width - style.margin.right - style.border.getPaddingRight() - closeButton.getBounds().width - style.closeIconPadding - style.updatedDiameter / 2,
156
+						bounds.y + style.margin.top + style.border.getPaddingTop() + ((bounds.height - style.margin.getVertical() - style.border.getPaddingVertical()) / 2), style.updatedDiameter / 2),
144
 					DTransform2D.IDENTITY,
157
 					DTransform2D.IDENTITY,
145
 					style.updatedColor);
158
 					style.updatedColor);
159
+		} else {
160
+			if (updated != null) {
161
+				updated.close();
162
+				updated = null;
163
+			}
146
 		}
164
 		}
147
-		
148
-		closeButton.paint(canvas);
149
 	}
165
 	}
150
 
166
 
151
 	@Override
167
 	@Override
152
 	public void close() {
168
 	public void close() {
153
 		titleListener.close();
169
 		titleListener.close();
154
 		updatedListener.close();
170
 		updatedListener.close();
171
+		
172
+		unmount();
155
 	}
173
 	}
156
 	
174
 	
157
 	@Override
175
 	@Override
158
 	public void onMouseEnter(DMouseEvent e) {
176
 	public void onMouseEnter(DMouseEvent e) {
159
 		hover = true;
177
 		hover = true;
160
-		repaint();
178
+		update();
161
 	}
179
 	}
162
 	
180
 	
163
 	@Override
181
 	@Override
164
 	public void onMouseExit(DMouseEvent e) {
182
 	public void onMouseExit(DMouseEvent e) {
165
 		hover = false;
183
 		hover = false;
166
 		press = false;
184
 		press = false;
167
-		repaint();
185
+		update();
168
 	}
186
 	}
169
 	
187
 	
170
 	@Override
188
 	@Override
171
 	public void onMouseDown(DMouseEvent e) {
189
 	public void onMouseDown(DMouseEvent e) {
172
 		press = true;
190
 		press = true;
173
-		repaint();
191
+		update();
174
 	}
192
 	}
175
 	
193
 	
176
 	@Override
194
 	@Override
177
 	public void onMouseRelease(DMouseEvent e) {
195
 	public void onMouseRelease(DMouseEvent e) {
178
 		press = false;
196
 		press = false;
179
-		repaint();
197
+		update();
180
 	}
198
 	}
181
 	
199
 	
182
 	@Override
200
 	@Override
184
 		currentTab.setValue(tab);
202
 		currentTab.setValue(tab);
185
 	}
203
 	}
186
 	
204
 	
187
-	private void repaint() {
188
-		if (surface != null && bounds != null)
189
-			surface.repaint(bounds);
205
+	private void update() {
206
+		if (style == null || shape == null)
207
+			return;
208
+		
209
+		int color = style.tabColorNormal;
210
+		if (currentTab.getValue() == tab)
211
+			color = style.tabColorActive;
212
+		else if (press)
213
+			color = style.tabColorPress;
214
+		else if (hover)
215
+			color = style.tabColorHover;
216
+		shape.setColor(color);
190
 	}
217
 	}
191
 }
218
 }

+ 37
- 15
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTabClose.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.ide.ui.view;
6
 package org.openzen.zenscript.ide.ui.view;
7
 
7
 
8
-import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DColorableIcon;
8
 import org.openzen.drawablegui.DColorableIcon;
9
+import org.openzen.drawablegui.DColorableIconInstance;
10
 import org.openzen.drawablegui.DComponent;
10
 import org.openzen.drawablegui.DComponent;
11
 import org.openzen.drawablegui.DSizing;
11
 import org.openzen.drawablegui.DSizing;
12
 import org.openzen.drawablegui.DIRectangle;
12
 import org.openzen.drawablegui.DIRectangle;
13
 import org.openzen.drawablegui.DMouseEvent;
13
 import org.openzen.drawablegui.DMouseEvent;
14
 import org.openzen.drawablegui.DTransform2D;
14
 import org.openzen.drawablegui.DTransform2D;
15
 import org.openzen.drawablegui.draw.DDrawSurface;
15
 import org.openzen.drawablegui.draw.DDrawSurface;
16
+import org.openzen.drawablegui.draw.DDrawnRectangle;
16
 import org.openzen.drawablegui.live.LiveObject;
17
 import org.openzen.drawablegui.live.LiveObject;
17
 import org.openzen.drawablegui.live.MutableLiveObject;
18
 import org.openzen.drawablegui.live.MutableLiveObject;
18
 import org.openzen.drawablegui.style.DStyleClass;
19
 import org.openzen.drawablegui.style.DStyleClass;
28
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
29
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
29
 	
30
 	
30
 	private DDrawSurface surface;
31
 	private DDrawSurface surface;
32
+	private int z;
31
 	private DIRectangle bounds;
33
 	private DIRectangle bounds;
32
 	private TabbedViewTabCloseStyle style;
34
 	private TabbedViewTabCloseStyle style;
33
 	private DColorableIcon icon;
35
 	private DColorableIcon icon;
35
 	private boolean hover;
37
 	private boolean hover;
36
 	private boolean press;
38
 	private boolean press;
37
 	
39
 	
40
+	private DDrawnRectangle background;
41
+	private DColorableIconInstance drawnIcon;
42
+	
38
 	public TabbedViewTabClose(TabbedViewTab tab) {
43
 	public TabbedViewTabClose(TabbedViewTab tab) {
39
 		this.tab = tab;
44
 		this.tab = tab;
40
 	}
45
 	}
41
 
46
 
42
 	@Override
47
 	@Override
43
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
48
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
44
 		this.surface = surface;
49
 		this.surface = surface;
50
+		this.z = z;
45
 		
51
 		
46
 		DStylePath path = parent.getChild("tabClose", DStyleClass.EMPTY);
52
 		DStylePath path = parent.getChild("tabClose", DStyleClass.EMPTY);
47
 		style = new TabbedViewTabCloseStyle(surface.getStylesheet(path));
53
 		style = new TabbedViewTabCloseStyle(surface.getStylesheet(path));
48
 		sizing.setValue(new DSizing(style.size, style.size));
54
 		sizing.setValue(new DSizing(style.size, style.size));
49
 		icon = new ScalableCloseIcon(style.size / 24);
55
 		icon = new ScalableCloseIcon(style.size / 24);
56
+		
57
+		if (background != null)
58
+			background.close();
59
+		background = surface.fillRect(z, DIRectangle.EMPTY, hover ? 0xFFE81123 : 0);
60
+		if (drawnIcon != null)
61
+			drawnIcon.close();
62
+		drawnIcon = new DColorableIconInstance(surface, z + 1, icon, DTransform2D.IDENTITY, 0xFF000000);
63
+	}
64
+	
65
+	@Override
66
+	public void unmount() {
67
+		if (background != null)
68
+			background.close();
69
+		if (drawnIcon != null)
70
+			drawnIcon.close();
50
 	}
71
 	}
51
 
72
 
52
 	@Override
73
 	@Override
67
 	@Override
88
 	@Override
68
 	public void setBounds(DIRectangle bounds) {
89
 	public void setBounds(DIRectangle bounds) {
69
 		this.bounds = bounds;
90
 		this.bounds = bounds;
70
-	}
71
-
72
-	@Override
73
-	public void paint(DCanvas canvas) {
74
-		if (hover) {
75
-			canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, 0xFFE81123);
76
-		}
77
 		
91
 		
78
-		icon.draw(canvas, DTransform2D.translate(
92
+		background.setRectangle(bounds);
93
+		
94
+		if (drawnIcon != null)
95
+			drawnIcon.close();
96
+		drawnIcon = new DColorableIconInstance(surface, z + 1, icon, DTransform2D.translate(
79
 				bounds.x + (bounds.width - icon.getNominalWidth()) / 2,
97
 				bounds.x + (bounds.width - icon.getNominalWidth()) / 2,
80
-				bounds.y + (bounds.height - icon.getNominalHeight()) / 2),
81
-				hover ? 0xFFFFFFFF : 0xFF000000);
98
+				bounds.y + (bounds.height - icon.getNominalHeight()) / 2), 0xFF000000);
99
+		/*drawnIcon.setTransform(DTransform2D.translate(
100
+				bounds.x + (bounds.width - icon.getNominalWidth()) / 2,
101
+				bounds.y + (bounds.height - icon.getNominalHeight()) / 2));*/
82
 	}
102
 	}
83
 
103
 
84
 	@Override
104
 	@Override
85
 	public void close() {
105
 	public void close() {
86
-		
106
+		unmount();
87
 	}
107
 	}
88
 	
108
 	
89
 	@Override
109
 	@Override
90
 	public void onMouseEnter(DMouseEvent e) {
110
 	public void onMouseEnter(DMouseEvent e) {
91
 		hover = true;
111
 		hover = true;
92
-		surface.repaint(bounds);
112
+		background.setColor(0xFFE81123);
113
+		drawnIcon.setColor(0xFFFFFFFF);
93
 	}
114
 	}
94
 	
115
 	
95
 	@Override
116
 	@Override
96
 	public void onMouseExit(DMouseEvent e) {
117
 	public void onMouseExit(DMouseEvent e) {
97
 		hover = false;
118
 		hover = false;
98
-		surface.repaint(bounds);
119
+		background.setColor(0);
120
+		drawnIcon.setColor(0xFF000000);
99
 	}
121
 	}
100
 	
122
 	
101
 	@Override
123
 	@Override

+ 6
- 17
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/TabbedViewTabStyle.java View File

7
 
7
 
8
 import org.openzen.drawablegui.DFont;
8
 import org.openzen.drawablegui.DFont;
9
 import org.openzen.drawablegui.DFontFamily;
9
 import org.openzen.drawablegui.DFontFamily;
10
+import org.openzen.drawablegui.border.DCompositeBorder;
11
+import org.openzen.drawablegui.border.DLineBorder;
12
+import org.openzen.drawablegui.border.DPaddedBorder;
13
+import org.openzen.drawablegui.style.DBaseStyle;
10
 import org.openzen.drawablegui.style.DDpDimension;
14
 import org.openzen.drawablegui.style.DDpDimension;
11
 import org.openzen.drawablegui.style.DPxDimension;
15
 import org.openzen.drawablegui.style.DPxDimension;
12
 import org.openzen.drawablegui.style.DStyleDefinition;
16
 import org.openzen.drawablegui.style.DStyleDefinition;
15
  *
19
  *
16
  * @author Hoofdgebruiker
20
  * @author Hoofdgebruiker
17
  */
21
  */
18
-public class TabbedViewTabStyle {
22
+public class TabbedViewTabStyle extends DBaseStyle {
19
 	public final DFont tabFont;
23
 	public final DFont tabFont;
20
 	public final int tabFontColor;
24
 	public final int tabFontColor;
21
 	
25
 	
24
 	public final int tabColorPress;
28
 	public final int tabColorPress;
25
 	public final int tabColorActive;
29
 	public final int tabColorActive;
26
 	
30
 	
27
-	public final int paddingTop;
28
-	public final int paddingBottom;
29
-	public final int paddingLeft;
30
-	public final int paddingRight;
31
-	
32
-	public final int borderColor;
33
-	public final int borderWidth;
34
-	
35
 	public final int closeIconSize;
31
 	public final int closeIconSize;
36
 	public final int closeIconPadding;
32
 	public final int closeIconPadding;
37
 	
33
 	
40
 	public final int updatedColor;
36
 	public final int updatedColor;
41
 	
37
 	
42
 	public TabbedViewTabStyle(DStyleDefinition style) {
38
 	public TabbedViewTabStyle(DStyleDefinition style) {
39
+		super(style, context -> new DCompositeBorder(new DLineBorder(0xFF888888, 1), new DPaddedBorder(context.dp(4))), 0);
43
 		tabFont = style.getFont("tabFont", context -> new DFont(DFontFamily.UI, false, false, false, (int)(12 * context.getScale())));
40
 		tabFont = style.getFont("tabFont", context -> new DFont(DFontFamily.UI, false, false, false, (int)(12 * context.getScale())));
44
 		tabFontColor = style.getColor("tabFontColor", 0xFF000000);
41
 		tabFontColor = style.getColor("tabFontColor", 0xFF000000);
45
 		
42
 		
48
 		tabColorPress = style.getColor("tabColorPress", 0xFFF0F0F0);
45
 		tabColorPress = style.getColor("tabColorPress", 0xFFF0F0F0);
49
 		tabColorActive = style.getColor("tabColorActive", 0xFFFFFFFF);
46
 		tabColorActive = style.getColor("tabColorActive", 0xFFFFFFFF);
50
 		
47
 		
51
-		paddingTop = style.getDimension("paddingTop", new DDpDimension(4));
52
-		paddingBottom = style.getDimension("paddingTop", new DDpDimension(4));
53
-		paddingLeft = style.getDimension("paddingLeft", new DDpDimension(4));
54
-		paddingRight = style.getDimension("paddingRight", new DDpDimension(4));
55
-		
56
-		borderColor = style.getColor("borderColor", 0xFF888888);
57
-		borderWidth = style.getDimension("borderWidth", new DPxDimension(1));
58
-		
59
 		closeIconSize = style.getDimension("closeIconSize", new DDpDimension(16));
48
 		closeIconSize = style.getDimension("closeIconSize", new DDpDimension(16));
60
 		closeIconPadding = style.getDimension("closeIconPadding", new DDpDimension(6));
49
 		closeIconPadding = style.getDimension("closeIconPadding", new DDpDimension(6));
61
 		
50
 		

+ 82
- 38
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarSelectorButton.java View File

10
 import org.openzen.drawablegui.DComponent;
10
 import org.openzen.drawablegui.DComponent;
11
 import org.openzen.drawablegui.DSizing;
11
 import org.openzen.drawablegui.DSizing;
12
 import org.openzen.drawablegui.DDrawable;
12
 import org.openzen.drawablegui.DDrawable;
13
+import org.openzen.drawablegui.DDrawableInstance;
13
 import org.openzen.drawablegui.DMouseEvent;
14
 import org.openzen.drawablegui.DMouseEvent;
14
 import org.openzen.drawablegui.DPath;
15
 import org.openzen.drawablegui.DPath;
15
 import org.openzen.drawablegui.DTransform2D;
16
 import org.openzen.drawablegui.DTransform2D;
16
 import org.openzen.drawablegui.DIRectangle;
17
 import org.openzen.drawablegui.DIRectangle;
17
 import org.openzen.drawablegui.DSimpleTooltip;
18
 import org.openzen.drawablegui.DSimpleTooltip;
18
 import org.openzen.drawablegui.draw.DDrawSurface;
19
 import org.openzen.drawablegui.draw.DDrawSurface;
20
+import org.openzen.drawablegui.draw.DDrawnShape;
19
 import org.openzen.drawablegui.listeners.ListenerHandle;
21
 import org.openzen.drawablegui.listeners.ListenerHandle;
20
 import org.openzen.drawablegui.live.ImmutableLiveString;
22
 import org.openzen.drawablegui.live.ImmutableLiveString;
21
 import org.openzen.drawablegui.live.LiveBool;
23
 import org.openzen.drawablegui.live.LiveBool;
37
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
39
 	private final MutableLiveObject<DSizing> sizing = DSizing.create();
38
 	private final Consumer<DMouseEvent> onClick;
40
 	private final Consumer<DMouseEvent> onClick;
39
 	private DDrawSurface surface;
41
 	private DDrawSurface surface;
42
+	private int z;
40
 	private AspectBarSelectorButtonStyle style;
43
 	private AspectBarSelectorButtonStyle style;
41
 	private DIRectangle bounds = DIRectangle.EMPTY;
44
 	private DIRectangle bounds = DIRectangle.EMPTY;
42
-	private DPath shape;
45
+	private DDrawnShape shape;
46
+	private DShadow shadow;
47
+	private DDrawableInstance iconInstance;
48
+	
43
 	private boolean hovering;
49
 	private boolean hovering;
44
 	private boolean pressing;
50
 	private boolean pressing;
45
 	private final DSimpleTooltip tooltip;
51
 	private final DSimpleTooltip tooltip;
53
 		this.onClick = onClick;
59
 		this.onClick = onClick;
54
 		this.tooltip = new DSimpleTooltip(DStyleClass.EMPTY, new ImmutableLiveString(tooltip));
60
 		this.tooltip = new DSimpleTooltip(DStyleClass.EMPTY, new ImmutableLiveString(tooltip));
55
 		
61
 		
56
-		activeListener = active.addListener((oldValue, newValue) -> repaint());
62
+		activeListener = active.addListener((oldValue, newValue) -> update());
57
 	}
63
 	}
58
 
64
 
59
 	@Override
65
 	@Override
60
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
66
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
61
 		this.surface = surface;
67
 		this.surface = surface;
68
+		this.z = z;
62
 		DStylePath path = parent.getChild("selectorbutton", styleClass);
69
 		DStylePath path = parent.getChild("selectorbutton", styleClass);
63
 		style = new AspectBarSelectorButtonStyle(surface.getStylesheet(path));
70
 		style = new AspectBarSelectorButtonStyle(surface.getStylesheet(path));
64
 		sizing.setValue(new DSizing(style.width, style.height));
71
 		sizing.setValue(new DSizing(style.width, style.height));
65
-		shape = DPath.roundedRectangle(
66
-				0,
67
-				0,
68
-				style.width,
69
-				style.height,
70
-				style.roundingRadius);
71
 		
72
 		
72
 		tooltip.setContext(surface.getContext());
73
 		tooltip.setContext(surface.getContext());
73
 	}
74
 	}
90
 	@Override
91
 	@Override
91
 	public void setBounds(DIRectangle bounds) {
92
 	public void setBounds(DIRectangle bounds) {
92
 		this.bounds = bounds;
93
 		this.bounds = bounds;
93
-	}
94
-
95
-	@Override
96
-	public void paint(DCanvas canvas) {
97
-		int color = style.colorNormal;
98
-		DShadow shadow = style.shadowNormal;
99
-		if (active.getValue()) {
100
-			color = style.colorActive;
101
-			shadow = style.shadowActive;
102
-		} else if (pressing) {
103
-			color = style.colorPress;
104
-			shadow = style.shadowPress;
105
-		} else if (hovering) {
106
-			color = style.colorHover;
107
-			shadow = style.shadowHover;
108
-		}
109
 		
94
 		
110
-		canvas.shadowPath(
111
-					shape,
112
-					DTransform2D.translate(bounds.x, bounds.y),
113
-					color,
114
-					shadow);
115
-		icon.draw(canvas, DTransform2D.scaleAndTranslate(
95
+		if (shape != null)
96
+			shape.close();
97
+		
98
+		shadow = getShadow();
99
+		shape = surface.shadowPath(
100
+				z,
101
+				DPath.roundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.roundingRadius),
102
+				DTransform2D.IDENTITY,
103
+				getColor(),
104
+				shadow);
105
+		
106
+		if (iconInstance != null)
107
+			iconInstance.close();
108
+		iconInstance = new DDrawableInstance(surface, z + 1, icon, DTransform2D.scaleAndTranslate(
116
 				bounds.x + (style.width - icon.getNominalWidth() * surface.getScale()) / 2,
109
 				bounds.x + (style.width - icon.getNominalWidth() * surface.getScale()) / 2,
117
 				bounds.y + (style.height - icon.getNominalHeight() * surface.getScale()) / 2,
110
 				bounds.y + (style.height - icon.getNominalHeight() * surface.getScale()) / 2,
118
 				surface.getScale()));
111
 				surface.getScale()));
119
 	}
112
 	}
120
 	
113
 	
114
+	@Override
115
+	public void unmount() {
116
+		if (shape != null)
117
+			shape.close();
118
+		if (iconInstance != null)
119
+			iconInstance.close();
120
+		
121
+		tooltip.close();
122
+	}
123
+	
121
 	@Override
124
 	@Override
122
 	public void onMouseEnter(DMouseEvent e) {
125
 	public void onMouseEnter(DMouseEvent e) {
123
 		hovering = true;
126
 		hovering = true;
124
 		tooltip.onTargetMouseEnter(e);
127
 		tooltip.onTargetMouseEnter(e);
125
-		repaint();
128
+		update();
126
 	}
129
 	}
127
 	
130
 	
128
 	@Override
131
 	@Override
135
 		hovering = false;
138
 		hovering = false;
136
 		pressing = false;
139
 		pressing = false;
137
 		tooltip.onTargetMouseExit(e);
140
 		tooltip.onTargetMouseExit(e);
138
-		repaint();
141
+		update();
139
 	}
142
 	}
140
 	
143
 	
141
 	@Override
144
 	@Override
142
 	public void onMouseDown(DMouseEvent e) {
145
 	public void onMouseDown(DMouseEvent e) {
143
 		pressing = true;
146
 		pressing = true;
144
-		repaint();
147
+		update();
145
 	}
148
 	}
146
 	
149
 	
147
 	@Override
150
 	@Override
150
 			onClick.accept(e);
153
 			onClick.accept(e);
151
 		
154
 		
152
 		pressing = false;
155
 		pressing = false;
153
-		repaint();
156
+		update();
154
 	}
157
 	}
155
 
158
 
156
 	@Override
159
 	@Override
157
 	public void close() {
160
 	public void close() {
158
 		activeListener.close();
161
 		activeListener.close();
159
 		tooltip.close();
162
 		tooltip.close();
163
+		
164
+		unmount();
165
+	}
166
+	
167
+	private void update() {
168
+		if (surface == null)
169
+			return;
170
+		
171
+		DShadow newShadow = getShadow();
172
+		if (newShadow != shadow) {
173
+			shadow = newShadow;
174
+			
175
+			if (shape != null)
176
+				shape.close();
177
+			
178
+			shape = surface.shadowPath(
179
+				z,
180
+				DPath.roundedRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.roundingRadius),
181
+				DTransform2D.IDENTITY,
182
+				getColor(),
183
+				shadow);
184
+		} else {
185
+			shape.setColor(getColor());
186
+		}
160
 	}
187
 	}
161
 	
188
 	
162
-	private void repaint() {
163
-		if (surface != null && bounds != null)
164
-			surface.repaint(bounds);
189
+	private DShadow getShadow() {
190
+		if (active.getValue())
191
+			return style.shadowActive;
192
+		if (pressing)
193
+			return style.shadowPress;
194
+		if (hovering)
195
+			return style.shadowHover;
196
+		
197
+		return style.shadowNormal;
198
+	}
199
+	
200
+	private int getColor() {
201
+		if (active.getValue())
202
+			return style.colorActive;
203
+		if (pressing)
204
+			return style.colorPress;
205
+		if (hovering)
206
+			return style.colorHover;
207
+		
208
+		return style.colorNormal;
165
 	}
209
 	}
166
 }
210
 }

+ 120
- 71
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/AspectBarView.java View File

22
 import org.openzen.drawablegui.draw.DDrawSurface;
22
 import org.openzen.drawablegui.draw.DDrawSurface;
23
 import org.openzen.drawablegui.draw.DDrawnRectangle;
23
 import org.openzen.drawablegui.draw.DDrawnRectangle;
24
 import org.openzen.drawablegui.draw.DDrawnShape;
24
 import org.openzen.drawablegui.draw.DDrawnShape;
25
+import org.openzen.drawablegui.draw.DDrawnText;
25
 import org.openzen.drawablegui.listeners.ListenerHandle;
26
 import org.openzen.drawablegui.listeners.ListenerHandle;
26
 import org.openzen.drawablegui.live.LiveBool;
27
 import org.openzen.drawablegui.live.LiveBool;
27
 import org.openzen.drawablegui.live.LiveList;
28
 import org.openzen.drawablegui.live.LiveList;
28
 import org.openzen.drawablegui.live.LiveMappedList;
29
 import org.openzen.drawablegui.live.LiveMappedList;
29
 import org.openzen.drawablegui.live.LivePredicateBool;
30
 import org.openzen.drawablegui.live.LivePredicateBool;
30
 import org.openzen.drawablegui.live.MutableLiveObject;
31
 import org.openzen.drawablegui.live.MutableLiveObject;
31
-import org.openzen.drawablegui.style.DShadow;
32
 import org.openzen.drawablegui.style.DStyleClass;
32
 import org.openzen.drawablegui.style.DStyleClass;
33
 import org.openzen.drawablegui.style.DStylePath;
33
 import org.openzen.drawablegui.style.DStylePath;
34
 import org.openzen.zenscript.ide.ui.IDEAspectBarControl;
34
 import org.openzen.zenscript.ide.ui.IDEAspectBarControl;
72
 	private DDrawnRectangle topBackground;
72
 	private DDrawnRectangle topBackground;
73
 	private DDrawnRectangle bottomBackground;
73
 	private DDrawnRectangle bottomBackground;
74
 	private DDrawnShape aspectBarShape;
74
 	private DDrawnShape aspectBarShape;
75
+	private DDrawnText activeBarText;
76
+	private DDrawnRectangle activeBarSeparator;
77
+	
78
+	private DDrawnShape windowControlsBackground;
75
 	
79
 	
76
 	public AspectBarView(DStyleClass styleClass, IDEAspectBar aspectBar) {
80
 	public AspectBarView(DStyleClass styleClass, IDEAspectBar aspectBar) {
77
 		this.styleClass = styleClass;
81
 		this.styleClass = styleClass;
98
 					LiveBool buttonActive = new LivePredicateBool<>(aspectBar.active, activeBar -> activeBar == bar);
102
 					LiveBool buttonActive = new LivePredicateBool<>(aspectBar.active, activeBar -> activeBar == bar);
99
 					AspectBarSelectorButton button = new AspectBarSelectorButton(DStyleClass.EMPTY, bar.icon, buttonActive, bar.description, e -> aspectBar.active.setValue(bar));
103
 					AspectBarSelectorButton button = new AspectBarSelectorButton(DStyleClass.EMPTY, bar.icon, buttonActive, bar.description, e -> aspectBar.active.setValue(bar));
100
 					if (surface != null)
104
 					if (surface != null)
101
-						button.setSurface(path, z + 1, surface);
105
+						button.mount(path, z + 1, surface);
102
 					
106
 					
103
 					return button;
107
 					return button;
104
 				});
108
 				});
109
 	}
113
 	}
110
 	
114
 	
111
 	@Override
115
 	@Override
112
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
116
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
113
 		this.surface = surface;
117
 		this.surface = surface;
114
 		this.z = z;
118
 		this.z = z;
115
 		this.path = parent.getChild("aspectbar", styleClass);
119
 		this.path = parent.getChild("aspectbar", styleClass);
121
 		sizing.setValue(new DSizing(0, style.height));
125
 		sizing.setValue(new DSizing(0, style.height));
122
 		
126
 		
123
 		for (DComponent selectorButton : selectorButtons)
127
 		for (DComponent selectorButton : selectorButtons)
124
-			selectorButton.setSurface(path, z + 2, surface);
128
+			selectorButton.mount(path, z + 2, surface);
125
 		
129
 		
126
 		if (activeToolbarComponents != null)
130
 		if (activeToolbarComponents != null)
127
 			for (DComponent component : activeToolbarComponents)
131
 			for (DComponent component : activeToolbarComponents)
128
-				component.setSurface(path, z + 2, surface);
132
+				component.mount(path, z + 2, surface);
129
 		
133
 		
130
-		minimize.setSurface(path, z + 2, surface);
131
-		maximizeRestore.setSurface(path, z + 2, surface);
132
-		close.setSurface(path, z + 2, surface);
134
+		minimize.mount(path, z + 2, surface);
135
+		maximizeRestore.mount(path, z + 2, surface);
136
+		close.mount(path, z + 2, surface);
133
 		
137
 		
134
 		if (topBackground != null)
138
 		if (topBackground != null)
135
 			topBackground.close();
139
 			topBackground.close();
140
 		bottomBackground = surface.fillRect(z, DIRectangle.EMPTY, style.backgroundColorBottom);
144
 		bottomBackground = surface.fillRect(z, DIRectangle.EMPTY, style.backgroundColorBottom);
141
 	}
145
 	}
142
 	
146
 	
147
+	@Override
148
+	public void unmount() {
149
+		topBackground.close();
150
+		topBackground = null;
151
+		bottomBackground.close();
152
+		bottomBackground = null;
153
+		
154
+		aspectBarShape.close();
155
+		aspectBarShape = null;
156
+		activeBarText.close();
157
+		activeBarText = null;
158
+		activeBarSeparator.close();
159
+		activeBarSeparator = null;
160
+		
161
+		if (windowControlsBackground != null) {
162
+			windowControlsBackground.close();
163
+			windowControlsBackground = null;
164
+		}
165
+	}
166
+	
143
 	@Override
167
 	@Override
144
 	public LiveObject<DSizing> getSizing() {
168
 	public LiveObject<DSizing> getSizing() {
145
 		return sizing;
169
 		return sizing;
161
 		
185
 		
162
 		if (surface != null) {
186
 		if (surface != null) {
163
 			layout();
187
 			layout();
188
+			setupActiveBarText();
164
 			surface.repaint(bounds);
189
 			surface.repaint(bounds);
165
 		}
190
 		}
166
 	}
191
 	}
167
 
192
 
168
-	@Override
169
-	public void paint(DCanvas canvas) {
170
-		canvas.pushBounds(bounds);
171
-		//canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, style.backgroundColor);
172
-		//canvas.fillRectangle(bounds.x, bounds.y + bounds.height - style.marginBottom, bounds.width, style.marginBottom, style.backgroundColorBottom);
173
-		
174
-		for (DComponent button : selectorButtons) {
175
-			if (button.getBounds() == null)
176
-				continue;
177
-			
178
-			button.paint(canvas);
179
-		}
180
-		
181
-		/*canvas.shadowPath(
182
-				aspectBarShape,
183
-				DTransform2D.IDENTITY,
184
-				style.foregroundColor,
185
-				style.aspectBarShadow);*/
186
-		
187
-		if (aspectBar.active.getValue() != null) {
188
-			int y = bounds.y
189
-					+ style.aspectBarPaddingTop
190
-					+ (int)(activeToolbarTitleFontMetrics.getAscent() * 0.35f)
191
-					+ (bounds.height - style.aspectBarPaddingTop) / 2;
192
-			int x = aspectSelectorEndX + style.aspectSelectorToToolbarSpacing;
193
-			canvas.drawText(style.activeToolbarTitleFont, style.activeToolbarTitleColor, x, y, aspectBar.active.getValue().title);
194
-			canvas.fillRectangle(
195
-					x + activeToolbarTitleFontMetrics.getWidth(aspectBar.active.getValue().title) + 8,
196
-					bounds.y + style.aspectBarPaddingTop + 8,
197
-					2,
198
-					bounds.height - style.aspectBarPaddingTop - 16,
199
-					0xFFCCCCCC);
200
-		}
201
-		
202
-		if (activeToolbarComponents != null) {
203
-			for (DComponent component : activeToolbarComponents)
204
-				component.paint(canvas);
205
-		}
206
-		
207
-		if (showWindowControls) {
208
-			canvas.shadowPath(windowControlsShape, DTransform2D.IDENTITY, style.backgroundColor, style.windowControlShadow);
209
-			minimize.paint(canvas);
210
-			maximizeRestore.paint(canvas);
211
-			close.paint(canvas);
212
-		}
213
-		
214
-		canvas.popBounds();
215
-	}
216
-
217
 	@Override
193
 	@Override
218
 	public void close() {
194
 	public void close() {
219
 		listener.close();
195
 		listener.close();
220
 		
196
 		
221
-		topBackground.close();
222
-		bottomBackground.close();
197
+		minimizeRelayout.close();
198
+		maximizeRestoreRelayout.close();
199
+		closeRelayout.close();
200
+		unmount();
223
 	}
201
 	}
224
 	
202
 	
225
 	private void onActiveChanged(IDEAspectToolbar previous, IDEAspectToolbar aspectBar) {
203
 	private void onActiveChanged(IDEAspectToolbar previous, IDEAspectToolbar aspectBar) {
226
-		if (activeToolbarComponents != null)
204
+		if (activeToolbarComponents != null) {
205
+			for (DComponent component : activeToolbarComponents)
206
+				component.close();
207
+			
227
 			activeToolbarComponents.close();
208
 			activeToolbarComponents.close();
209
+		}
228
 		
210
 		
229
 		activeToolbarComponents = new LiveMappedList<>(aspectBar.controls, control -> {
211
 		activeToolbarComponents = new LiveMappedList<>(aspectBar.controls, control -> {
230
 			DComponent result = control.instantiate();
212
 			DComponent result = control.instantiate();
231
 			if (surface != null)
213
 			if (surface != null)
232
-				result.setSurface(path, z + 2, surface);
214
+				result.mount(path, z + 2, surface);
233
 			return result;
215
 			return result;
234
 		});
216
 		});
235
 		
217
 		
218
+		setupActiveBarText();
236
 		layoutActiveToolbarComponents();
219
 		layoutActiveToolbarComponents();
237
 	}
220
 	}
238
 	
221
 	
222
+	private void setupActiveBarText() {
223
+		if (bounds == null)
224
+			return;
225
+		
226
+		if (activeBarText != null) {
227
+			activeBarText.close();
228
+			activeBarText = null;
229
+		}
230
+		if (activeBarSeparator != null) {
231
+			activeBarSeparator.close();
232
+			activeBarSeparator = null;
233
+		}
234
+		if (aspectBar.active.getValue() == null)
235
+			return;
236
+		
237
+		int y = bounds.y
238
+				+ style.aspectBarPaddingTop
239
+				+ (int)(activeToolbarTitleFontMetrics.getAscent() * 0.35f)
240
+				+ (bounds.height - style.aspectBarPaddingTop) / 2;
241
+		int x = aspectSelectorEndX + style.aspectSelectorToToolbarSpacing;
242
+		activeBarText = surface.drawText(z + 3, style.activeToolbarTitleFont, style.activeToolbarTitleColor, x, y, aspectBar.active.getValue().title);
243
+		activeBarSeparator = surface.fillRect(
244
+				z + 3,
245
+				new DIRectangle(
246
+					x + activeBarText.getBounds().width + 8,
247
+					bounds.y + style.aspectBarPaddingTop + 8,
248
+					2,
249
+					bounds.height - style.aspectBarPaddingTop - 16),
250
+				0xFFCCCCCC);
251
+	}
252
+	
239
 	private void layout() {
253
 	private void layout() {
240
 		if (bounds == null)
254
 		if (bounds == null)
241
 			return;
255
 			return;
246
 		layoutAspectSelectorButtons();
260
 		layoutAspectSelectorButtons();
247
 		layoutActiveToolbarComponents();
261
 		layoutActiveToolbarComponents();
248
 		
262
 		
249
-		int x = bounds.x + bounds.width;
250
-		DSizing closeSize = close.getSizing().getValue();
251
-		DSizing maximizeRestoreSize = maximizeRestore.getSizing().getValue();
252
-		DSizing minimizeSize = minimize.getSizing().getValue();
263
+		if (showWindowControls) {
264
+			int x = bounds.x + bounds.width;
265
+			
266
+			DSizing closeSize = close.getSizing().getValue();
267
+			DSizing maximizeRestoreSize = maximizeRestore.getSizing().getValue();
268
+			DSizing minimizeSize = minimize.getSizing().getValue();
269
+			
270
+			x -= closeSize.preferredWidth;
271
+			close.setBounds(new DIRectangle(x, bounds.y, closeSize.preferredWidth, closeSize.preferredHeight));
272
+			x -= maximizeRestoreSize.preferredWidth;
273
+			maximizeRestore.setBounds(new DIRectangle(x, bounds.y, maximizeRestoreSize.preferredWidth, maximizeRestoreSize.preferredHeight));
274
+			x -= minimizeSize.preferredWidth;
275
+			minimize.setBounds(new DIRectangle(x, bounds.y, minimizeSize.preferredWidth, minimizeSize.preferredHeight));
276
+		}
253
 		
277
 		
254
-		x -= closeSize.preferredWidth;
255
-		close.setBounds(new DIRectangle(x, bounds.y, closeSize.preferredWidth, closeSize.preferredHeight));
256
-		x -= maximizeRestoreSize.preferredWidth;
257
-		maximizeRestore.setBounds(new DIRectangle(x, bounds.y, maximizeRestoreSize.preferredWidth, maximizeRestoreSize.preferredHeight));
258
-		x -= minimizeSize.preferredWidth;
259
-		minimize.setBounds(new DIRectangle(x, bounds.y, minimizeSize.preferredWidth, minimizeSize.preferredHeight));
278
+		if (activeBarText != null) {
279
+			int activeBarY = bounds.y
280
+				+ style.aspectBarPaddingTop
281
+				+ (int)(activeToolbarTitleFontMetrics.getAscent() * 0.35f)
282
+				+ (bounds.height - style.aspectBarPaddingTop) / 2;
283
+			int activeBarX = aspectSelectorEndX + style.aspectSelectorToToolbarSpacing;
284
+			activeBarText.setPosition(activeBarX, activeBarY);
285
+			
286
+			activeBarSeparator.close();
287
+			activeBarSeparator = surface.fillRect(
288
+				z + 3,
289
+				new DIRectangle(
290
+					activeBarX + activeBarText.getBounds().width + 8,
291
+					bounds.y + style.aspectBarPaddingTop + 8,
292
+					2,
293
+					bounds.height - style.aspectBarPaddingTop - 16),
294
+				0xFFCCCCCC);
295
+		}
260
 		
296
 		
261
 		calculateAspectBarShape();
297
 		calculateAspectBarShape();
298
+		
299
+		if (showWindowControls) {
300
+			if (windowControlsBackground != null)
301
+				windowControlsBackground.close();
302
+			
303
+			windowControlsBackground = surface.shadowPath(
304
+					z + 1,
305
+					windowControlsShape,
306
+					DTransform2D.IDENTITY,
307
+					style.backgroundColor,
308
+					style.windowControlShadow);
309
+		}
310
+		
262
 		surface.repaint(bounds);
311
 		surface.repaint(bounds);
263
 	}
312
 	}
264
 	
313
 	

+ 67
- 32
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/aspectbar/WindowActionButton.java View File

9
 import java.util.function.Function;
9
 import java.util.function.Function;
10
 import org.openzen.drawablegui.DCanvas;
10
 import org.openzen.drawablegui.DCanvas;
11
 import org.openzen.drawablegui.DColorableIcon;
11
 import org.openzen.drawablegui.DColorableIcon;
12
+import org.openzen.drawablegui.DColorableIconInstance;
12
 import org.openzen.drawablegui.DComponent;
13
 import org.openzen.drawablegui.DComponent;
13
 import org.openzen.drawablegui.DSizing;
14
 import org.openzen.drawablegui.DSizing;
14
 import org.openzen.drawablegui.DMouseEvent;
15
 import org.openzen.drawablegui.DMouseEvent;
15
 import org.openzen.drawablegui.DTransform2D;
16
 import org.openzen.drawablegui.DTransform2D;
16
 import org.openzen.drawablegui.DIRectangle;
17
 import org.openzen.drawablegui.DIRectangle;
17
 import org.openzen.drawablegui.draw.DDrawSurface;
18
 import org.openzen.drawablegui.draw.DDrawSurface;
19
+import org.openzen.drawablegui.draw.DDrawnRectangle;
18
 import org.openzen.drawablegui.listeners.ListenerHandle;
20
 import org.openzen.drawablegui.listeners.ListenerHandle;
19
 import org.openzen.drawablegui.live.LiveBool;
21
 import org.openzen.drawablegui.live.LiveBool;
20
 import org.openzen.drawablegui.live.LiveObject;
22
 import org.openzen.drawablegui.live.LiveObject;
40
 	private boolean hover;
42
 	private boolean hover;
41
 	private boolean press;
43
 	private boolean press;
42
 	private DDrawSurface surface;
44
 	private DDrawSurface surface;
45
+	private int z;
46
+	
47
+	private DDrawnRectangle background;
48
+	private DColorableIconInstance drawnIcon;
43
 	
49
 	
44
 	public WindowActionButton(Function<Float, DColorableIcon> icon, Consumer<DMouseEvent> action) {
50
 	public WindowActionButton(Function<Float, DColorableIcon> icon, Consumer<DMouseEvent> action) {
45
 		this.scalableIcon = icon;
51
 		this.scalableIcon = icon;
47
 	}
53
 	}
48
 
54
 
49
 	@Override
55
 	@Override
50
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
56
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
51
 		this.surface = surface;
57
 		this.surface = surface;
58
+		this.z = z;
52
 		
59
 		
53
 		windowFocused = surface.getContext().getWindow().getActive();
60
 		windowFocused = surface.getContext().getWindow().getActive();
54
-		windowFocusedListener = windowFocused.addListener((a, b) -> repaint());
61
+		windowFocusedListener = windowFocused.addListener((a, b) -> update());
55
 		
62
 		
56
 		icon = scalableIcon == null ? null : scalableIcon.apply(surface.getScale());
63
 		icon = scalableIcon == null ? null : scalableIcon.apply(surface.getScale());
57
 		sizing.setValue(new DSizing(
64
 		sizing.setValue(new DSizing(
58
 				(int)(48 * surface.getScale()),
65
 				(int)(48 * surface.getScale()),
59
 				(int)(24 * surface.getScale())));
66
 				(int)(24 * surface.getScale())));
67
+		
68
+		background = surface.fillRect(z, DIRectangle.EMPTY, getBackgroundColor());
69
+	}
70
+	
71
+	@Override
72
+	public void unmount() {
73
+		if (drawnIcon != null) {
74
+			drawnIcon.close();
75
+			drawnIcon = null;
76
+		}
77
+		if (background != null) {
78
+			background.close();
79
+			background = null;
80
+		}
60
 	}
81
 	}
61
 
82
 
62
 	@Override
83
 	@Override
77
 	@Override
98
 	@Override
78
 	public void setBounds(DIRectangle bounds) {
99
 	public void setBounds(DIRectangle bounds) {
79
 		this.bounds = bounds;
100
 		this.bounds = bounds;
80
-	}
81
-
82
-	@Override
83
-	public void paint(DCanvas canvas) {
84
-		int color = 0xFFFFFFFF;
85
-		int iconColor = windowFocused.getValue() ? 0xFF000000 : 0xFF999999;
86
-		
87
-		if (hover) {
88
-			if (icon instanceof ScalableCloseIcon) {
89
-				color = 0xFFE81123;
90
-				iconColor = 0xFFFFFFFF;
91
-			} else {
92
-				color = 0xFFE0E0E0;
93
-			}
94
-		}
95
-		if (press)
96
-			color = 0xFFCCCCCC;
97
-		
98
-		
99
-		canvas.fillRectangle(bounds.x, bounds.y, bounds.width, bounds.height, color);
101
+		background.setRectangle(bounds);
100
 		
102
 		
101
-		if (scalableIcon != null) {
103
+		if (icon != null) {
104
+			if (drawnIcon != null)
105
+				drawnIcon.close();
106
+			
102
 			int iconX = bounds.x + (int)(bounds.width - icon.getNominalWidth()) / 2;
107
 			int iconX = bounds.x + (int)(bounds.width - icon.getNominalWidth()) / 2;
103
 			int iconY = bounds.y + (int)(bounds.height - icon.getNominalHeight()) / 2;
108
 			int iconY = bounds.y + (int)(bounds.height - icon.getNominalHeight()) / 2;
104
-			icon.draw(canvas, DTransform2D.translate(iconX, iconY), iconColor);
109
+			drawnIcon = new DColorableIconInstance(surface, z + 1, icon, DTransform2D.translate(iconX, iconY), getIconColor());
105
 		}
110
 		}
106
 	}
111
 	}
107
 
112
 
108
 	@Override
113
 	@Override
109
 	public void close() {
114
 	public void close() {
110
 		windowFocusedListener.close();
115
 		windowFocusedListener.close();
116
+		unmount();
111
 	}
117
 	}
112
 	
118
 	
113
 	@Override
119
 	@Override
114
 	public void onMouseEnter(DMouseEvent e) {
120
 	public void onMouseEnter(DMouseEvent e) {
115
 		hover = true;
121
 		hover = true;
116
-		repaint();
122
+		update();
117
 	}
123
 	}
118
 	
124
 	
119
 	@Override
125
 	@Override
120
 	public void onMouseExit(DMouseEvent e) {
126
 	public void onMouseExit(DMouseEvent e) {
121
 		hover = false;
127
 		hover = false;
122
 		press = false;
128
 		press = false;
123
-		repaint();
129
+		update();
124
 	}
130
 	}
125
 	
131
 	
126
 	@Override
132
 	@Override
127
 	public void onMouseDown(DMouseEvent e) {
133
 	public void onMouseDown(DMouseEvent e) {
128
 		press = true;
134
 		press = true;
129
-		repaint();
135
+		update();
130
 	}
136
 	}
131
 	
137
 	
132
 	@Override
138
 	@Override
135
 			action.accept(e);
141
 			action.accept(e);
136
 		
142
 		
137
 		press = false;
143
 		press = false;
138
-		repaint();
144
+		update();
139
 	}
145
 	}
140
 	
146
 	
141
-	private void repaint() {
142
-		if (surface == null)
143
-			return;
147
+	private void update() {
148
+		background.setColor(getBackgroundColor());
149
+		if (drawnIcon != null)
150
+			drawnIcon.setColor(getIconColor());
151
+	}
152
+	
153
+	private int getBackgroundColor() {
154
+		int color = 0xFFFFFFFF;
155
+		int iconColor = windowFocused.getValue() ? 0xFF000000 : 0xFF999999;
156
+		
157
+		if (hover) {
158
+			if (icon instanceof ScalableCloseIcon) {
159
+				color = 0xFFE81123;
160
+				iconColor = 0xFFFFFFFF;
161
+			} else {
162
+				color = 0xFFE0E0E0;
163
+			}
164
+		}
165
+		if (press)
166
+			color = 0xFFCCCCCC;
167
+		
168
+		return color;
169
+	}
170
+	
171
+	private int getIconColor() {
172
+		int iconColor = windowFocused.getValue() ? 0xFF000000 : 0xFF999999;
173
+		
174
+		if (hover) {
175
+			if (icon instanceof ScalableCloseIcon) {
176
+				iconColor = 0xFFFFFFFF;
177
+			}
178
+		}
144
 		
179
 		
145
-		surface.repaint(bounds);
180
+		return iconColor;
146
 	}
181
 	}
147
 }
182
 }

+ 179
- 93
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/editor/SourceEditor.java View File

6
 package org.openzen.zenscript.ide.ui.view.editor;
6
 package org.openzen.zenscript.ide.ui.view.editor;
7
 
7
 
8
 import java.io.IOException;
8
 import java.io.IOException;
9
+import java.util.ArrayList;
10
+import java.util.List;
9
 import org.openzen.drawablegui.DCanvas;
11
 import org.openzen.drawablegui.DCanvas;
10
 import org.openzen.drawablegui.DComponent;
12
 import org.openzen.drawablegui.DComponent;
11
 import org.openzen.drawablegui.DSizing;
13
 import org.openzen.drawablegui.DSizing;
30
 import org.openzen.drawablegui.DUIContext;
32
 import org.openzen.drawablegui.DUIContext;
31
 import org.openzen.drawablegui.draw.DDrawSurface;
33
 import org.openzen.drawablegui.draw.DDrawSurface;
32
 import org.openzen.drawablegui.draw.DDrawnRectangle;
34
 import org.openzen.drawablegui.draw.DDrawnRectangle;
35
+import org.openzen.drawablegui.draw.DDrawnShape;
36
+import org.openzen.drawablegui.draw.DDrawnText;
33
 import org.openzen.drawablegui.live.ImmutableLiveString;
37
 import org.openzen.drawablegui.live.ImmutableLiveString;
34
 import org.openzen.drawablegui.live.InverseLiveBool;
38
 import org.openzen.drawablegui.live.InverseLiveBool;
35
 import org.openzen.drawablegui.live.LiveBool;
39
 import org.openzen.drawablegui.live.LiveBool;
84
 	
88
 	
85
 	private DDrawnRectangle background;
89
 	private DDrawnRectangle background;
86
 	private DDrawnRectangle lineBarBackground;
90
 	private DDrawnRectangle lineBarBackground;
91
+	private DDrawnShape lineBarLine;
92
+	private DDrawnRectangle selection;
93
+	private DDrawnRectangle cursor;
94
+	private DDrawnRectangle currentLineHighlight;
95
+	private final List<DDrawnRectangle> multiLineSelection = new ArrayList<>();
96
+	private final List<DDrawnText> lineNumbers = new ArrayList<>();
97
+	private final List<List<DDrawnText>> drawnTokens = new ArrayList<>();
87
 	
98
 	
88
 	public SourceEditor(DStyleClass styleClass, IDEWindow window, IDESourceFile sourceFile) {
99
 	public SourceEditor(DStyleClass styleClass, IDEWindow window, IDESourceFile sourceFile) {
89
 		this.styleClass = styleClass;
100
 		this.styleClass = styleClass;
111
 		return updated;
122
 		return updated;
112
 	}
123
 	}
113
 	
124
 	
114
-	@Override
115
-	public void onMounted() {
116
-		window.aspectBar.toolbars.add(editToolbar);
117
-		window.aspectBar.active.setValue(editToolbar);
118
-	}
119
-	
120
-	@Override
121
-	public void onUnmounted() {
122
-		window.aspectBar.toolbars.remove(editToolbar);
123
-	}
124
-	
125
 	@Override
125
 	@Override
126
 	public void close() {
126
 	public void close() {
127
 		if (blinkTimer != null)
127
 		if (blinkTimer != null)
131
 	}
131
 	}
132
 
132
 
133
 	@Override
133
 	@Override
134
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
134
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
135
+		if (surface != null)
136
+			unmount();
137
+		
135
 		this.surface = surface;
138
 		this.surface = surface;
136
 		this.z = z;
139
 		this.z = z;
137
 		this.style = new SourceEditorStyle(surface.getStylesheet(parent.getChild("sourceeditor", styleClass)));
140
 		this.style = new SourceEditorStyle(surface.getStylesheet(parent.getChild("sourceeditor", styleClass)));
143
 		
146
 		
144
 		sizing.setValue(new DSizing(0, fullLineHeight * tokens.getLineCount()));
147
 		sizing.setValue(new DSizing(0, fullLineHeight * tokens.getLineCount()));
145
 		
148
 		
149
+		blinkTimer = surface.getContext().setTimer(300, this::blink);
150
+		
151
+		selection = surface.fillRect(z + 2, DIRectangle.EMPTY, style.selectionColor);
152
+		cursor = surface.fillRect(z + 4, DIRectangle.EMPTY, style.cursorColor);
153
+		currentLineHighlight = surface.fillRect(z + 1, DIRectangle.EMPTY, style.currentLineHighlight);
154
+		
155
+		for (int i = 0; i < tokens.getLineCount(); i++)
156
+			lineNumbers.add(surface.drawText(z + 3, font, style.lineBarTextColor, 0, 0, Integer.toString(i + 1)));
157
+		
158
+		for (TokenLine line : tokens.getLines())
159
+			drawnTokens.add(lineToTokens(line));
160
+		
161
+		window.aspectBar.toolbars.add(editToolbar);
162
+		window.aspectBar.active.setValue(editToolbar);
163
+	}
164
+	
165
+	@Override
166
+	public void unmount() {
167
+		window.aspectBar.toolbars.remove(editToolbar);
168
+		
169
+		surface = null;
170
+		
171
+		if (background != null) {
172
+			background.close();
173
+			background = null;
174
+		}
175
+		if (lineBarBackground != null) {
176
+			lineBarBackground.close();
177
+			lineBarBackground = null;
178
+		}
179
+		if (lineBarLine != null) {
180
+			lineBarLine.close();
181
+			lineBarLine = null;
182
+		}
183
+		if (selection != null) {
184
+			selection.close();
185
+			selection = null;
186
+		}
187
+		if (cursor != null) {
188
+			cursor.close();
189
+			cursor = null;
190
+		}
191
+		
146
 		if (blinkTimer != null)
192
 		if (blinkTimer != null)
147
 			blinkTimer.close();
193
 			blinkTimer.close();
148
-		blinkTimer = surface.getContext().setTimer(300, this::blink);
194
+		
195
+		for (DDrawnText lineNumber : lineNumbers)
196
+			lineNumber.close();
197
+		lineNumbers.clear();
198
+		
199
+		for (List<DDrawnText> line : drawnTokens)
200
+			for (DDrawnText token : line)
201
+				token.close();
202
+		drawnTokens.clear();
203
+		
204
+		clearMultilineSelection();
205
+	}
206
+	
207
+	private void clearMultilineSelection() {
208
+		for (DDrawnRectangle item : multiLineSelection)
209
+			item.close();
210
+		multiLineSelection.clear();
149
 	}
211
 	}
150
 
212
 
151
 	@Override
213
 	@Override
175
 			background.close();
237
 			background.close();
176
 		if (lineBarBackground != null)
238
 		if (lineBarBackground != null)
177
 			lineBarBackground.close();
239
 			lineBarBackground.close();
240
+		if (lineBarLine != null)
241
+			lineBarLine.close();
178
 		background = surface.fillRect(z, new DIRectangle(bounds.x + lineBarWidth, bounds.y, bounds.width - lineBarWidth, bounds.height), style.backgroundColor);
242
 		background = surface.fillRect(z, new DIRectangle(bounds.x + lineBarWidth, bounds.y, bounds.width - lineBarWidth, bounds.height), style.backgroundColor);
179
 		lineBarBackground = surface.fillRect(z, new DIRectangle(bounds.x, bounds.y, lineBarWidth, bounds.height), style.lineBarBackgroundColor);
243
 		lineBarBackground = surface.fillRect(z, new DIRectangle(bounds.x, bounds.y, lineBarWidth, bounds.height), style.lineBarBackgroundColor);
180
-	}
181
-
182
-	@Override
183
-	public void paint(DCanvas canvas) {
184
-		DIRectangle canvasBounds = canvas.getBounds();
185
-		
186
-		if (style.lineBarStrokeWidth > 0) {
187
-			canvas.strokePath(tracer -> {
244
+		lineBarLine = surface.strokePath(z + 1, tracer -> {
188
 				tracer.moveTo(bounds.x + lineBarWidth, bounds.y);
245
 				tracer.moveTo(bounds.x + lineBarWidth, bounds.y);
189
 				tracer.lineTo(bounds.x + lineBarWidth, bounds.y + bounds.height);
246
 				tracer.lineTo(bounds.x + lineBarWidth, bounds.y + bounds.height);
190
 			}, DTransform2D.IDENTITY, style.lineBarStrokeColor, style.lineBarStrokeWidth);
247
 			}, DTransform2D.IDENTITY, style.lineBarStrokeColor, style.lineBarStrokeWidth);
191
-		}
192
 		
248
 		
193
-		int x = bounds.x + lineBarWidth + style.lineBarMargin;
194
-		if (cursorEnd != null)
195
-			canvas.fillRectangle(x, lineToY(cursorEnd.line), bounds.width - x, selectionLineHeight, style.currentLineHighlight);
196
-		
197
-		if (cursorStart != null && !cursorStart.equals(cursorEnd)) {
198
-			if (cursorStart.line == cursorEnd.line) {
199
-				int y = getY(cursorStart);
200
-				int x1 = getX(cursorStart);
201
-				int x2 = getX(cursorEnd);
202
-				int fromX = Math.min(x1, x2);
203
-				int toX = Math.max(x1, x2);
204
-				canvas.fillRectangle(fromX, y, toX - fromX, selectionLineHeight, style.selectionColor);
205
-			} else {
206
-				SourcePosition from = SourcePosition.min(cursorStart, cursorEnd);
207
-				SourcePosition to = SourcePosition.max(cursorStart, cursorEnd);
208
-				
209
-				int fromX = getX(from);
210
-				canvas.fillRectangle(fromX, getY(from), bounds.width - fromX, selectionLineHeight, style.selectionColor);
211
-				
212
-				for (int i = from.line + 1; i < to.line; i++) {
213
-					canvas.fillRectangle(x, lineToY(i), bounds.width - x, selectionLineHeight, style.selectionColor);
214
-				}
215
-				
216
-				int toX = getX(to);
217
-				canvas.fillRectangle(x, getY(to), toX - x, selectionLineHeight, style.selectionColor);
218
-			}
219
-		}
220
-		
221
-		int y = bounds.y + style.selectionPaddingTop;
222
-		int lineIndex = 1;
223
-		for (TokenLine line : tokens.getLines()) {
224
-			if (y + textLineHeight  >= canvasBounds.y && y < canvasBounds.y + canvasBounds.height) {
225
-				String lineNumber = Integer.toString(lineIndex);
226
-				int lineNumberX = x - style.lineBarSpacingRight - style.lineBarMargin - fontMetrics.getWidth(lineNumber);
227
-				canvas.drawText(font, style.lineBarTextColor, lineNumberX, y + fontMetrics.getAscent(), lineNumber);
228
-
229
-				int lineX = x;
230
-				for (ZSToken token : line.getTokens()) {
231
-					String content = getDisplayContent(token);
232
-					canvas.drawText(font, TokenClass.get(token.type).color, lineX, y + fontMetrics.getAscent(), content);
233
-					lineX += fontMetrics.getWidth(content);
234
-				}
235
-			}
236
-			
237
-			y += fullLineHeight;
238
-			lineIndex++;
249
+		for (int i = 0; i < lineNumbers.size(); i++) {
250
+			lineNumbers.get(i).setPosition(
251
+					bounds.x + lineBarWidth - style.lineBarSpacingRight - style.lineBarMargin - lineNumbers.get(i).getBounds().width,
252
+					bounds.y + style.selectionPaddingTop + i * fullLineHeight + fontMetrics.getAscent());
239
 		}
253
 		}
240
 		
254
 		
241
-		if (cursorEnd != null && cursorBlink) {
242
-			int cursorX = getX(cursorEnd);
243
-			int cursorY = getY(cursorEnd);
244
-			canvas.fillRectangle(cursorX, cursorY, style.cursorWidth, selectionLineHeight, style.cursorColor);
245
-		}
255
+		layoutLines(0);
246
 	}
256
 	}
247
 	
257
 	
248
 	@Override
258
 	@Override
279
 	}
289
 	}
280
 	
290
 	
281
 	private void setCursor(SourcePosition start, SourcePosition end) {
291
 	private void setCursor(SourcePosition start, SourcePosition end) {
282
-		if (cursorStart != null)
283
-			repaint(cursorStart, cursorEnd);
284
-		
285
 		int previousLine = cursorEnd == null ? -1 : cursorEnd.line;
292
 		int previousLine = cursorEnd == null ? -1 : cursorEnd.line;
286
 		
293
 		
287
 		cursorStart = start;
294
 		cursorStart = start;
292
 				repaintLine(previousLine);
299
 				repaintLine(previousLine);
293
 			repaintLine(cursorEnd.line);
300
 			repaintLine(cursorEnd.line);
294
 		}
301
 		}
295
-		repaint(cursorStart, cursorEnd);
302
+		
303
+		clearMultilineSelection();
304
+		
305
+		int x = bounds.x + lineBarWidth + style.lineBarMargin;
306
+		currentLineHighlight.setRectangle(new DIRectangle(x, lineToY(cursorEnd.line), bounds.width - x, selectionLineHeight));
307
+		int cursorX = getX(cursorEnd);
308
+		int cursorY = getY(cursorEnd);
309
+		cursor.setRectangle(new DIRectangle(cursorX, cursorY, style.cursorWidth, selectionLineHeight));
310
+		
311
+		if (cursorStart != null && !cursorStart.equals(cursorEnd)) {
312
+			if (cursorStart.line == cursorEnd.line) {
313
+				int y = getY(cursorStart);
314
+				int x1 = getX(cursorStart);
315
+				int x2 = getX(cursorEnd);
316
+				int fromX = Math.min(x1, x2);
317
+				int toX = Math.max(x1, x2);
318
+				selection.setRectangle(new DIRectangle(fromX, y, toX - fromX, selectionLineHeight));
319
+			} else {
320
+				SourcePosition from = SourcePosition.min(cursorStart, cursorEnd);
321
+				SourcePosition to = SourcePosition.max(cursorStart, cursorEnd);
322
+				
323
+				int fromX = getX(from);
324
+				multiLineSelection.add(surface.fillRect(
325
+						z + 2,
326
+						new DIRectangle(fromX, getY(from), bounds.width - fromX, selectionLineHeight),
327
+						style.selectionColor));
328
+				
329
+				for (int i = from.line + 1; i < to.line; i++) {
330
+					multiLineSelection.add(surface.fillRect(z + 2, new DIRectangle(x, lineToY(i), bounds.width - x, selectionLineHeight), style.selectionColor));
331
+				}
332
+				
333
+				int toX = getX(to);
334
+				multiLineSelection.add(surface.fillRect(z + 2, new DIRectangle(x, getY(to), toX - x, selectionLineHeight), style.selectionColor));
335
+				selection.setRectangle(DIRectangle.EMPTY);
336
+			}
337
+		} else {
338
+			if (cursorEnd != null)
339
+				
340
+			selection.setRectangle(DIRectangle.EMPTY);
341
+		}
342
+		
296
 		scrollTo(cursorEnd);
343
 		scrollTo(cursorEnd);
297
 	}
344
 	}
298
 	
345
 	
556
 		unchanged.setValue(false);
603
 		unchanged.setValue(false);
557
 	}
604
 	}
558
 	
605
 	
559
-	private void repaint(SourcePosition from, SourcePosition to) {
560
-		if (from.line == to.line) {
561
-			int y = lineToY(from.line);
562
-			int x1 = getX(from);
563
-			int x2 = getX(to);
564
-			int fromX = Math.min(x1, x2);
565
-			int toX = Math.max(x1, x2) + 2;
566
-			surface.repaint(fromX, y, toX - fromX, selectionLineHeight);
567
-		} else {
568
-			int fromY = lineToY(Math.min(from.line, to.line));
569
-			int toY = lineToY(Math.max(from.line, to.line) + 1);
570
-			surface.repaint(bounds.x, fromY, bounds.width, toY - fromY);
571
-		}
572
-	}
573
-	
574
 	private void repaintLine(int line) {
606
 	private void repaintLine(int line) {
575
 		if (bounds == null)
607
 		if (bounds == null)
576
 			return;
608
 			return;
585
 	private void blink() {
617
 	private void blink() {
586
 		if (cursorEnd != null) {
618
 		if (cursorEnd != null) {
587
 			cursorBlink = !cursorBlink;
619
 			cursorBlink = !cursorBlink;
588
-			repaint(cursorEnd, cursorEnd);
620
+			cursor.setColor(cursorBlink ? style.cursorColor : 0);
589
 		}
621
 		}
590
 	}
622
 	}
591
 	
623
 	
677
 			surface.repaint(bounds);
709
 			surface.repaint(bounds);
678
 	}
710
 	}
679
 	
711
 	
712
+	private void layoutLines(int fromIndex) {
713
+		for (int i = fromIndex; i < drawnTokens.size(); i++) {
714
+			layoutLine(i);
715
+		}
716
+	}
717
+	
718
+	private void layoutLine(int index) {
719
+		List<DDrawnText> tokenLine = drawnTokens.get(index);
720
+		int x = bounds.x + lineBarWidth + style.lineBarMargin;
721
+		int y = bounds.y + style.selectionPaddingTop + index * fullLineHeight + fontMetrics.getAscent();
722
+
723
+		for (DDrawnText token : tokenLine) {
724
+			token.setPosition(x, y);
725
+			x += token.getBounds().width;
726
+		};
727
+	}
728
+	
729
+	private List<DDrawnText> lineToTokens(TokenLine line) {
730
+		List<DDrawnText> tokenLine = new ArrayList<>();
731
+		for (ZSToken token : line.getTokens()) {
732
+			String content = getDisplayContent(token);
733
+			tokenLine.add(surface.drawText(z + 3, font, TokenClass.get(token.type).color, 0, 0, content));
734
+		}
735
+		return tokenLine;
736
+	}
737
+	
680
 	private class TokenListener implements TokenModel.Listener {
738
 	private class TokenListener implements TokenModel.Listener {
681
 
739
 
682
 		@Override
740
 		@Override
683
 		public void onLineInserted(int index) {
741
 		public void onLineInserted(int index) {
684
 			onLinesUpdated();
742
 			onLinesUpdated();
743
+			
744
+			if (bounds != null) {
745
+				String str = Integer.toString(lineNumbers.size() + 1);
746
+				int x = bounds.x + lineBarWidth - style.lineBarSpacingRight - style.lineBarMargin - fontMetrics.getWidth(str);
747
+				int y = bounds.y + style.selectionPaddingTop + lineNumbers.size() * fullLineHeight + fontMetrics.getAscent();
748
+				lineNumbers.add(surface.drawText(z + 3, font, style.lineBarTextColor, x, y, str));
749
+				
750
+				drawnTokens.add(index, lineToTokens(tokens.getLine(index)));
751
+				layoutLines(index);
752
+			}
685
 		}
753
 		}
686
 
754
 
687
 		@Override
755
 		@Override
688
 		public void onLineChanged(int index) {
756
 		public void onLineChanged(int index) {
689
 			repaintLine(index);
757
 			repaintLine(index);
758
+			
759
+			if (bounds != null) {
760
+				removeLineTokens(drawnTokens.get(index));
761
+				drawnTokens.get(index).clear();
762
+				drawnTokens.get(index).addAll(lineToTokens(tokens.getLine(index)));
763
+				layoutLine(index);
764
+			}
690
 		}
765
 		}
691
 
766
 
692
 		@Override
767
 		@Override
693
 		public void onLineDeleted(int index) {
768
 		public void onLineDeleted(int index) {
694
 			onLinesUpdated();
769
 			onLinesUpdated();
770
+			
771
+			if (bounds != null) {
772
+				lineNumbers.remove(lineNumbers.size() - 1).close();
773
+				removeLineTokens(drawnTokens.remove(index));
774
+				layoutLines(index);
775
+			}
776
+		}
777
+		
778
+		private void removeLineTokens(List<DDrawnText> tokens) {
779
+			for (DDrawnText token : tokens)
780
+				token.close();
695
 		}
781
 		}
696
 	}
782
 	}
697
 	
783
 	

+ 16
- 14
IDE/src/main/java/org/openzen/zenscript/ide/ui/view/output/OutputView.java View File

8
 import org.openzen.drawablegui.DCanvas;
8
 import org.openzen.drawablegui.DCanvas;
9
 import org.openzen.drawablegui.DComponent;
9
 import org.openzen.drawablegui.DComponent;
10
 import org.openzen.drawablegui.DIRectangle;
10
 import org.openzen.drawablegui.DIRectangle;
11
-import org.openzen.drawablegui.DPath;
12
 import org.openzen.drawablegui.DSizing;
11
 import org.openzen.drawablegui.DSizing;
13
 import org.openzen.drawablegui.DTransform2D;
12
 import org.openzen.drawablegui.DTransform2D;
14
 import org.openzen.drawablegui.draw.DDrawSurface;
13
 import org.openzen.drawablegui.draw.DDrawSurface;
14
+import org.openzen.drawablegui.draw.DDrawnShape;
15
 import org.openzen.drawablegui.live.LiveList;
15
 import org.openzen.drawablegui.live.LiveList;
16
 import org.openzen.drawablegui.live.MutableLiveObject;
16
 import org.openzen.drawablegui.live.MutableLiveObject;
17
 import org.openzen.drawablegui.style.DStyleClass;
17
 import org.openzen.drawablegui.style.DStyleClass;
27
 	private final LiveList<OutputLine> lines;
27
 	private final LiveList<OutputLine> lines;
28
 	
28
 	
29
 	private DDrawSurface surface;
29
 	private DDrawSurface surface;
30
+	private int z;
30
 	private DIRectangle bounds;
31
 	private DIRectangle bounds;
31
-	private DPath shape;
32
 	private OutputViewStyle style;
32
 	private OutputViewStyle style;
33
 	
33
 	
34
+	private DDrawnShape shape;
35
+	
34
 	public OutputView(DStyleClass styleClass, LiveList<OutputLine> lines) {
36
 	public OutputView(DStyleClass styleClass, LiveList<OutputLine> lines) {
35
 		this.styleClass = styleClass;
37
 		this.styleClass = styleClass;
36
 		this.lines = lines;
38
 		this.lines = lines;
37
 	}
39
 	}
38
 
40
 
39
 	@Override
41
 	@Override
40
-	public void setSurface(DStylePath parent, int z, DDrawSurface surface) {
42
+	public void mount(DStylePath parent, int z, DDrawSurface surface) {
41
 		this.surface = surface;
43
 		this.surface = surface;
44
+		this.z = z;
42
 		
45
 		
43
 		DStylePath path = parent.getChild("outputview", styleClass);
46
 		DStylePath path = parent.getChild("outputview", styleClass);
44
 		style = new OutputViewStyle(surface.getStylesheet(path));
47
 		style = new OutputViewStyle(surface.getStylesheet(path));
45
 	}
48
 	}
49
+	
50
+	@Override
51
+	public void unmount() {
52
+		if (shape != null) {
53
+			shape.close();
54
+			shape = null;
55
+		}
56
+	}
46
 
57
 
47
 	@Override
58
 	@Override
48
 	public MutableLiveObject<DSizing> getSizing() {
59
 	public MutableLiveObject<DSizing> getSizing() {
62
 	@Override
73
 	@Override
63
 	public void setBounds(DIRectangle bounds) {
74
 	public void setBounds(DIRectangle bounds) {
64
 		this.bounds = bounds;
75
 		this.bounds = bounds;
65
-		shape = style.shape.instance(bounds);
66
-	}
67
-
68
-	@Override
69
-	public void paint(DCanvas canvas) {
70
-		canvas.shadowPath(
71
-				shape,
72
-				DTransform2D.IDENTITY,
73
-				style.backgroundColor,
74
-				style.shadow);
76
+		shape = surface.shadowPath(z, style.shape.instance(bounds), DTransform2D.IDENTITY, style.backgroundColor, style.shadow);
75
 	}
77
 	}
76
 
78
 
77
 	@Override
79
 	@Override
78
 	public void close() {
80
 	public void close() {
79
-		
81
+		unmount();
80
 	}
82
 	}
81
 }
83
 }

Loading…
Cancel
Save