1 /* 2 * Copyright 2006-2010, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <LayoutUtils.h> 7 8 #include <View.h> 9 10 11 // // AddSizesFloat 12 // float 13 // BLayoutUtils::AddSizesFloat(float a, float b) 14 // { 15 // float sum = a + b + 1; 16 // if (sum >= B_SIZE_UNLIMITED) 17 // return B_SIZE_UNLIMITED; 18 // 19 // return sum; 20 // } 21 // 22 // // AddSizesFloat 23 // float 24 // BLayoutUtils::AddSizesFloat(float a, float b, float c) 25 // { 26 // return AddSizesFloat(AddSizesFloat(a, b), c); 27 // } 28 29 30 // AddSizesInt32 31 int32 32 BLayoutUtils::AddSizesInt32(int32 a, int32 b) 33 { 34 if (a >= B_SIZE_UNLIMITED - b) 35 return B_SIZE_UNLIMITED; 36 return a + b; 37 } 38 39 40 // AddSizesInt32 41 int32 42 BLayoutUtils::AddSizesInt32(int32 a, int32 b, int32 c) 43 { 44 return AddSizesInt32(AddSizesInt32(a, b), c); 45 } 46 47 48 // AddDistances 49 float 50 BLayoutUtils::AddDistances(float a, float b) 51 { 52 float sum = a + b + 1; 53 if (sum >= B_SIZE_UNLIMITED) 54 return B_SIZE_UNLIMITED; 55 56 return sum; 57 } 58 59 60 // AddDistances 61 float 62 BLayoutUtils::AddDistances(float a, float b, float c) 63 { 64 return AddDistances(AddDistances(a, b), c); 65 } 66 67 68 // // SubtractSizesFloat 69 // float 70 // BLayoutUtils::SubtractSizesFloat(float a, float b) 71 // { 72 // if (a < b) 73 // return -1; 74 // return a - b - 1; 75 // } 76 77 78 // SubtractSizesInt32 79 int32 80 BLayoutUtils::SubtractSizesInt32(int32 a, int32 b) 81 { 82 if (a < b) 83 return 0; 84 return a - b; 85 } 86 87 88 // SubtractDistances 89 float 90 BLayoutUtils::SubtractDistances(float a, float b) 91 { 92 if (a < b) 93 return -1; 94 return a - b - 1; 95 } 96 97 98 // FixSizeConstraints 99 void 100 BLayoutUtils::FixSizeConstraints(float& min, float& max, float& preferred) 101 { 102 if (max < min) 103 max = min; 104 if (preferred < min) 105 preferred = min; 106 else if (preferred > max) 107 preferred = max; 108 } 109 110 111 // FixSizeConstraints 112 void 113 BLayoutUtils::FixSizeConstraints(BSize& min, BSize& max, BSize& preferred) 114 { 115 FixSizeConstraints(min.width, max.width, preferred.width); 116 FixSizeConstraints(min.height, max.height, preferred.height); 117 } 118 119 120 // ComposeSize 121 BSize 122 BLayoutUtils::ComposeSize(BSize size, BSize layoutSize) 123 { 124 if (!size.IsWidthSet()) 125 size.width = layoutSize.width; 126 if (!size.IsHeightSet()) 127 size.height = layoutSize.height; 128 129 return size; 130 } 131 132 133 // ComposeAlignment 134 BAlignment 135 BLayoutUtils::ComposeAlignment(BAlignment alignment, BAlignment layoutAlignment) 136 { 137 if (!alignment.IsHorizontalSet()) 138 alignment.horizontal = layoutAlignment.horizontal; 139 if (!alignment.IsVerticalSet()) 140 alignment.vertical = layoutAlignment.vertical; 141 142 return alignment; 143 } 144 145 146 // AlignInFrame 147 BRect 148 BLayoutUtils::AlignInFrame(BRect frame, BSize maxSize, BAlignment alignment) 149 { 150 // align according to the given alignment 151 if (maxSize.width < frame.Width() 152 && alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) { 153 frame.left += (int)((frame.Width() - maxSize.width) 154 * alignment.RelativeHorizontal()); 155 frame.right = frame.left + maxSize.width; 156 } 157 if (maxSize.height < frame.Height() 158 && alignment.vertical != B_ALIGN_USE_FULL_HEIGHT) { 159 frame.top += (int)((frame.Height() - maxSize.height) 160 * alignment.RelativeVertical()); 161 frame.bottom = frame.top + maxSize.height; 162 } 163 164 return frame; 165 } 166 167 168 // AlignInFrame 169 void 170 BLayoutUtils::AlignInFrame(BView* view, BRect frame) 171 { 172 BSize maxSize = view->MaxSize(); 173 BAlignment alignment = view->LayoutAlignment(); 174 175 if (view->HasHeightForWidth()) { 176 // The view has height for width, so we do the horizontal alignment 177 // ourselves and restrict the height max constraint respectively. 178 179 if (maxSize.width < frame.Width() 180 && alignment.horizontal != B_ALIGN_USE_FULL_WIDTH) { 181 frame.OffsetBy(floor((frame.Width() - maxSize.width) 182 * alignment.RelativeHorizontal()), 0); 183 frame.right = frame.left + maxSize.width; 184 } 185 alignment.horizontal = B_ALIGN_USE_FULL_WIDTH; 186 187 float minHeight; 188 float maxHeight; 189 float preferredHeight; 190 view->GetHeightForWidth(frame.Width(), &minHeight, &maxHeight, 191 &preferredHeight); 192 193 frame.bottom = frame.top + max_c(frame.Height(), minHeight); 194 maxSize.height = minHeight; 195 } 196 197 frame = AlignInFrame(frame, maxSize, alignment); 198 view->MoveTo(frame.LeftTop()); 199 view->ResizeTo(frame.Size()); 200 } 201 202 203 /*! Offsets a rectangle's location so that it lies fully in a given rectangular 204 frame. 205 206 If the rectangle is too wide/high to fully fit in the frame, its left/top 207 edge is offset to 0. The rect's size always remains unchanged. 208 209 \param rect The rectangle to be moved. 210 \param frameSize The size of the frame the rect shall be moved into. The 211 frame's left-top is (0, 0). 212 \return The modified rect. 213 */ 214 /*static*/ BRect 215 BLayoutUtils::MoveIntoFrame(BRect rect, BSize frameSize) 216 { 217 BPoint leftTop(rect.LeftTop()); 218 219 // enforce horizontal limits; favor left edge 220 if (rect.right > frameSize.width) 221 leftTop.x -= rect.right - frameSize.width; 222 if (leftTop.x < 0) 223 leftTop.x = 0; 224 225 // enforce vertical limits; favor top edge 226 if (rect.bottom > frameSize.height) 227 leftTop.y -= rect.bottom - frameSize.height; 228 if (leftTop.y < 0) 229 leftTop.y = 0; 230 231 return rect.OffsetToSelf(leftTop); 232 } 233