ZenScript main repository
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DSideLayout.java 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. import java.io.Closeable;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. import java.util.function.Consumer;
  11. import java.util.function.Predicate;
  12. import org.openzen.drawablegui.listeners.ListenerHandle;
  13. import org.openzen.drawablegui.live.LiveObject;
  14. import org.openzen.drawablegui.live.SimpleLiveObject;
  15. import org.openzen.drawablegui.style.DStyleClass;
  16. import org.openzen.drawablegui.style.DStylePath;
  17. /**
  18. *
  19. * @author Hoofdgebruiker
  20. */
  21. public class DSideLayout extends BaseComponentGroup {
  22. private final DStyleClass styleClass;
  23. private DComponent main;
  24. private final List<SideComponent> sides = new ArrayList<>();
  25. private final LiveObject<DDimensionPreferences> dimensionPreferences = new SimpleLiveObject<>(DDimensionPreferences.EMPTY);
  26. private DStylePath path;
  27. private DUIContext context;
  28. private DIRectangle bounds;
  29. public DSideLayout(DStyleClass styleClass, DComponent main) {
  30. this.styleClass = styleClass;
  31. this.main = main;
  32. }
  33. public void add(Side side, DComponent component) {
  34. if (context != null)
  35. component.setContext(path, context);
  36. sides.add(new SideComponent(side, component));
  37. }
  38. public void setMain(DComponent component) {
  39. if (this.main != null)
  40. this.main.close();
  41. this.main = component;
  42. if (context != null && bounds != null) {
  43. main.setContext(path, context);
  44. setBounds(bounds);
  45. context.repaint(bounds);
  46. }
  47. }
  48. @Override
  49. public void setContext(DStylePath parent, DUIContext context) {
  50. this.context = context;
  51. this.path = parent.getChild("sidelayout", styleClass);
  52. main.setContext(path, context);
  53. for (SideComponent side : sides)
  54. side.component.setContext(path, context);
  55. }
  56. @Override
  57. public DIRectangle getBounds() {
  58. return bounds;
  59. }
  60. @Override
  61. public LiveObject<DDimensionPreferences> getDimensionPreferences() {
  62. return dimensionPreferences;
  63. }
  64. @Override
  65. public void setBounds(DIRectangle bounds) {
  66. this.bounds = bounds;
  67. int left = bounds.x;
  68. int right = bounds.x + bounds.width;
  69. int top = bounds.y;
  70. int bottom = bounds.y + bounds.height;
  71. for (int i = sides.size() - 1; i >= 0; i--) {
  72. SideComponent side = sides.get(i);
  73. DDimensionPreferences preferences = side.component.getDimensionPreferences().getValue();
  74. switch (side.side) {
  75. case TOP: {
  76. int componentWidth = right - left;
  77. int componentHeight = preferences.preferredHeight;
  78. int componentX = left;
  79. int componentY = top;
  80. if (componentWidth > preferences.maximumWidth) {
  81. componentX += (componentWidth - preferences.maximumWidth) / 2;
  82. componentWidth = preferences.maximumWidth;
  83. }
  84. side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
  85. top += componentHeight;
  86. break;
  87. }
  88. case BOTTOM: {
  89. int componentWidth = right - left;
  90. int componentHeight = preferences.preferredHeight;
  91. bottom -= componentHeight;
  92. int componentX = left;
  93. int componentY = bottom;
  94. if (componentWidth > preferences.maximumWidth) {
  95. componentX += (componentWidth - preferences.maximumWidth) / 2;
  96. componentWidth = preferences.maximumWidth;
  97. }
  98. side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
  99. break;
  100. }
  101. case LEFT: {
  102. int componentWidth = preferences.preferredWidth;
  103. int componentHeight = bottom - top;
  104. int componentX = left;
  105. int componentY = top;
  106. if (componentHeight > preferences.maximumHeight) {
  107. componentY += (componentHeight - preferences.maximumHeight) / 2;
  108. componentHeight = preferences.maximumHeight;
  109. }
  110. side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
  111. left += componentWidth;
  112. break;
  113. }
  114. case RIGHT: {
  115. int componentWidth = preferences.preferredWidth;
  116. int componentHeight = bottom - top;
  117. right -= componentWidth;
  118. int componentX = right;
  119. int componentY = top;
  120. if (componentHeight > preferences.maximumHeight) {
  121. componentY += (componentHeight - preferences.maximumHeight) / 2;
  122. componentHeight = preferences.maximumHeight;
  123. }
  124. side.component.setBounds(new DIRectangle(componentX, componentY, componentWidth, componentHeight));
  125. break;
  126. }
  127. }
  128. }
  129. main.setBounds(new DIRectangle(left, top, right - left, bottom - top));
  130. }
  131. @Override
  132. public void paint(DCanvas canvas) {
  133. main.paint(canvas);
  134. for (SideComponent component : sides)
  135. component.component.paint(canvas);
  136. }
  137. private void recalculateSize() {
  138. DDimensionPreferences mainPreferences = main.getDimensionPreferences().getValue();
  139. int minimumWidth = mainPreferences.minimumWidth;
  140. int minimumHeight = mainPreferences.minimumHeight;
  141. int preferredWidth = mainPreferences.preferredWidth;
  142. int preferredHeight = mainPreferences.preferredHeight;
  143. int maximumWidth = mainPreferences.maximumWidth;
  144. int maximumHeight = mainPreferences.maximumHeight;
  145. for (SideComponent side : sides) {
  146. DDimensionPreferences sidePreferences = side.component.getDimensionPreferences().getValue();
  147. switch (side.side) {
  148. case LEFT:
  149. case RIGHT:
  150. minimumWidth += sidePreferences.preferredWidth;
  151. preferredWidth += sidePreferences.preferredWidth;
  152. maximumWidth += sidePreferences.preferredWidth;
  153. minimumHeight = Math.max(minimumHeight, sidePreferences.minimumHeight);
  154. preferredHeight = Math.max(maximumHeight, sidePreferences.preferredHeight);
  155. break;
  156. case BOTTOM:
  157. case TOP:
  158. minimumHeight += sidePreferences.preferredHeight;
  159. preferredHeight += sidePreferences.preferredHeight;
  160. maximumHeight += sidePreferences.preferredHeight;
  161. minimumWidth = Math.max(minimumWidth, sidePreferences.minimumWidth);
  162. preferredWidth = Math.max(preferredWidth, sidePreferences.preferredWidth);
  163. break;
  164. }
  165. }
  166. dimensionPreferences.setValue(new DDimensionPreferences(
  167. minimumWidth,
  168. minimumHeight,
  169. preferredWidth,
  170. preferredHeight,
  171. maximumWidth,
  172. maximumHeight));
  173. }
  174. @Override
  175. protected void forEachChild(Consumer<DComponent> children) {
  176. children.accept(main);
  177. for (SideComponent side : sides)
  178. children.accept(side.component);
  179. }
  180. @Override
  181. public DComponent findChild(Predicate<DComponent> predicate) {
  182. if (predicate.test(main))
  183. return main;
  184. for (SideComponent side : sides)
  185. if (predicate.test(side.component))
  186. return side.component;
  187. return null;
  188. }
  189. @Override
  190. public void close() {
  191. main.close();
  192. for (SideComponent side : sides)
  193. side.close();
  194. }
  195. public class SideComponent implements Closeable, LiveObject.Listener<DDimensionPreferences> {
  196. public final Side side;
  197. public final DComponent component;
  198. public final ListenerHandle<LiveObject.Listener<DDimensionPreferences>> listenerHandle;
  199. public SideComponent(Side side, DComponent component) {
  200. this.side = side;
  201. this.component = component;
  202. listenerHandle = component.getDimensionPreferences().addListener(this);
  203. }
  204. @Override
  205. public void close() {
  206. listenerHandle.close();
  207. }
  208. @Override
  209. public void onUpdated(DDimensionPreferences oldValue, DDimensionPreferences newValue) {
  210. recalculateSize();
  211. }
  212. }
  213. public enum Side {
  214. LEFT,
  215. RIGHT,
  216. TOP,
  217. BOTTOM
  218. }
  219. }