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