View difference between Paste ID: ws8XYQn6 and Ahycv2r2
SHOW: | | - or go back to the newest paste.
1-
package com.javadaemon.teaclient.ui;
1+
2
import com.badlogic.gdx.graphics.g2d.Batch;
3
import com.badlogic.gdx.scenes.scene2d.Actor;
4
import com.badlogic.gdx.scenes.scene2d.InputEvent;
5
import com.badlogic.gdx.scenes.scene2d.InputListener;
6
import com.badlogic.gdx.scenes.scene2d.Stage;
7
import com.badlogic.gdx.scenes.scene2d.Touchable;
8
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
9
import com.badlogic.gdx.scenes.scene2d.ui.Table;
10
import com.badlogic.gdx.scenes.scene2d.utils.Align;
11
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
12
13
/**
14
 * This is very much like a regular Table, although it has some extra features. 
15
 * It is movable on a Stage, and can be resized by dragging.
16
 * It can also act modal if needed, and be locked to be inside of the Stage if needed.
17
 * 
18
 * This is basicly Window from scene2d.ui, with a few modifications.
19
 * 
20
 * @author Mads Peter Horndrup
21
 */
22
public class MovableTable extends Table {
23
	
24
	/** Different flags to define different behaviors */
25
	private boolean isModal, isResizable, isMovable;
26
	
27
	/** Maximum pixels from the border where the MovableWindow can be resized */
28
	private int resizeBorder = 8;
29
	
30
	/** Are we currently resizing or moving the MovableWindow?? */
31
	private boolean dragging;
32
	
33
	/** Should we make sure the MovableWindow stays inside the Viewport?? */
34
	private boolean keepWithinStage;
35
	
36
	/** What Actors allow the MovableWindow to be dragged */
37
	protected Actor[] dragActors;
38
	
39
	private MovableTableStyle style;
40
	
41
	/** Used to indicate that side of the MovableWindow that is being resized, and if it's being moved */
42
	static private final int MOVE = 1 << 5;
43
	
44
	public MovableTable(Skin skin) {
45
		this(skin.get(MovableTableStyle.class));
46
		setSkin(skin);
47
	}
48
49
	public MovableTable(Skin skin, String styleName) {
50
		this(skin.get(styleName, MovableTableStyle.class));
51
		setSkin(skin);
52
	}
53
54
	public MovableTable(MovableTableStyle closeableWindowStyle) {
55
		setTouchable(Touchable.enabled);
56
		setClip(true);
57
		setStyle(closeableWindowStyle);
58
		setWidth(150);
59
		setHeight(150);
60
		setMovable(true);
61
		setResizable(false);
62
		setKeepWithinStage(true);
63
		
64
		dragActors = new Actor[1];
65
		dragActors[0] = this;
66
67
		addCaptureListener(new InputListener() {
68
			public boolean touchDown(InputEvent event, float x, float y,
69
					int pointer, int button) {
70
				toFront();
71
				return false;
72
			}
73
		});
74
		addListener(new InputListener() {
75
			int edge;
76
			float startX, startY, lastX, lastY;
77
78
			public boolean touchDown(InputEvent event, float x, float y,
79
					int pointer, int button) {
80
				Actor hitActor = hit(x,y,true);
81
				boolean success = false;
82
				for (Actor a : getDraggableRegions()) {
83
					if (hitActor.equals(a)) {
84
						success = true;
85
					}
86
				}
87
				if (!success) {
88
					return false;
89
				}
90
				if (button == Input.Buttons.LEFT) {
91
					int border = resizeBorder;
92
					float width = getWidth(), height = getHeight();
93
					edge = 0;
94
					if (isResizable) {
95
						if (x < border)
96
							edge |= Align.left;
97
						if (x > width - border)
98
							edge |= Align.right;
99
						if (y < border)
100
							edge |= Align.bottom;
101
						if (y > height - border)
102
							edge |= Align.top;
103
						if (edge != 0)
104
							border += 25;
105
						if (x < border)
106
							edge |= Align.left;
107
						if (x > width - border)
108
							edge |= Align.right;
109
						if (y < border)
110
							edge |= Align.bottom;
111
						if (y > height - border)
112
							edge |= Align.top;
113
					}
114
					if (isMovable 
115
							&& edge == 0 	// We are not resizing!
116
							&& y <= height	// Inside the Window
117
							&& y >= 0 		
118
							&& x >= 0
119
							&& x <= width)
120
						edge = MOVE;
121
					dragging = edge != 0;
122
					startX = x;
123
					startY = y;
124
					lastX = x;
125
					lastY = y;
126
				}
127
				return edge != 0 || isModal;
128
			}
129
130
			public void touchUp(InputEvent event, float x, float y,
131
					int pointer, int button) {
132
				dragging = false;
133
			}
134
135
			public void touchDragged(InputEvent event, float x, float y,
136
					int pointer) {
137
				if (!dragging)
138
					return;
139
				float width = getWidth(), height = getHeight();
140
				float windowX = getX(), windowY = getY();
141
142
				float minWidth = getMinWidth(), maxWidth = getMaxWidth();
143
				float minHeight = getMinHeight(), maxHeight = getMaxHeight();
144
				Stage stage = getStage();
145
				boolean clampPosition = keepWithinStage
146
						&& getParent() == stage.getRoot();
147
148
				if ((edge & MOVE) != 0) { // We are moving!
149
					float amountX = x - startX, amountY = y - startY;
150
					windowX += amountX;
151
					windowY += amountY;
152
				}
153
				if ((edge & Align.left) != 0) { // We are resizing!
154
					float amountX = x - startX;
155
					if (width - amountX < minWidth)
156
						amountX = -(minWidth - width);
157
					if (clampPosition && windowX + amountX < 0)
158
						amountX = -windowX;
159
					width -= amountX;
160
					windowX += amountX;
161
				}
162
				if ((edge & Align.bottom) != 0) {
163
					float amountY = y - startY;
164
					if (height - amountY < minHeight)
165
						amountY = -(minHeight - height);
166
					if (clampPosition && windowY + amountY < 0)
167
						amountY = -windowY;
168
					height -= amountY;
169
					windowY += amountY;
170
				}
171
				if ((edge & Align.right) != 0) {
172
					float amountX = x - lastX;
173
					if (width + amountX < minWidth)
174
						amountX = minWidth - width;
175
					if (clampPosition
176
							&& windowX + width + amountX > stage.getWidth())
177
						amountX = stage.getWidth() - windowX - width;
178
					width += amountX;
179
				}
180
				if ((edge & Align.top) != 0) {
181
					float amountY = y - lastY;
182
					if (height + amountY < minHeight)
183
						amountY = minHeight - height;
184
					if (clampPosition
185
							&& windowY + height + amountY > stage.getHeight())
186
						amountY = stage.getHeight() - windowY - height;
187
					height += amountY;
188
				}
189
				lastX = x;
190
				lastY = y;
191
				setBounds(Math.round(windowX), Math.round(windowY),
192
						Math.round(width), Math.round(height));
193
			}
194
195
			public boolean mouseMoved(InputEvent event, float x, float y) {
196
				return isModal;
197
			}
198
199
			public boolean scrolled(InputEvent event, float x, float y,
200
					int amount) {
201
				return isModal;
202
			}
203
204
			public boolean keyDown(InputEvent event, int keycode) {
205
				return isModal;
206
			}
207
208
			public boolean keyUp(InputEvent event, int keycode) {
209
				return isModal;
210
			}
211
212
			public boolean keyTyped(InputEvent event, char character) {
213
				return isModal;
214
			}
215
		});
216
	}
217
	
218
	/**
219
	 * Checks if the Window is within the Stage. If not, it is pushed inside.
220
	 */
221
	private void keepWithinStage () {
222
		if (!keepWithinStage) return;
223
		Stage stage = getStage();
224
		if (getParent() == stage.getRoot()) {
225
			float parentWidth = stage.getWidth();
226
			float parentHeight = stage.getHeight();
227
			if (getX() < 0) setX(0);
228
			if (getRight() > parentWidth) setX(parentWidth - getWidth());
229
			if (getY() < 0) setY(0);
230
			if (getTop() > parentHeight) setY(parentHeight - getHeight());
231
		}
232
	}
233
	
234
	/**
235
	 * @return	The Actor that was hit first.
236
	 */
237
	public Actor hit (float x, float y, boolean touchable) {
238
		Actor hit = super.hit(x, y, touchable);
239
		if (hit == null && isModal && (!touchable || getTouchable() == Touchable.enabled)) return this;
240
		return hit;
241
	}
242
	
243
	/**
244
	 * This method is used to determine what Actors can be clicked to drag the dialog.
245
	 * This is to prevent dragging inside the content of the MovableWindow.
246
	 * @return	An Array of Actors that can be used to drag the MovableWindow.
247
	 */
248
	protected Actor[] getDraggableRegions() {
249
		return dragActors;
250
	}
251
	
252
	/**
253
	 * Renders the beautiful Table.
254
	 */
255
	public void draw(Batch batch, float parentAlpha) {
256
		keepWithinStage();
257
		super.draw(batch, parentAlpha);
258
	}
259
	
260
	public void setStyle(MovableTableStyle style) {
261
		if (style == null) throw new IllegalArgumentException("style cannot be null.");
262
		this.style = style;
263
		setBackground(style.background);
264
		invalidateHierarchy(); // This one is questionable!
265
	}
266
	
267
	public MovableTableStyle getStyle () {
268
		return style;
269
	}
270
	
271
	public boolean isModal() {
272
		return isModal;
273
	}
274
275
	public void setModal(boolean isModal) {
276
		this.isModal = isModal;
277
	}
278
279
	public boolean isResizable() {
280
		return isResizable;
281
	}
282
283
	public void setResizable(boolean isResizable) {
284
		this.isResizable = isResizable;
285
	}
286
287
	public boolean isMovable() {
288
		return isMovable;
289
	}
290
291
	public void setMovable(boolean isMovable) {
292
		this.isMovable = isMovable;
293
	}
294
295
	public boolean isKeepWithinStage() {
296
		return keepWithinStage;
297
	}
298
299
	public void setKeepWithinStage(boolean keepWithinStage) {
300
		this.keepWithinStage = keepWithinStage;
301
	}
302
303
	static public class MovableTableStyle {
304
		
305
		public Drawable background;	
306
	}
307
}