1/*******************************************************************************
2 * Copyright (c) 2011, Nathan Sweet <nathan.sweet@gmail.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *     * Redistributions of source code must retain the above copyright
8 *       notice, this list of conditions and the following disclaimer.
9 *     * Redistributions in binary form must reproduce the above copyright
10 *       notice, this list of conditions and the following disclaimer in the
11 *       documentation and/or other materials provided with the distribution.
12 *     * Neither the name of the <organization> nor the
13 *       names of its contributors may be used to endorse or promote products
14 *       derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 ******************************************************************************/
27
28package com.badlogic.gdx.scenes.scene2d.ui;
29
30import com.badlogic.gdx.scenes.scene2d.Actor;
31import com.badlogic.gdx.scenes.scene2d.Touchable;
32import com.badlogic.gdx.scenes.scene2d.utils.Layout;
33import com.badlogic.gdx.utils.Array;
34import com.badlogic.gdx.utils.SnapshotArray;
35
36/** A stack is a container that sizes its children to its size and positions them at 0,0 on top of each other.
37 * <p>
38 * The preferred and min size of the stack is the largest preferred and min size of any children. The max size of the stack is the
39 * smallest max size of any children.
40 * @author Nathan Sweet */
41public class Stack extends WidgetGroup {
42	private float prefWidth, prefHeight, minWidth, minHeight, maxWidth, maxHeight;
43	private boolean sizeInvalid = true;
44
45	public Stack () {
46		setTransform(false);
47		setWidth(150);
48		setHeight(150);
49		setTouchable(Touchable.childrenOnly);
50	}
51
52	public Stack (Actor... actors) {
53		this();
54		for (Actor actor : actors)
55			addActor(actor);
56	}
57
58	public void invalidate () {
59		super.invalidate();
60		sizeInvalid = true;
61	}
62
63	private void computeSize () {
64		sizeInvalid = false;
65		prefWidth = 0;
66		prefHeight = 0;
67		minWidth = 0;
68		minHeight = 0;
69		maxWidth = 0;
70		maxHeight = 0;
71		SnapshotArray<Actor> children = getChildren();
72		for (int i = 0, n = children.size; i < n; i++) {
73			Actor child = children.get(i);
74			float childMaxWidth, childMaxHeight;
75			if (child instanceof Layout) {
76				Layout layout = (Layout)child;
77				prefWidth = Math.max(prefWidth, layout.getPrefWidth());
78				prefHeight = Math.max(prefHeight, layout.getPrefHeight());
79				minWidth = Math.max(minWidth, layout.getMinWidth());
80				minHeight = Math.max(minHeight, layout.getMinHeight());
81				childMaxWidth = layout.getMaxWidth();
82				childMaxHeight = layout.getMaxHeight();
83			} else {
84				prefWidth = Math.max(prefWidth, child.getWidth());
85				prefHeight = Math.max(prefHeight, child.getHeight());
86				minWidth = Math.max(minWidth, child.getWidth());
87				minHeight = Math.max(minHeight, child.getHeight());
88				childMaxWidth = 0;
89				childMaxHeight = 0;
90			}
91			if (childMaxWidth > 0) maxWidth = maxWidth == 0 ? childMaxWidth : Math.min(maxWidth, childMaxWidth);
92			if (childMaxHeight > 0) maxHeight = maxHeight == 0 ? childMaxHeight : Math.min(maxHeight, childMaxHeight);
93		}
94	}
95
96	public void add (Actor actor) {
97		addActor(actor);
98	}
99
100	public void layout () {
101		if (sizeInvalid) computeSize();
102		float width = getWidth(), height = getHeight();
103		Array<Actor> children = getChildren();
104		for (int i = 0, n = children.size; i < n; i++) {
105			Actor child = children.get(i);
106			child.setBounds(0, 0, width, height);
107			if (child instanceof Layout) ((Layout)child).validate();
108		}
109	}
110
111	public float getPrefWidth () {
112		if (sizeInvalid) computeSize();
113		return prefWidth;
114	}
115
116	public float getPrefHeight () {
117		if (sizeInvalid) computeSize();
118		return prefHeight;
119	}
120
121	public float getMinWidth () {
122		if (sizeInvalid) computeSize();
123		return minWidth;
124	}
125
126	public float getMinHeight () {
127		if (sizeInvalid) computeSize();
128		return minHeight;
129	}
130
131	public float getMaxWidth () {
132		if (sizeInvalid) computeSize();
133		return maxWidth;
134	}
135
136	public float getMaxHeight () {
137		if (sizeInvalid) computeSize();
138		return maxHeight;
139	}
140}
141