1 /* 2 * Copyright 2012, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "SharedSolver.h" 8 9 #include <ALMLayout.h> 10 #include <ObjectList.h> 11 12 13 using LinearProgramming::LinearSpec; 14 15 16 struct LayoutOperation { 17 LayoutOperation(BObjectList<BALMLayout>* layouts) 18 : 19 fLayouts(layouts), 20 fVariables(layouts->CountItems() * 2) 21 { 22 } 23 24 virtual ~LayoutOperation() 25 { 26 } 27 28 void Validate(SharedSolver* solver) 29 { 30 for (int32 i = fLayouts->CountItems() - 1; i >= 0; i--) { 31 BALMLayout* layout = fLayouts->ItemAt(i); 32 layout->Right()->SetRange(0, 20000); 33 layout->Bottom()->SetRange(0, 20000); 34 35 fVariables.AddItem(layout->Right()); 36 fVariables.AddItem(layout->Bottom()); 37 } 38 39 CallSolverMethod(solver->Solver(), &fVariables); 40 41 for (int32 i = fLayouts->CountItems() - 1; i >= 0; i--) 42 Finalize(fLayouts->ItemAt(i), solver); 43 } 44 45 virtual void CallSolverMethod(LinearSpec* spec, VariableList* vars) = 0; 46 virtual void Finalize(BALMLayout* layout, SharedSolver* solver) = 0; 47 48 private: 49 BObjectList<BALMLayout>* fLayouts; 50 VariableList fVariables; 51 }; 52 53 54 struct SharedSolver::MinSizeValidator : LayoutOperation { 55 MinSizeValidator(BObjectList<BALMLayout>* layouts) 56 : 57 LayoutOperation(layouts) 58 { 59 } 60 61 void CallSolverMethod(LinearSpec* spec, VariableList* vars) 62 { 63 spec->FindMins(vars); 64 } 65 66 void Finalize(BALMLayout* layout, SharedSolver* solver) 67 { 68 solver->SetMinSize(layout, BSize(layout->Right()->Value(), 69 layout->Bottom()->Value())); 70 } 71 }; 72 73 74 struct SharedSolver::MaxSizeValidator : LayoutOperation { 75 MaxSizeValidator(BObjectList<BALMLayout>* layouts) 76 : 77 LayoutOperation(layouts) 78 { 79 } 80 81 void CallSolverMethod(LinearSpec* spec, VariableList* vars) 82 { 83 spec->FindMaxs(vars); 84 } 85 86 void Finalize(BALMLayout* layout, SharedSolver* solver) 87 { 88 solver->SetMaxSize(layout, BSize(layout->Right()->Value(), 89 layout->Bottom()->Value())); 90 } 91 }; 92 93 94 SharedSolver::SharedSolver() 95 : 96 fConstraintsValid(false), 97 fMinValid(false), 98 fMaxValid(false), 99 fLayoutValid(false), 100 fLayoutContext(NULL) 101 { 102 } 103 104 105 SharedSolver::~SharedSolver() 106 { 107 if (fLayouts.CountItems() > 0) 108 debugger("SharedSolver deleted while still in use!"); 109 110 _SetContext(NULL); 111 } 112 113 114 LinearSpec* 115 SharedSolver::Solver() const 116 { 117 return const_cast<LinearSpec*>(&fLinearSpec); 118 } 119 120 121 void 122 SharedSolver::Invalidate(bool children) 123 { 124 if (!fConstraintsValid && !fMaxValid && !fMinValid && !fLayoutValid) 125 return; 126 127 fConstraintsValid = false; 128 fMinValid = false; 129 fMaxValid = false; 130 fLayoutValid = false; 131 132 _SetContext(NULL); 133 134 for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) 135 fLayouts.ItemAt(i)->InvalidateLayout(children); 136 } 137 138 139 void 140 SharedSolver::RegisterLayout(BALMLayout* layout) 141 { 142 fLayouts.AddItem(layout); 143 Invalidate(false); 144 } 145 146 147 void 148 SharedSolver::LayoutLeaving(BALMLayout* layout) 149 { 150 fLayouts.RemoveItem(layout); 151 Invalidate(false); 152 } 153 154 155 ResultType 156 SharedSolver::ValidateMinSize() 157 { 158 if (fMinValid) 159 return fMinResult; 160 161 _ValidateConstraints(); 162 163 MinSizeValidator validator(&fLayouts); 164 validator.Validate(this); 165 166 fMinResult = fLinearSpec.Result(); 167 168 fMinValid = true; 169 fLayoutValid = false; 170 return fMinResult; 171 } 172 173 174 ResultType 175 SharedSolver::ValidateMaxSize() 176 { 177 if (fMaxValid) 178 return fMaxResult; 179 180 _ValidateConstraints(); 181 182 MaxSizeValidator validator(&fLayouts); 183 validator.Validate(this); 184 185 fMaxResult = fLinearSpec.Result(); 186 187 fMaxValid = true; 188 fLayoutValid = false; 189 190 return fMaxResult; 191 } 192 193 194 ResultType 195 SharedSolver::ValidateLayout(BLayoutContext* context) 196 { 197 if (fLayoutValid && fLayoutContext == context) 198 return fLayoutResult; 199 200 _SetContext(context); 201 _ValidateConstraints(); 202 203 for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) { 204 BALMLayout* layout = fLayouts.ItemAt(i); 205 BSize size(layout->LayoutArea().Size()); 206 layout->Right()->SetRange(size.width, size.width); 207 layout->Bottom()->SetRange(size.height, size.height); 208 } 209 210 fLayoutResult = fLinearSpec.Solve(); 211 fLayoutValid = true; 212 return fLayoutResult; 213 } 214 215 216 void 217 SharedSolver::SetMaxSize(BALMLayout* layout, const BSize& max) 218 { 219 layout->fMaxSize = max; 220 } 221 222 223 void 224 SharedSolver::SetMinSize(BALMLayout* layout, const BSize& min) 225 { 226 layout->fMinSize = min; 227 } 228 229 230 void 231 SharedSolver::LayoutContextLeft(BLayoutContext* context) 232 { 233 _SetContext(NULL); 234 } 235 236 237 void 238 SharedSolver::_SetContext(BLayoutContext* context) 239 { 240 if (fLayoutContext) 241 fLayoutContext->RemoveListener(this); 242 fLayoutContext = context; 243 if (fLayoutContext) 244 fLayoutContext->AddListener(this); 245 } 246 247 248 void 249 SharedSolver::_ValidateConstraints() 250 { 251 if (!fConstraintsValid) { 252 for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) { 253 fLayouts.ItemAt(i)->UpdateConstraints(fLayoutContext); 254 } 255 fConstraintsValid = true; 256 } 257 } 258