xref: /haiku/src/servers/app/stackandtile/SATGroup.h (revision fb6ab24a07c7f4af3c5fec0f9abd083e6f8c098f)
127f5d579SClemens Zeidler /*
2*fb6ab24aSJohn Scipione  * Copyright 2010-2014 Haiku, Inc. All rights reserved.
327f5d579SClemens Zeidler  * Distributed under the terms of the MIT License.
427f5d579SClemens Zeidler  *
527f5d579SClemens Zeidler  * Authors:
6*fb6ab24aSJohn Scipione  *		John Scipione, jscipione@gmail.com
7*fb6ab24aSJohn Scipione  *		Clemens Zeidler, haiku@clemens-zeidler.de
827f5d579SClemens Zeidler  */
927f5d579SClemens Zeidler #ifndef SAT_GROUP_H
1027f5d579SClemens Zeidler #define SAT_GROUP_H
1127f5d579SClemens Zeidler 
1227f5d579SClemens Zeidler 
1327f5d579SClemens Zeidler #include <Rect.h>
1427f5d579SClemens Zeidler 
1527f5d579SClemens Zeidler #include "ObjectList.h"
1627f5d579SClemens Zeidler #include "Referenceable.h"
1727f5d579SClemens Zeidler 
18e0bc3d9eSClemens Zeidler #include "MagneticBorder.h"
19e0bc3d9eSClemens Zeidler 
2027f5d579SClemens Zeidler #include "LinearSpec.h"
2127f5d579SClemens Zeidler 
2227f5d579SClemens Zeidler 
2327f5d579SClemens Zeidler class SATWindow;
2427f5d579SClemens Zeidler class Tab;
2527f5d579SClemens Zeidler class WindowArea;
2627f5d579SClemens Zeidler 
2727f5d579SClemens Zeidler typedef BObjectList<SATWindow> SATWindowList;
2827f5d579SClemens Zeidler 
2927f5d579SClemens Zeidler 
3027f5d579SClemens Zeidler class Corner {
3127f5d579SClemens Zeidler public:
3227f5d579SClemens Zeidler 		enum info_t
3327f5d579SClemens Zeidler 		{
3427f5d579SClemens Zeidler 			kFree,
3527f5d579SClemens Zeidler 			kUsed,
3627f5d579SClemens Zeidler 			kNotDockable
3727f5d579SClemens Zeidler 		};
3827f5d579SClemens Zeidler 
3927f5d579SClemens Zeidler 		enum position_t
4027f5d579SClemens Zeidler 		{
4127f5d579SClemens Zeidler 			kLeftTop = 0,
4227f5d579SClemens Zeidler 			kRightTop = 1,
4327f5d579SClemens Zeidler 			kLeftBottom = 2,
4427f5d579SClemens Zeidler 			kRightBottom = 3
4527f5d579SClemens Zeidler 		};
4627f5d579SClemens Zeidler 
4727f5d579SClemens Zeidler 						Corner();
4827f5d579SClemens Zeidler 		void			Trace() const;
4927f5d579SClemens Zeidler 
5027f5d579SClemens Zeidler 		info_t			status;
5127f5d579SClemens Zeidler 		WindowArea*		windowArea;
5227f5d579SClemens Zeidler };
5327f5d579SClemens Zeidler 
5427f5d579SClemens Zeidler 
5527f5d579SClemens Zeidler class Crossing : public BReferenceable {
5627f5d579SClemens Zeidler public:
5727f5d579SClemens Zeidler 								Crossing(Tab* vertical, Tab* horizontal);
5827f5d579SClemens Zeidler 								~Crossing();
5927f5d579SClemens Zeidler 
6027f5d579SClemens Zeidler 			Corner*				GetCorner(Corner::position_t corner) const;
6127f5d579SClemens Zeidler 			Corner*				GetOppositeCorner(
6227f5d579SClemens Zeidler 									Corner::position_t corner) const;
6327f5d579SClemens Zeidler 
6427f5d579SClemens Zeidler 			Corner*				LeftTopCorner()
6527f5d579SClemens Zeidler 									{ return &fCorners[Corner::kLeftTop]; }
6627f5d579SClemens Zeidler 			Corner*				RightTopCorner()
6727f5d579SClemens Zeidler 									{ return &fCorners[Corner::kRightTop]; }
6827f5d579SClemens Zeidler 			Corner*				LeftBottomCorner()
6927f5d579SClemens Zeidler 									{ return &fCorners[Corner::kLeftBottom]; }
7027f5d579SClemens Zeidler 			Corner*				RightBottomCorner()
7127f5d579SClemens Zeidler 									{ return &fCorners[Corner::kRightBottom]; }
7227f5d579SClemens Zeidler 
7327f5d579SClemens Zeidler 			Tab*				VerticalTab() const;
7427f5d579SClemens Zeidler 			Tab*				HorizontalTab() const;
7527f5d579SClemens Zeidler 
7627f5d579SClemens Zeidler 			void				Trace() const;
7727f5d579SClemens Zeidler private:
7827f5d579SClemens Zeidler 			Corner				fCorners[4];
7927f5d579SClemens Zeidler 
80e0bc3d9eSClemens Zeidler 			BReference<Tab>		fVerticalTab;
81e0bc3d9eSClemens Zeidler 			BReference<Tab>		fHorizontalTab;
8227f5d579SClemens Zeidler };
8327f5d579SClemens Zeidler 
8427f5d579SClemens Zeidler 
8527f5d579SClemens Zeidler typedef BObjectList<Constraint> ConstraintList;
8627f5d579SClemens Zeidler class SATGroup;
8727f5d579SClemens Zeidler 
8827f5d579SClemens Zeidler typedef BObjectList<Crossing> CrossingList;
8927f5d579SClemens Zeidler 
9027f5d579SClemens Zeidler 
9127f5d579SClemens Zeidler // make all coordinates positive needed for the solver
9227f5d579SClemens Zeidler const float kMakePositiveOffset = 5000;
9327f5d579SClemens Zeidler 
9427f5d579SClemens Zeidler 
9527f5d579SClemens Zeidler class Tab : public BReferenceable {
9627f5d579SClemens Zeidler public:
9727f5d579SClemens Zeidler 		enum orientation_t
9827f5d579SClemens Zeidler 		{
9927f5d579SClemens Zeidler 			kVertical,
10027f5d579SClemens Zeidler 			kHorizontal
10127f5d579SClemens Zeidler 		};
10227f5d579SClemens Zeidler 
10327f5d579SClemens Zeidler 								Tab(SATGroup* group, Variable* variable,
10427f5d579SClemens Zeidler 									orientation_t orientation);
10527f5d579SClemens Zeidler 								~Tab();
10627f5d579SClemens Zeidler 
10727f5d579SClemens Zeidler 			float				Position() const;
10827f5d579SClemens Zeidler 			void				SetPosition(float position);
10927f5d579SClemens Zeidler 			orientation_t		Orientation() const;
11027f5d579SClemens Zeidler 			Variable*			Var() {	return fVariable;	}
11127f5d579SClemens Zeidler 
11227f5d579SClemens Zeidler 			//! Caller takes ownership of the constraint.
11327f5d579SClemens Zeidler 			Constraint*			Connect(Variable* variable);
11427f5d579SClemens Zeidler 
11527f5d579SClemens Zeidler 			BReference<Crossing>	AddCrossing(Tab* tab);
11627f5d579SClemens Zeidler 			bool				RemoveCrossing(Crossing* crossing);
11727f5d579SClemens Zeidler 			int32				FindCrossingIndex(Tab* tab);
11827f5d579SClemens Zeidler 			int32				FindCrossingIndex(float tabPosition);
11927f5d579SClemens Zeidler 			Crossing*			FindCrossing(Tab* tab);
12027f5d579SClemens Zeidler 			Crossing*			FindCrossing(float tabPosition);
12127f5d579SClemens Zeidler 
12227f5d579SClemens Zeidler 			const CrossingList*	GetCrossingList() const;
12327f5d579SClemens Zeidler 
12427f5d579SClemens Zeidler 	static	int					CompareFunction(const Tab* tab1,
12527f5d579SClemens Zeidler 									const Tab* tab2);
12627f5d579SClemens Zeidler 
12727f5d579SClemens Zeidler private:
12827f5d579SClemens Zeidler 			SATGroup*			fGroup;
12927f5d579SClemens Zeidler 			Variable*			fVariable;
13027f5d579SClemens Zeidler 			orientation_t		fOrientation;
13127f5d579SClemens Zeidler 
13227f5d579SClemens Zeidler 			CrossingList		fCrossingList;
13327f5d579SClemens Zeidler };
13427f5d579SClemens Zeidler 
13527f5d579SClemens Zeidler 
13627f5d579SClemens Zeidler class WindowArea : public BReferenceable {
13727f5d579SClemens Zeidler public:
13827f5d579SClemens Zeidler 								WindowArea(Crossing* leftTop,
13927f5d579SClemens Zeidler 									Crossing* rightTop, Crossing* leftBottom,
14027f5d579SClemens Zeidler 									Crossing* rightBottom);
14127f5d579SClemens Zeidler 								~WindowArea();
14227f5d579SClemens Zeidler 
143e0bc3d9eSClemens Zeidler 			bool				Init(SATGroup* group);
144e0bc3d9eSClemens Zeidler 			SATGroup*			Group() { return fGroup; }
145e0bc3d9eSClemens Zeidler 
146e0bc3d9eSClemens Zeidler 			void				DoGroupLayout();
147e0bc3d9eSClemens Zeidler 			void				UpdateSizeLimits();
148e0bc3d9eSClemens Zeidler 			void				UpdateSizeConstaints(const BRect& frame);
14927f5d579SClemens Zeidler 
15027f5d579SClemens Zeidler 	const	SATWindowList&		WindowList() { return fWindowList; }
15127f5d579SClemens Zeidler 	const	SATWindowList&		LayerOrder() { return fWindowLayerOrder; }
15227f5d579SClemens Zeidler 			bool				MoveWindowToPosition(SATWindow* window,
15327f5d579SClemens Zeidler 									int32 index);
15427f5d579SClemens Zeidler 			SATWindow*			TopWindow();
15527f5d579SClemens Zeidler 
15627f5d579SClemens Zeidler 			Crossing*			LeftTopCrossing()
15727f5d579SClemens Zeidler 									{ return fLeftTopCrossing.Get(); }
15827f5d579SClemens Zeidler 			Crossing*			RightTopCrossing()
15927f5d579SClemens Zeidler 									{ return fRightTopCrossing.Get(); }
16027f5d579SClemens Zeidler 			Crossing*			LeftBottomCrossing()
16127f5d579SClemens Zeidler 									{ return fLeftBottomCrossing.Get(); }
16227f5d579SClemens Zeidler 			Crossing*			RightBottomCrossing()
16327f5d579SClemens Zeidler 									{ return fRightBottomCrossing.Get(); }
16427f5d579SClemens Zeidler 
16527f5d579SClemens Zeidler 			Tab*				LeftTab();
16627f5d579SClemens Zeidler 			Tab*				RightTab();
16727f5d579SClemens Zeidler 			Tab*				TopTab();
16827f5d579SClemens Zeidler 			Tab*				BottomTab();
16927f5d579SClemens Zeidler 
170e0bc3d9eSClemens Zeidler 			Variable*			LeftVar() { return LeftTab()->Var(); }
171e0bc3d9eSClemens Zeidler 			Variable*			RightVar() { return RightTab()->Var(); }
172e0bc3d9eSClemens Zeidler 			Variable*			TopVar() { return TopTab()->Var(); }
173e0bc3d9eSClemens Zeidler 			Variable*			BottomVar() { return BottomTab()->Var(); }
174e0bc3d9eSClemens Zeidler 
17527f5d579SClemens Zeidler 			BRect				Frame();
17627f5d579SClemens Zeidler 
17727f5d579SClemens Zeidler 			bool				PropagateToGroup(SATGroup* group);
17827f5d579SClemens Zeidler 
17927f5d579SClemens Zeidler 			bool				MoveToTopLayer(SATWindow* window);
18027f5d579SClemens Zeidler 
18127f5d579SClemens Zeidler private:
18227f5d579SClemens Zeidler 		friend class SATGroup;
183e0bc3d9eSClemens Zeidler 			void				_UninitConstraints();
184e0bc3d9eSClemens Zeidler 			void				_UpdateConstraintValues();
185e0bc3d9eSClemens Zeidler 
18627f5d579SClemens Zeidler 			/*! SATGroup adds new windows to the area. */
18727f5d579SClemens Zeidler 			bool				_AddWindow(SATWindow* window,
18827f5d579SClemens Zeidler 									SATWindow* after = NULL);
18927f5d579SClemens Zeidler 			/*! After the last window has been removed the WindowArea delete
19027f5d579SClemens Zeidler 			himself and clean up all crossings. */
19127f5d579SClemens Zeidler 			bool				_RemoveWindow(SATWindow* window);
19227f5d579SClemens Zeidler 
19327f5d579SClemens Zeidler 	inline	void				_InitCorners();
19427f5d579SClemens Zeidler 	inline	void				_CleanupCorners();
19527f5d579SClemens Zeidler 	inline	void				_SetToWindowCorner(Corner* corner);
19627f5d579SClemens Zeidler 	inline	void				_SetToNeighbourCorner(Corner* neighbour);
19727f5d579SClemens Zeidler 	inline	void				_UnsetWindowCorner(Corner* corner);
19827f5d579SClemens Zeidler 		//! opponent is the other neighbour of the neighbour
19927f5d579SClemens Zeidler 	inline	void				_UnsetNeighbourCorner(Corner* neighbour,
20027f5d579SClemens Zeidler 									Corner* opponent);
20127f5d579SClemens Zeidler 
20227f5d579SClemens Zeidler 			// Find crossing by tab position in group and if not exist create
20327f5d579SClemens Zeidler 			// it.
20427f5d579SClemens Zeidler 			BReference<Crossing>	_CrossingByPosition(Crossing* crossing,
20527f5d579SClemens Zeidler 										SATGroup* group);
20627f5d579SClemens Zeidler 
207e0bc3d9eSClemens Zeidler 			void				_MoveToSAT(SATWindow* topWindow);
208e0bc3d9eSClemens Zeidler 
209e0bc3d9eSClemens Zeidler 			BReference<SATGroup>	fGroup;
21027f5d579SClemens Zeidler 
21127f5d579SClemens Zeidler 			SATWindowList		fWindowList;
21227f5d579SClemens Zeidler 
21327f5d579SClemens Zeidler 			SATWindowList		fWindowLayerOrder;
21427f5d579SClemens Zeidler 
21527f5d579SClemens Zeidler 			BReference<Crossing>	fLeftTopCrossing;
21627f5d579SClemens Zeidler 			BReference<Crossing>	fRightTopCrossing;
21727f5d579SClemens Zeidler 			BReference<Crossing>	fLeftBottomCrossing;
21827f5d579SClemens Zeidler 			BReference<Crossing>	fRightBottomCrossing;
219e0bc3d9eSClemens Zeidler 
220e0bc3d9eSClemens Zeidler 			Constraint*			fMinWidthConstraint;
221e0bc3d9eSClemens Zeidler 			Constraint*			fMinHeightConstraint;
222e0bc3d9eSClemens Zeidler 			Constraint*			fMaxWidthConstraint;
223e0bc3d9eSClemens Zeidler 			Constraint*			fMaxHeightConstraint;
224e0bc3d9eSClemens Zeidler 			Constraint*			fWidthConstraint;
225e0bc3d9eSClemens Zeidler 			Constraint*			fHeightConstraint;
226e0bc3d9eSClemens Zeidler 
227e0bc3d9eSClemens Zeidler 			MagneticBorder		fMagneticBorder;
22827f5d579SClemens Zeidler };
22927f5d579SClemens Zeidler 
23027f5d579SClemens Zeidler 
23127f5d579SClemens Zeidler typedef BObjectList<WindowArea> WindowAreaList;
23227f5d579SClemens Zeidler typedef BObjectList<Tab> TabList;
23327f5d579SClemens Zeidler 
23427f5d579SClemens Zeidler class BMessage;
23527f5d579SClemens Zeidler class StackAndTile;
23627f5d579SClemens Zeidler 
23727f5d579SClemens Zeidler 
23827f5d579SClemens Zeidler class SATGroup : public BReferenceable {
23927f5d579SClemens Zeidler public:
24027f5d579SClemens Zeidler 		friend class Tab;
24127f5d579SClemens Zeidler 		friend class WindowArea;
24227f5d579SClemens Zeidler 		friend class GroupCookie;
24327f5d579SClemens Zeidler 
24427f5d579SClemens Zeidler 								SATGroup();
24527f5d579SClemens Zeidler 								~SATGroup();
24627f5d579SClemens Zeidler 
24727f5d579SClemens Zeidler 			LinearSpec*			GetLinearSpec() { return &fLinearSpec; }
24827f5d579SClemens Zeidler 
24927f5d579SClemens Zeidler 			/*! Create a new WindowArea from the crossing and add the window. */
2503779f5cfSJohn Scipione 			bool				AddWindow(SATWindow* window, Tab* left,
2513779f5cfSJohn Scipione 									Tab* top, Tab* right, Tab* bottom);
25227f5d579SClemens Zeidler 			/*! Add a window to an existing window area. */
25327f5d579SClemens Zeidler 			bool				AddWindow(SATWindow* window, WindowArea* area,
25427f5d579SClemens Zeidler 									SATWindow* after = NULL);
25527f5d579SClemens Zeidler 			/*! If stayBelowMouse is true move the removed window below the
25627f5d579SClemens Zeidler 			cursor if necessary. */
25727f5d579SClemens Zeidler 			bool				RemoveWindow(SATWindow* window,
25827f5d579SClemens Zeidler 									bool stayBelowMouse = true);
25927f5d579SClemens Zeidler 			int32				CountItems();
26027f5d579SClemens Zeidler 			SATWindow*			WindowAt(int32 index);
26127f5d579SClemens Zeidler 
26294d4c319SJohn Scipione 			SATWindow*			ActiveWindow() const;
26394d4c319SJohn Scipione 			void				SetActiveWindow(SATWindow* window);
26494d4c319SJohn Scipione 
26527f5d579SClemens Zeidler 			const WindowAreaList&	GetAreaList() { return fWindowAreaList; }
26627f5d579SClemens Zeidler 
26727f5d579SClemens Zeidler 			/*! \return a sorted tab list. */
26827f5d579SClemens Zeidler 			const TabList*		HorizontalTabs();
26927f5d579SClemens Zeidler 			const TabList*		VerticalTabs();
27027f5d579SClemens Zeidler 
27127f5d579SClemens Zeidler 			Tab*				FindHorizontalTab(float position);
27227f5d579SClemens Zeidler 			Tab*				FindVerticalTab(float position);
27327f5d579SClemens Zeidler 
27427f5d579SClemens Zeidler 			void				WindowAreaRemoved(WindowArea* area);
27527f5d579SClemens Zeidler 
27627f5d579SClemens Zeidler 	static	status_t			RestoreGroup(const BMessage& archive,
27727f5d579SClemens Zeidler 									StackAndTile* sat);
27827f5d579SClemens Zeidler 			status_t			ArchiveGroup(BMessage& archive);
27927f5d579SClemens Zeidler 
28027f5d579SClemens Zeidler private:
28127f5d579SClemens Zeidler 			BReference<Tab>		_AddHorizontalTab(float position = 0);
28227f5d579SClemens Zeidler 			BReference<Tab>		_AddVerticalTab(float position = 0);
28327f5d579SClemens Zeidler 
28427f5d579SClemens Zeidler 			bool				_RemoveHorizontalTab(Tab* tab);
28527f5d579SClemens Zeidler 			bool				_RemoveVerticalTab(Tab* tab);
28627f5d579SClemens Zeidler 
28727f5d579SClemens Zeidler 			Tab*				_FindTab(const TabList& list, float position);
28827f5d579SClemens Zeidler 
28927f5d579SClemens Zeidler 			void				_SplitGroupIfNecessary(
29027f5d579SClemens Zeidler 									WindowArea* removedArea);
29127f5d579SClemens Zeidler 			void				_FillNeighbourList(
29227f5d579SClemens Zeidler 									WindowAreaList& neighbourWindows,
29327f5d579SClemens Zeidler 									WindowArea* area);
29427f5d579SClemens Zeidler 			void				_LeftNeighbours(
29527f5d579SClemens Zeidler 									WindowAreaList& neighbourWindows,
29627f5d579SClemens Zeidler 									WindowArea* window);
29727f5d579SClemens Zeidler 			void				_TopNeighbours(
29827f5d579SClemens Zeidler 									WindowAreaList& neighbourWindows,
29927f5d579SClemens Zeidler 									WindowArea* window);
30027f5d579SClemens Zeidler 			void				_RightNeighbours(
30127f5d579SClemens Zeidler 									WindowAreaList& neighbourWindows,
30227f5d579SClemens Zeidler 									WindowArea* window);
30327f5d579SClemens Zeidler 			void				_BottomNeighbours(
30427f5d579SClemens Zeidler 									WindowAreaList& neighbourWindows,
30527f5d579SClemens Zeidler 									WindowArea* window);
30627f5d579SClemens Zeidler 			bool				_FindConnectedGroup(WindowAreaList& seedList,
30727f5d579SClemens Zeidler 									WindowArea* removedArea,
30827f5d579SClemens Zeidler 									WindowAreaList& newGroup);
30927f5d579SClemens Zeidler 			void				_FollowSeed(WindowArea* area, WindowArea* veto,
31027f5d579SClemens Zeidler 									WindowAreaList& seedList,
31127f5d579SClemens Zeidler 									WindowAreaList& newGroup);
31227f5d579SClemens Zeidler 			void				_SpawnNewGroup(const WindowAreaList& newGroup);
31327f5d579SClemens Zeidler 
31427f5d579SClemens Zeidler 			void				_EnsureGroupIsOnScreen(SATGroup* group);
31527f5d579SClemens Zeidler 	inline	void				_CallculateXOffset(BPoint& offset, BRect& frame,
31627f5d579SClemens Zeidler 									BRect& screen);
31727f5d579SClemens Zeidler 	inline	void				_CallculateYOffset(BPoint& offset, BRect& frame,
31827f5d579SClemens Zeidler 									BRect& screen);
31927f5d579SClemens Zeidler 
32027f5d579SClemens Zeidler protected:
32127f5d579SClemens Zeidler 			WindowAreaList		fWindowAreaList;
32227f5d579SClemens Zeidler 			SATWindowList		fSATWindowList;
32327f5d579SClemens Zeidler 
32427f5d579SClemens Zeidler 			LinearSpec			fLinearSpec;
32527f5d579SClemens Zeidler 
32627f5d579SClemens Zeidler private:
32727f5d579SClemens Zeidler 			TabList				fHorizontalTabs;
32827f5d579SClemens Zeidler 			bool				fHorizontalTabsSorted;
32927f5d579SClemens Zeidler 			TabList				fVerticalTabs;
33027f5d579SClemens Zeidler 			bool				fVerticalTabsSorted;
33194d4c319SJohn Scipione 
33294d4c319SJohn Scipione 			SATWindow*			fActiveWindow;
33327f5d579SClemens Zeidler };
33427f5d579SClemens Zeidler 
33527f5d579SClemens Zeidler 
33627f5d579SClemens Zeidler typedef BObjectList<SATGroup> SATGroupList;
33727f5d579SClemens Zeidler 
33827f5d579SClemens Zeidler #endif
339