1 /** 2 * Module for a container. 3 * 4 * Authors: 5 * Jacob Jensen 6 * License: 7 * https://github.com/PoisonEngine/poison-ui/blob/master/LICENSE 8 */ 9 module poison.ui.container; 10 11 import std.algorithm : filter; 12 import std.array : array; 13 14 public import dsfml.graphics : RenderWindow; 15 16 import poison.ui.component; 17 import poison.core : Size, Point, ActionArgs, executeUI; 18 19 /// A container component. 20 class Container : Component { 21 private: 22 /// The components. 23 Component[][] _components; 24 25 public: 26 /** 27 * Creates a new container. 28 * Params: 29 * name = The name of the container. 30 * initialSize = The initial size of the container. 31 * layers = The layers of the container. 32 */ 33 this(string name, Size initialSize, size_t layers) { 34 assert(layers > 0); 35 36 super(name, initialSize); 37 38 _components = new Component[][layers]; 39 40 foreach (i; 0 .. _components.length) { 41 _components[i] = []; 42 } 43 44 addSelector("container"); 45 } 46 47 /** 48 * Creates a new container. 49 * Params: 50 * name = The name of the container. 51 * layers = The layers of the container. 52 */ 53 this(string name, size_t layers) { 54 this(name, new Size(100, 100), layers); 55 } 56 57 @property { 58 /// Gets a boolean determining whether the container is disabled or not. 59 override bool disabled() { return super.disabled; } 60 61 /// Sets a boolean determining whether the container is disabled or not. 62 override void disabled(bool isDisabled) { 63 super.disabled = isDisabled; 64 65 foreach (children; _components) { 66 if (children) { 67 foreach (component; children) { 68 if (component) { 69 component.disabled = isDisabled; 70 } 71 } 72 } 73 } 74 } 75 } 76 77 /** 78 * Adds a component to the container. 79 * Params: 80 * child = The child component to add. 81 * layer = The layer to add the component to. 82 */ 83 void add(Component child, size_t layer) { 84 assert(layer >= 0); 85 assert(layer < _components.length); 86 assert(child !is null); 87 assert(child.layer == -1); 88 89 executeUI({ 90 _components[layer] ~= child; 91 92 child.layer = cast(ptrdiff_t)layer; 93 child.parentWindow = parentWindow; 94 child.parentContainer = this; 95 parentWindow._windowComponents[child.id] = child; 96 97 child.disabled = child.disabled; // HACK: calls updateStyles() internally. 98 child.render(); 99 child.show(); 100 }); 101 } 102 103 /** 104 * Adds an array of components to the container. 105 * Params: 106 * components = The child components to add. 107 * layer = The layer to add the components to. 108 */ 109 void add(Component[] components, size_t layer) { 110 assert(components && components.length); 111 112 executeUI({ 113 foreach (component; components) { 114 add(component, layer); 115 } 116 }); 117 } 118 119 /** 120 * Removes a component from the container. 121 * Params: 122 * child = The child component to remove. 123 */ 124 void remove(Component child) { 125 assert(child.layer != -1); 126 127 executeUI({ 128 auto children = _components[child.layer]; 129 130 if (children) { 131 children = children.filter!((c) { return c.id == child.id; }).array; 132 133 _components[layer] = children; 134 } 135 136 child.layer = -1; 137 child.parentWindow._windowComponents.remove(child.id); 138 child.parentWindow = null; 139 child.parentContainer = null; 140 }); 141 } 142 143 /** 144 * Removes a component from the container. 145 * Params: 146 * name = The name of the component. 147 */ 148 void remove(string name) { 149 executeUI({ 150 foreach (ref children; _components) { 151 if (children) { 152 children = children.filter!((c) { return c.name == name; }).array; 153 } 154 } 155 }); 156 } 157 158 /// Clears the component for children. 159 void clear() { 160 executeUI({ 161 foreach (children; _components) { 162 if (children) { 163 foreach (component; children) { 164 if (component) { 165 component.layer = -1; 166 } 167 } 168 } 169 } 170 171 _components = new Component[][_components.length]; 172 }); 173 } 174 175 /** 176 * Clears the components for a specific layer. 177 * Params: 178 * layer = The layer to clear. 179 */ 180 void clear(size_t layer) { 181 assert(layer >= 0); 182 assert(layer < _components.length); 183 184 executeUI({ 185 auto children = _components[layer]; 186 187 if (children) { 188 foreach (component; children) { 189 if (component) { 190 component.layer = -1; 191 } 192 } 193 } 194 195 _components[layer] = []; 196 }); 197 } 198 199 protected: 200 /** 201 * Processes the container during application cycles. 202 * Params: 203 * window = The render window to process. 204 */ 205 override void process(RenderWindow window) { 206 super.process(window); 207 208 foreach (children; _components) { 209 if (children) { 210 foreach (component; children) { 211 if (component) { 212 component.processInternal(window); 213 } 214 } 215 } 216 } 217 } 218 }