1/*
2 * Copyright 2010-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		John Scipione, jscipione@gmail.com
7 *		Clemens Zeidler, haiku@clemens-zeidler.de
8 */
9#ifndef SAT_GROUP_H
10#define SAT_GROUP_H
11
12
13#include <Rect.h>
14
15#include <AutoDeleter.h>
16#include "ObjectList.h"
17#include "Referenceable.h"
18
19#include "MagneticBorder.h"
20
21#include "LinearSpec.h"
22
23
24class SATWindow;
25class Tab;
26class WindowArea;
27
28typedef BObjectList<SATWindow> SATWindowList;
29
30
31class Corner {
32public:
33		enum info_t
34		{
35			kFree,
36			kUsed,
37			kNotDockable
38		};
39
40		enum position_t
41		{
42			kLeftTop = 0,
43			kRightTop = 1,
44			kLeftBottom = 2,
45			kRightBottom = 3
46		};
47
48						Corner();
49		void			Trace() const;
50
51		info_t			status;
52		WindowArea*		windowArea;
53};
54
55
56class Crossing : public BReferenceable {
57public:
58								Crossing(Tab* vertical, Tab* horizontal);
59								~Crossing();
60
61			Corner*				GetCorner(Corner::position_t corner) const;
62			Corner*				GetOppositeCorner(
63									Corner::position_t corner) const;
64
65			Corner*				LeftTopCorner()
66									{ return &fCorners[Corner::kLeftTop]; }
67			Corner*				RightTopCorner()
68									{ return &fCorners[Corner::kRightTop]; }
69			Corner*				LeftBottomCorner()
70									{ return &fCorners[Corner::kLeftBottom]; }
71			Corner*				RightBottomCorner()
72									{ return &fCorners[Corner::kRightBottom]; }
73
74			Tab*				VerticalTab() const;
75			Tab*				HorizontalTab() const;
76
77			void				Trace() const;
78private:
79			Corner				fCorners[4];
80
81			BReference<Tab>		fVerticalTab;
82			BReference<Tab>		fHorizontalTab;
83};
84
85
86typedef BObjectList<Constraint> ConstraintList;
87class SATGroup;
88
89typedef BObjectList<Crossing> CrossingList;
90
91
92// make all coordinates positive needed for the solver
93const float kMakePositiveOffset = 5000;
94
95
96class Tab : public BReferenceable {
97public:
98		enum orientation_t
99		{
100			kVertical,
101			kHorizontal
102		};
103
104								Tab(SATGroup* group, Variable* variable,
105									orientation_t orientation);
106								~Tab();
107
108			float				Position() const;
109			void				SetPosition(float position);
110			orientation_t		Orientation() const;
111			Variable*			Var() {	return fVariable.Get(); }
112
113			//! Caller takes ownership of the constraint.
114			Constraint*			Connect(Variable* variable);
115
116			BReference<Crossing>	AddCrossing(Tab* tab);
117			bool				RemoveCrossing(Crossing* crossing);
118			int32				FindCrossingIndex(Tab* tab);
119			int32				FindCrossingIndex(float tabPosition);
120			Crossing*			FindCrossing(Tab* tab);
121			Crossing*			FindCrossing(float tabPosition);
122
123			const CrossingList*	GetCrossingList() const;
124
125	static	int					CompareFunction(const Tab* tab1,
126									const Tab* tab2);
127
128private:
129			SATGroup*			fGroup;
130			ObjectDeleter<Variable>
131								fVariable;
132			orientation_t		fOrientation;
133
134			CrossingList		fCrossingList;
135};
136
137
138class WindowArea : public BReferenceable {
139public:
140								WindowArea(Crossing* leftTop,
141									Crossing* rightTop, Crossing* leftBottom,
142									Crossing* rightBottom);
143								~WindowArea();
144
145			bool				Init(SATGroup* group);
146			SATGroup*			Group() { return fGroup; }
147
148			void				DoGroupLayout();
149			void				UpdateSizeLimits();
150			void				UpdateSizeConstaints(const BRect& frame);
151
152	const	SATWindowList&		WindowList() { return fWindowList; }
153	const	SATWindowList&		LayerOrder() { return fWindowLayerOrder; }
154			bool				MoveWindowToPosition(SATWindow* window,
155									int32 index);
156			SATWindow*			TopWindow();
157
158			Crossing*			LeftTopCrossing()
159									{ return fLeftTopCrossing.Get(); }
160			Crossing*			RightTopCrossing()
161									{ return fRightTopCrossing.Get(); }
162			Crossing*			LeftBottomCrossing()
163									{ return fLeftBottomCrossing.Get(); }
164			Crossing*			RightBottomCrossing()
165									{ return fRightBottomCrossing.Get(); }
166
167			Tab*				LeftTab();
168			Tab*				RightTab();
169			Tab*				TopTab();
170			Tab*				BottomTab();
171
172			Variable*			LeftVar() { return LeftTab()->Var(); }
173			Variable*			RightVar() { return RightTab()->Var(); }
174			Variable*			TopVar() { return TopTab()->Var(); }
175			Variable*			BottomVar() { return BottomTab()->Var(); }
176
177			BRect				Frame();
178
179			bool				PropagateToGroup(SATGroup* group);
180
181			bool				MoveToTopLayer(SATWindow* window);
182
183private:
184		friend class SATGroup;
185			void				_UninitConstraints();
186			void				_UpdateConstraintValues();
187
188			/*! SATGroup adds new windows to the area. */
189			bool				_AddWindow(SATWindow* window,
190									SATWindow* after = NULL);
191			/*! After the last window has been removed the WindowArea delete
192			himself and clean up all crossings. */
193			bool				_RemoveWindow(SATWindow* window);
194
195	inline	void				_InitCorners();
196	inline	void				_CleanupCorners();
197	inline	void				_SetToWindowCorner(Corner* corner);
198	inline	void				_SetToNeighbourCorner(Corner* neighbour);
199	inline	void				_UnsetWindowCorner(Corner* corner);
200		//! opponent is the other neighbour of the neighbour
201	inline	void				_UnsetNeighbourCorner(Corner* neighbour,
202									Corner* opponent);
203
204			// Find crossing by tab position in group and if not exist create
205			// it.
206			BReference<Crossing>	_CrossingByPosition(Crossing* crossing,
207										SATGroup* group);
208
209			void				_MoveToSAT(SATWindow* topWindow);
210
211			BReference<SATGroup>	fGroup;
212
213			SATWindowList		fWindowList;
214
215			SATWindowList		fWindowLayerOrder;
216
217			BReference<Crossing>	fLeftTopCrossing;
218			BReference<Crossing>	fRightTopCrossing;
219			BReference<Crossing>	fLeftBottomCrossing;
220			BReference<Crossing>	fRightBottomCrossing;
221
222			Constraint*			fMinWidthConstraint;
223			Constraint*			fMinHeightConstraint;
224			Constraint*			fMaxWidthConstraint;
225			Constraint*			fMaxHeightConstraint;
226			Constraint*			fWidthConstraint;
227			Constraint*			fHeightConstraint;
228
229			MagneticBorder		fMagneticBorder;
230};
231
232
233typedef BObjectList<WindowArea> WindowAreaList;
234typedef BObjectList<Tab> TabList;
235
236class BMessage;
237class StackAndTile;
238
239
240class SATGroup : public BReferenceable {
241public:
242		friend class Tab;
243		friend class WindowArea;
244		friend class GroupCookie;
245
246								SATGroup();
247								~SATGroup();
248
249			LinearSpec*			GetLinearSpec() { return fLinearSpec; }
250
251			/*! Create a new WindowArea from the crossing and add the window. */
252			bool				AddWindow(SATWindow* window, Tab* left,
253									Tab* top, Tab* right, Tab* bottom);
254			/*! Add a window to an existing window area. */
255			bool				AddWindow(SATWindow* window, WindowArea* area,
256									SATWindow* after = NULL);
257			/*! If stayBelowMouse is true move the removed window below the
258			cursor if necessary. */
259			bool				RemoveWindow(SATWindow* window,
260									bool stayBelowMouse = true);
261			int32				CountItems();
262			SATWindow*			WindowAt(int32 index);
263
264			SATWindow*			ActiveWindow() const;
265			void				SetActiveWindow(SATWindow* window);
266
267			const WindowAreaList&	GetAreaList() { return fWindowAreaList; }
268
269			/*! \return a sorted tab list. */
270			const TabList*		HorizontalTabs();
271			const TabList*		VerticalTabs();
272
273			Tab*				FindHorizontalTab(float position);
274			Tab*				FindVerticalTab(float position);
275
276			void				WindowAreaRemoved(WindowArea* area);
277
278	static	status_t			RestoreGroup(const BMessage& archive,
279									StackAndTile* sat);
280			status_t			ArchiveGroup(BMessage& archive);
281
282private:
283			BReference<Tab>		_AddHorizontalTab(float position = 0);
284			BReference<Tab>		_AddVerticalTab(float position = 0);
285
286			bool				_RemoveHorizontalTab(Tab* tab);
287			bool				_RemoveVerticalTab(Tab* tab);
288
289			Tab*				_FindTab(const TabList& list, float position);
290
291			void				_SplitGroupIfNecessary(
292									WindowArea* removedArea);
293			void				_FillNeighbourList(
294									WindowAreaList& neighbourWindows,
295									WindowArea* area);
296			void				_LeftNeighbours(
297									WindowAreaList& neighbourWindows,
298									WindowArea* window);
299			void				_TopNeighbours(
300									WindowAreaList& neighbourWindows,
301									WindowArea* window);
302			void				_RightNeighbours(
303									WindowAreaList& neighbourWindows,
304									WindowArea* window);
305			void				_BottomNeighbours(
306									WindowAreaList& neighbourWindows,
307									WindowArea* window);
308			bool				_FindConnectedGroup(WindowAreaList& seedList,
309									WindowArea* removedArea,
310									WindowAreaList& newGroup);
311			void				_FollowSeed(WindowArea* area, WindowArea* veto,
312									WindowAreaList& seedList,
313									WindowAreaList& newGroup);
314			void				_SpawnNewGroup(const WindowAreaList& newGroup);
315
316			void				_EnsureGroupIsOnScreen(SATGroup* group);
317	inline	void				_CallculateXOffset(BPoint& offset, BRect& frame,
318									BRect& screen);
319	inline	void				_CallculateYOffset(BPoint& offset, BRect& frame,
320									BRect& screen);
321
322protected:
323			WindowAreaList		fWindowAreaList;
324			SATWindowList		fSATWindowList;
325
326			LinearSpec*			fLinearSpec;
327
328private:
329			TabList				fHorizontalTabs;
330			bool				fHorizontalTabsSorted;
331			TabList				fVerticalTabs;
332			bool				fVerticalTabsSorted;
333
334			SATWindow*			fActiveWindow;
335};
336
337
338typedef BObjectList<SATGroup> SATGroupList;
339
340#endif
341