1 /* 2 ============================================================================== 3 4 This file is part of the JUCE library. 5 Copyright (c) 2020 - Raw Material Software Limited 6 7 JUCE is an open source library subject to commercial or open-source 8 licensing. 9 10 By using JUCE, you agree to the terms of both the JUCE 6 End-User License 11 Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020). 12 13 End User License Agreement: www.juce.com/juce-6-licence 14 Privacy Policy: www.juce.com/juce-privacy-policy 15 16 Or: You may also use this code under the terms of the GPL v3 (see 17 www.gnu.org/licenses). 18 19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 21 DISCLAIMED. 22 23 ============================================================================== 24 */ 25 26 namespace juce 27 { 28 29 //============================================================================== 30 /** 31 For laying out a set of components, where the components have preferred sizes 32 and size limits, but where they are allowed to stretch to fill the available 33 space. 34 35 For example, if you have a component containing several other components, and 36 each one should be given a share of the total size, you could use one of these 37 to resize the child components when the parent component is resized. Then 38 you could add a StretchableLayoutResizerBar to easily let the user rescale them. 39 40 A StretchableLayoutManager operates only in one dimension, so if you have a set 41 of components stacked vertically on top of each other, you'd use one to manage their 42 heights. To build up complex arrangements of components, e.g. for applications 43 with multiple nested panels, you would use more than one StretchableLayoutManager. 44 E.g. by using two (one vertical, one horizontal), you could create a resizable 45 spreadsheet-style table. 46 47 E.g. 48 @code 49 class MyComp : public Component 50 { 51 StretchableLayoutManager myLayout; 52 53 MyComp() 54 { 55 myLayout.setItemLayout (0, // for item 0 56 50, 100, // must be between 50 and 100 pixels in size 57 -0.6); // and its preferred size is 60% of the total available space 58 59 myLayout.setItemLayout (1, // for item 1 60 -0.2, -0.6, // size must be between 20% and 60% of the available space 61 50); // and its preferred size is 50 pixels 62 } 63 64 void resized() 65 { 66 // make a list of two of our child components that we want to reposition 67 Component* comps[] = { myComp1, myComp2 }; 68 69 // this will position the 2 components, one above the other, to fit 70 // vertically into the rectangle provided. 71 myLayout.layOutComponents (comps, 2, 72 0, 0, getWidth(), getHeight(), 73 true); 74 } 75 }; 76 @endcode 77 78 @see StretchableLayoutResizerBar 79 80 @tags{GUI} 81 */ 82 class JUCE_API StretchableLayoutManager 83 { 84 public: 85 //============================================================================== 86 /** Creates an empty layout. 87 88 You'll need to add some item properties to the layout before it can be used 89 to resize things - see setItemLayout(). 90 */ 91 StretchableLayoutManager(); 92 93 /** Destructor. */ 94 ~StretchableLayoutManager(); 95 96 //============================================================================== 97 /** For a numbered item, this sets its size limits and preferred size. 98 99 @param itemIndex the index of the item to change. 100 @param minimumSize the minimum size that this item is allowed to be - a positive number 101 indicates an absolute size in pixels. A negative number indicates a 102 proportion of the available space (e.g -0.5 is 50%) 103 @param maximumSize the maximum size that this item is allowed to be - a positive number 104 indicates an absolute size in pixels. A negative number indicates a 105 proportion of the available space 106 @param preferredSize the size that this item would like to be, if there's enough room. A 107 positive number indicates an absolute size in pixels. A negative number 108 indicates a proportion of the available space 109 @see getItemLayout 110 */ 111 void setItemLayout (int itemIndex, 112 double minimumSize, 113 double maximumSize, 114 double preferredSize); 115 116 /** For a numbered item, this returns its size limits and preferred size. 117 118 @param itemIndex the index of the item. 119 @param minimumSize the minimum size that this item is allowed to be - a positive number 120 indicates an absolute size in pixels. A negative number indicates a 121 proportion of the available space (e.g -0.5 is 50%) 122 @param maximumSize the maximum size that this item is allowed to be - a positive number 123 indicates an absolute size in pixels. A negative number indicates a 124 proportion of the available space 125 @param preferredSize the size that this item would like to be, if there's enough room. A 126 positive number indicates an absolute size in pixels. A negative number 127 indicates a proportion of the available space 128 @returns false if the item's properties hadn't been set 129 @see setItemLayout 130 */ 131 bool getItemLayout (int itemIndex, 132 double& minimumSize, 133 double& maximumSize, 134 double& preferredSize) const; 135 136 /** Clears all the properties that have been set with setItemLayout() and resets 137 this object to its initial state. 138 */ 139 void clearAllItems(); 140 141 //============================================================================== 142 /** Takes a set of components that correspond to the layout's items, and positions 143 them to fill a space. 144 145 This will try to give each item its preferred size, whether that's a relative size 146 or an absolute one. 147 148 @param components an array of components that correspond to each of the 149 numbered items that the StretchableLayoutManager object 150 has been told about with setItemLayout() 151 @param numComponents the number of components in the array that is passed-in. This 152 should be the same as the number of items this object has been 153 told about. 154 @param x the left of the rectangle in which the components should 155 be laid out 156 @param y the top of the rectangle in which the components should 157 be laid out 158 @param width the width of the rectangle in which the components should 159 be laid out 160 @param height the height of the rectangle in which the components should 161 be laid out 162 @param vertically if true, the components will be positioned in a vertical stack, 163 so that they fill the height of the rectangle. If false, they 164 will be placed side-by-side in a horizontal line, filling the 165 available width 166 @param resizeOtherDimension if true, this means that the components will have their 167 other dimension resized to fit the space - i.e. if the 'vertically' 168 parameter is true, their x-positions and widths are adjusted to fit 169 the x and width parameters; if 'vertically' is false, their y-positions 170 and heights are adjusted to fit the y and height parameters. 171 */ 172 void layOutComponents (Component** components, 173 int numComponents, 174 int x, int y, int width, int height, 175 bool vertically, 176 bool resizeOtherDimension); 177 178 //============================================================================== 179 /** Returns the current position of one of the items. 180 181 This is only a valid call after layOutComponents() has been called, as it 182 returns the last position that this item was placed at. If the layout was 183 vertical, the value returned will be the y position of the top of the item, 184 relative to the top of the rectangle in which the items were placed (so for 185 example, item 0 will always have position of 0, even in the rectangle passed 186 in to layOutComponents() wasn't at y = 0). If the layout was done horizontally, 187 the position returned is the item's left-hand position, again relative to the 188 x position of the rectangle used. 189 190 @see getItemCurrentSize, setItemPosition 191 */ 192 int getItemCurrentPosition (int itemIndex) const; 193 194 /** Returns the current size of one of the items. 195 196 This is only meaningful after layOutComponents() has been called, as it 197 returns the last size that this item was given. If the layout was done 198 vertically, it'll return the item's height in pixels; if it was horizontal, 199 it'll return its width. 200 201 @see getItemCurrentRelativeSize 202 */ 203 int getItemCurrentAbsoluteSize (int itemIndex) const; 204 205 /** Returns the current size of one of the items. 206 207 This is only meaningful after layOutComponents() has been called, as it 208 returns the last size that this item was given. If the layout was done 209 vertically, it'll return a negative value representing the item's height relative 210 to the last size used for laying the components out; if the layout was done 211 horizontally it'll be the proportion of its width. 212 213 @see getItemCurrentAbsoluteSize 214 */ 215 double getItemCurrentRelativeSize (int itemIndex) const; 216 217 //============================================================================== 218 /** Moves one of the items, shifting along any other items as necessary in 219 order to get it to the desired position. 220 221 Calling this method will also update the preferred sizes of the items it 222 shuffles along, so that they reflect their new positions. 223 224 (This is the method that a StretchableLayoutResizerBar uses to shift the items 225 about when it's dragged). 226 227 @param itemIndex the item to move 228 @param newPosition the absolute position that you'd like this item to move 229 to. The item might not be able to always reach exactly this position, 230 because other items may have minimum sizes that constrain how 231 far it can go 232 */ 233 void setItemPosition (int itemIndex, 234 int newPosition); 235 236 237 private: 238 //============================================================================== 239 struct ItemLayoutProperties 240 { 241 int itemIndex; 242 int currentSize; 243 double minSize, maxSize, preferredSize; 244 }; 245 246 OwnedArray<ItemLayoutProperties> items; 247 int totalSize = 0; 248 249 //============================================================================== 250 static int sizeToRealSize (double size, int totalSpace); 251 ItemLayoutProperties* getInfoFor (int itemIndex) const; 252 void setTotalSize (int newTotalSize); 253 int fitComponentsIntoSpace (int startIndex, int endIndex, int availableSpace, int startPos); 254 int getMinimumSizeOfItems (int startIndex, int endIndex) const; 255 int getMaximumSizeOfItems (int startIndex, int endIndex) const; 256 void updatePrefSizesToMatchCurrentPositions(); 257 258 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StretchableLayoutManager) 259 }; 260 261 } // namespace juce 262