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 void 156 SharedSolver::ValidateMinSize() 157 { 158 if (fMinValid) 159 return; 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 } 171 172 173 void 174 SharedSolver::ValidateMaxSize() 175 { 176 if (fMaxValid) 177 return; 178 179 _ValidateConstraints(); 180 181 MaxSizeValidator validator(&fLayouts); 182 validator.Validate(this); 183 184 fMaxResult = fLinearSpec.Result(); 185 186 fMaxValid = true; 187 fLayoutValid = false; 188 } 189 190 191 void 192 SharedSolver::ValidateLayout(BLayoutContext* context) 193 { 194 if (fLayoutValid && fLayoutContext == context) 195 return; 196 197 fConstraintsValid = false; 198 _SetContext(context); 199 _ValidateConstraints(); 200 fLayoutResult = fLinearSpec.Solve(); 201 202 fLayoutValid = true; 203 } 204 205 206 void 207 SharedSolver::SetMaxSize(BALMLayout* layout, const BSize& max) 208 { 209 layout->fMaxSize = max; 210 } 211 212 213 void 214 SharedSolver::SetMinSize(BALMLayout* layout, const BSize& min) 215 { 216 layout->fMinSize = min; 217 } 218 219 220 void 221 SharedSolver::LayoutContextLeft(BLayoutContext* context) 222 { 223 _SetContext(NULL); 224 } 225 226 227 void 228 SharedSolver::_SetContext(BLayoutContext* context) 229 { 230 if (fLayoutContext) 231 fLayoutContext->RemoveListener(this); 232 fLayoutContext = context; 233 if (fLayoutContext) 234 fLayoutContext->AddListener(this); 235 } 236 237 238 void 239 SharedSolver::_ValidateConstraints() 240 { 241 if (!fConstraintsValid) { 242 for (int32 i = fLayouts.CountItems() - 1; i >= 0; i--) { 243 fLayouts.ItemAt(i)->UpdateConstraints(fLayoutContext); 244 } 245 fConstraintsValid = true; 246 } 247 } 248