xref: /haiku/src/libs/alm/SharedSolver.cpp (revision 419fe0b8ae0e16d798868eeebf0282978deb224d)
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