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