1154133Sharti/*
2154133Sharti * Copyright 2010, Haiku.
3154133Sharti * Distributed under the terms of the MIT License.
4154133Sharti *
5154133Sharti * Authors:
6154133Sharti *		Clemens Zeidler <haiku@clemens-zeidler.de>
7154133Sharti */
8154133Sharti#ifndef SAT_GROUP_H
9154133Sharti#define SAT_GROUP_H
10154133Sharti
11154133Sharti
12154133Sharti#include <Rect.h>
13154133Sharti
14154133Sharti#include "ObjectList.h"
15154133Sharti#include "Referenceable.h"
16154133Sharti
17154133Sharti#include "MagneticBorder.h"
18154133Sharti
19154133Sharti#include "LinearSpec.h"
20154133Sharti
21154133Sharti
22154133Sharticlass SATWindow;
23154133Sharticlass Tab;
24154133Sharticlass WindowArea;
25154133Sharti
26154133Shartitypedef BObjectList<SATWindow> SATWindowList;
27154133Sharti
28154133Sharti
29154133Sharticlass Corner {
30154133Shartipublic:
31154133Sharti		enum info_t
32154133Sharti		{
33154133Sharti			kFree,
34154133Sharti			kUsed,
35154133Sharti			kNotDockable
36154133Sharti		};
37154133Sharti
38154133Sharti		enum position_t
39154133Sharti		{
40154133Sharti			kLeftTop = 0,
41154133Sharti			kRightTop = 1,
42154133Sharti			kLeftBottom = 2,
43154133Sharti			kRightBottom = 3
44154133Sharti		};
45154133Sharti
46160341Sharti						Corner();
47154133Sharti		void			Trace() const;
48154133Sharti
49154133Sharti		info_t			status;
50154133Sharti		WindowArea*		windowArea;
51154133Sharti};
52160341Sharti
53160341Sharti
54160341Sharticlass Crossing : public BReferenceable {
55160341Shartipublic:
56160341Sharti								Crossing(Tab* vertical, Tab* horizontal);
57160341Sharti								~Crossing();
58160341Sharti
59154133Sharti			Corner*				GetCorner(Corner::position_t corner) const;
60154133Sharti			Corner*				GetOppositeCorner(
61154133Sharti									Corner::position_t corner) const;
62154133Sharti
63154133Sharti			Corner*				LeftTopCorner()
64154133Sharti									{ return &fCorners[Corner::kLeftTop]; }
65154133Sharti			Corner*				RightTopCorner()
66154133Sharti									{ return &fCorners[Corner::kRightTop]; }
67154133Sharti			Corner*				LeftBottomCorner()
68154133Sharti									{ return &fCorners[Corner::kLeftBottom]; }
69154133Sharti			Corner*				RightBottomCorner()
70154133Sharti									{ return &fCorners[Corner::kRightBottom]; }
71154133Sharti
72154133Sharti			Tab*				VerticalTab() const;
73154133Sharti			Tab*				HorizontalTab() const;
74154133Sharti
75154133Sharti			void				Trace() const;
76154133Shartiprivate:
77154133Sharti			Corner				fCorners[4];
78154133Sharti
79154133Sharti			BReference<Tab>		fVerticalTab;
80154133Sharti			BReference<Tab>		fHorizontalTab;
81154133Sharti};
82154133Sharti
83154133Sharti
84154133Shartitypedef BObjectList<Constraint> ConstraintList;
85154133Sharticlass SATGroup;
86154133Sharti
87154133Shartitypedef BObjectList<Crossing> CrossingList;
88154133Sharti
89154133Sharti
90154133Sharti// make all coordinates positive needed for the solver
91154133Sharticonst float kMakePositiveOffset = 5000;
92154133Sharti
93154133Sharti
94154133Sharticlass Tab : public BReferenceable {
95154133Shartipublic:
96154133Sharti		enum orientation_t
97154133Sharti		{
98154133Sharti			kVertical,
99154133Sharti			kHorizontal
100154133Sharti		};
101154133Sharti
102154133Sharti								Tab(SATGroup* group, Variable* variable,
103160341Sharti									orientation_t orientation);
104160341Sharti								~Tab();
105160341Sharti
106160341Sharti			float				Position() const;
107154133Sharti			void				SetPosition(float position);
108154133Sharti			orientation_t		Orientation() const;
109154133Sharti			Variable*			Var() {	return fVariable;	}
110154133Sharti
111154133Sharti			//! Caller takes ownership of the constraint.
112154133Sharti			Constraint*			Connect(Variable* variable);
113160341Sharti
114160341Sharti			BReference<Crossing>	AddCrossing(Tab* tab);
115160341Sharti			bool				RemoveCrossing(Crossing* crossing);
116154133Sharti			int32				FindCrossingIndex(Tab* tab);
117154133Sharti			int32				FindCrossingIndex(float tabPosition);
118154133Sharti			Crossing*			FindCrossing(Tab* tab);
119154133Sharti			Crossing*			FindCrossing(float tabPosition);
120154133Sharti
121160341Sharti			const CrossingList*	GetCrossingList() const;
122154133Sharti
123154133Sharti	static	int					CompareFunction(const Tab* tab1,
124154133Sharti									const Tab* tab2);
125154133Sharti
126154133Shartiprivate:
127154133Sharti			SATGroup*			fGroup;
128160341Sharti			Variable*			fVariable;
129160341Sharti			orientation_t		fOrientation;
130160341Sharti
131160341Sharti			CrossingList		fCrossingList;
132160341Sharti};
133160341Sharti
134160341Sharti
135160341Sharticlass WindowArea : public BReferenceable {
136154133Shartipublic:
137154133Sharti								WindowArea(Crossing* leftTop,
138154133Sharti									Crossing* rightTop, Crossing* leftBottom,
139154133Sharti									Crossing* rightBottom);
140154133Sharti								~WindowArea();
141154133Sharti
142154133Sharti			bool				Init(SATGroup* group);
143160341Sharti			SATGroup*			Group() { return fGroup; }
144160341Sharti
145160341Sharti			void				DoGroupLayout();
146160341Sharti			void				UpdateSizeLimits();
147160341Sharti			void				UpdateSizeConstaints(const BRect& frame);
148160341Sharti
149160341Sharti	const	SATWindowList&		WindowList() { return fWindowList; }
150160341Sharti	const	SATWindowList&		LayerOrder() { return fWindowLayerOrder; }
151160341Sharti			bool				MoveWindowToPosition(SATWindow* window,
152160341Sharti									int32 index);
153160341Sharti			SATWindow*			TopWindow();
154160341Sharti
155160341Sharti			Crossing*			LeftTopCrossing()
156160341Sharti									{ return fLeftTopCrossing.Get(); }
157160341Sharti			Crossing*			RightTopCrossing()
158160341Sharti									{ return fRightTopCrossing.Get(); }
159160341Sharti			Crossing*			LeftBottomCrossing()
160160341Sharti									{ return fLeftBottomCrossing.Get(); }
161160341Sharti			Crossing*			RightBottomCrossing()
162160341Sharti									{ return fRightBottomCrossing.Get(); }
163160341Sharti
164160341Sharti			Tab*				LeftTab();
165160341Sharti			Tab*				RightTab();
166154133Sharti			Tab*				TopTab();
167154133Sharti			Tab*				BottomTab();
168160341Sharti
169160341Sharti			Variable*			LeftVar() { return LeftTab()->Var(); }
170154133Sharti			Variable*			RightVar() { return RightTab()->Var(); }
171154133Sharti			Variable*			TopVar() { return TopTab()->Var(); }
172154133Sharti			Variable*			BottomVar() { return BottomTab()->Var(); }
173154133Sharti
174154133Sharti			BRect				Frame();
175154133Sharti
176154133Sharti			bool				PropagateToGroup(SATGroup* group);
177154133Sharti
178154133Sharti			bool				MoveToTopLayer(SATWindow* window);
179160341Sharti
180160341Shartiprivate:
181160341Sharti		friend class SATGroup;
182160341Sharti			void				_UninitConstraints();
183160341Sharti			void				_UpdateConstraintValues();
184160341Sharti
185154133Sharti			/*! SATGroup adds new windows to the area. */
186160341Sharti			bool				_AddWindow(SATWindow* window,
187154133Sharti									SATWindow* after = NULL);
188160341Sharti			/*! After the last window has been removed the WindowArea delete
189160341Sharti			himself and clean up all crossings. */
190160341Sharti			bool				_RemoveWindow(SATWindow* window);
191160341Sharti
192160341Sharti	inline	void				_InitCorners();
193154133Sharti	inline	void				_CleanupCorners();
194160341Sharti	inline	void				_SetToWindowCorner(Corner* corner);
195160341Sharti	inline	void				_SetToNeighbourCorner(Corner* neighbour);
196160341Sharti	inline	void				_UnsetWindowCorner(Corner* corner);
197160341Sharti		//! opponent is the other neighbour of the neighbour
198160341Sharti	inline	void				_UnsetNeighbourCorner(Corner* neighbour,
199160341Sharti									Corner* opponent);
200160341Sharti
201160341Sharti			// Find crossing by tab position in group and if not exist create
202160341Sharti			// it.
203228990Suqs			BReference<Crossing>	_CrossingByPosition(Crossing* crossing,
204160341Sharti										SATGroup* group);
205154133Sharti
206160341Sharti			void				_MoveToSAT(SATWindow* topWindow);
207160341Sharti
208154133Sharti			BReference<SATGroup>	fGroup;
209160341Sharti
210160341Sharti			SATWindowList		fWindowList;
211160341Sharti
212160341Sharti			SATWindowList		fWindowLayerOrder;
213160341Sharti
214160341Sharti			BReference<Crossing>	fLeftTopCrossing;
215160341Sharti			BReference<Crossing>	fRightTopCrossing;
216160341Sharti			BReference<Crossing>	fLeftBottomCrossing;
217160341Sharti			BReference<Crossing>	fRightBottomCrossing;
218160341Sharti
219160341Sharti			Constraint*			fMinWidthConstraint;
220160341Sharti			Constraint*			fMinHeightConstraint;
221160341Sharti			Constraint*			fMaxWidthConstraint;
222160341Sharti			Constraint*			fMaxHeightConstraint;
223160341Sharti			Constraint*			fWidthConstraint;
224160341Sharti			Constraint*			fHeightConstraint;
225160341Sharti
226160341Sharti			MagneticBorder		fMagneticBorder;
227160341Sharti};
228160341Sharti
229160341Sharti
230154133Shartitypedef BObjectList<WindowArea> WindowAreaList;
231154133Shartitypedef BObjectList<Tab> TabList;
232160341Sharti
233160341Sharticlass BMessage;
234154133Sharticlass StackAndTile;
235160341Sharti
236154133Sharti
237154133Sharticlass SATGroup : public BReferenceable {
238154133Shartipublic:
239154133Sharti		friend class Tab;
240154133Sharti		friend class WindowArea;
241154133Sharti		friend class GroupCookie;
242154133Sharti
243154133Sharti								SATGroup();
244154133Sharti								~SATGroup();
245154133Sharti
246154133Sharti			LinearSpec*			GetLinearSpec() { return &fLinearSpec; }
247154133Sharti
248154133Sharti			/*! Create a new WindowArea from the crossing and add the window. */
249154133Sharti			bool				AddWindow(SATWindow* window, Tab* left, Tab* top,
250154133Sharti									Tab* right, Tab* bottom);
251154133Sharti			/*! Add a window to an existing window area. */
252154133Sharti			bool				AddWindow(SATWindow* window, WindowArea* area,
253154133Sharti									SATWindow* after = NULL);
254154133Sharti			/*! If stayBelowMouse is true move the removed window below the
255154133Sharti			cursor if necessary. */
256154133Sharti			bool				RemoveWindow(SATWindow* window,
257154133Sharti									bool stayBelowMouse = true);
258154133Sharti			int32				CountItems();
259160341Sharti			SATWindow*			WindowAt(int32 index);
260154133Sharti
261154133Sharti			const WindowAreaList&	GetAreaList() { return fWindowAreaList; }
262154133Sharti
263154133Sharti			/*! \return a sorted tab list. */
264154133Sharti			const TabList*		HorizontalTabs();
265154133Sharti			const TabList*		VerticalTabs();
266154133Sharti
267154133Sharti			Tab*				FindHorizontalTab(float position);
268154133Sharti			Tab*				FindVerticalTab(float position);
269154133Sharti
270154133Sharti			void				WindowAreaRemoved(WindowArea* area);
271154133Sharti
272154133Sharti	static	status_t			RestoreGroup(const BMessage& archive,
273160341Sharti									StackAndTile* sat);
274160341Sharti			status_t			ArchiveGroup(BMessage& archive);
275154133Sharti
276154133Shartiprivate:
277154133Sharti			BReference<Tab>		_AddHorizontalTab(float position = 0);
278154133Sharti			BReference<Tab>		_AddVerticalTab(float position = 0);
279154133Sharti
280154133Sharti			bool				_RemoveHorizontalTab(Tab* tab);
281154133Sharti			bool				_RemoveVerticalTab(Tab* tab);
282154133Sharti
283154133Sharti			Tab*				_FindTab(const TabList& list, float position);
284154133Sharti
285154133Sharti			void				_SplitGroupIfNecessary(
286154133Sharti									WindowArea* removedArea);
287154133Sharti			void				_FillNeighbourList(
288154133Sharti									WindowAreaList& neighbourWindows,
289154133Sharti									WindowArea* area);
290154133Sharti			void				_LeftNeighbours(
291154133Sharti									WindowAreaList& neighbourWindows,
292154133Sharti									WindowArea* window);
293154133Sharti			void				_TopNeighbours(
294154133Sharti									WindowAreaList& neighbourWindows,
295154133Sharti									WindowArea* window);
296154133Sharti			void				_RightNeighbours(
297154133Sharti									WindowAreaList& neighbourWindows,
298154133Sharti									WindowArea* window);
299154133Sharti			void				_BottomNeighbours(
300154133Sharti									WindowAreaList& neighbourWindows,
301154133Sharti									WindowArea* window);
302154133Sharti			bool				_FindConnectedGroup(WindowAreaList& seedList,
303154133Sharti									WindowArea* removedArea,
304154133Sharti									WindowAreaList& newGroup);
305154133Sharti			void				_FollowSeed(WindowArea* area, WindowArea* veto,
306154133Sharti									WindowAreaList& seedList,
307154133Sharti									WindowAreaList& newGroup);
308154133Sharti			void				_SpawnNewGroup(const WindowAreaList& newGroup);
309154133Sharti
310154133Sharti			void				_EnsureGroupIsOnScreen(SATGroup* group);
311154133Sharti	inline	void				_CallculateXOffset(BPoint& offset, BRect& frame,
312154133Sharti									BRect& screen);
313154133Sharti	inline	void				_CallculateYOffset(BPoint& offset, BRect& frame,
314154133Sharti									BRect& screen);
315154133Sharti
316154133Shartiprotected:
317154133Sharti			WindowAreaList		fWindowAreaList;
318154133Sharti			SATWindowList		fSATWindowList;
319154133Sharti
320154133Sharti			LinearSpec			fLinearSpec;
321154133Sharti
322154133Shartiprivate:
323154133Sharti			TabList				fHorizontalTabs;
324154133Sharti			bool				fHorizontalTabsSorted;
325154133Sharti			TabList				fVerticalTabs;
326154133Sharti			bool				fVerticalTabsSorted;
327154133Sharti};
328154133Sharti
329160341Sharti
330154133Shartitypedef BObjectList<SATGroup> SATGroupList;
331154133Sharti
332154133Sharti#endif
333154133Sharti