1#include <Message.h>
2#include <Messenger.h>
3#include <Window.h>
4
5#include <stdio.h>
6#include <stack.h>
7
8#include "MyView.h"
9#include "Layer.h"
10
11extern BWindow *wind;
12struct node {
13			node()
14			{
15				pointers = NULL;
16			}
17			node(const BRect& r, int32 maxPointers)
18			{
19				init(r, maxPointers);
20			}
21			~node()
22			{
23				delete [] pointers;
24			}
25
26	void	init(const BRect& r, int32 maxPointers)
27			{
28				rect = r;
29				pointers = new node*[maxPointers];
30				in_degree = 0;
31				next_pointer = 0;
32			}
33
34	void	push(node* node)
35			{
36				pointers[next_pointer] = node;
37				next_pointer++;
38			}
39	node*	top()
40			{
41				return pointers[next_pointer];
42			}
43	node*	pop()
44			{
45				node* ret = top();
46				next_pointer--;
47				return ret;
48			}
49
50	BRect	rect;
51	int32	in_degree;
52	node**	pointers;
53	int32	next_pointer;
54};
55
56bool
57is_left_of(const BRect& a, const BRect& b)
58{
59	return (a.right < b.left);
60}
61bool
62is_above(const BRect& a, const BRect& b)
63{
64	return (a.bottom < b.top);
65}
66
67MyView::MyView(BRect frame, const char *name, uint32 resizingMode, uint32 flags)
68	: BView(frame, name, resizingMode, flags)
69{
70	SetViewColor(B_TRANSPARENT_COLOR);
71	fTracking	= false;
72	fIsResize	= false;
73	fIs2ndButton= false;
74	fMovingLayer = NULL;
75
76	rgb_color	col;
77	col.red		= 49;
78	col.green	= 101;
79	col.blue	= 156;
80	topLayer = new Layer(Bounds(), "topLayer", B_FOLLOW_ALL, 0, col);
81	topLayer->SetRootLayer(this);
82
83	topLayer->rebuild_visible_regions(BRegion(Bounds()), BRegion(Bounds()), NULL);
84	fRedrawReg.Set(Bounds());
85}
86
87MyView::~MyView()
88{
89	delete topLayer;
90}
91
92Layer* MyView::FindLayer(Layer *lay, BPoint &where) const
93{
94	if (lay->Visible()->Contains(where))
95		return lay;
96	else
97		for (Layer *child = lay->BottomChild(); child; child = lay->UpperSibling())
98		{
99			Layer	*found = FindLayer(child, where);
100			if (found)
101				return found;
102		}
103	return NULL;
104}
105
106void MyView::MouseDown(BPoint where)
107{
108	SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
109	int32		buttons;
110	Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
111	fLastPos = where;
112	if (buttons == B_PRIMARY_MOUSE_BUTTON)
113	{
114		fTracking = true;
115		fMovingLayer = FindLayer(topLayer, where);
116		if (fMovingLayer == topLayer)
117			fMovingLayer = NULL;
118		if (fMovingLayer)
119		{
120			BRect	bounds(fMovingLayer->Bounds());
121			fMovingLayer->ConvertToScreen2(&bounds);
122			BRect	resizeRect(bounds.right-10, bounds.bottom-10, bounds.right, bounds.bottom);
123			if (resizeRect.Contains(where))
124				fIsResize = true;
125			else
126				fIsResize = false;
127		}
128	}
129	else if (buttons == B_SECONDARY_MOUSE_BUTTON)
130	{
131		fIs2ndButton = true;
132	}
133	else if (buttons == B_TERTIARY_MOUSE_BUTTON)
134	{
135		DrawSubTree(topLayer);
136	}
137}
138
139void MyView::MouseUp(BPoint where)
140{
141	fTracking = false;
142	fIs2ndButton = false;
143	fMovingLayer = NULL;
144}
145
146void MyView::MouseMoved(BPoint where, uint32 code, const BMessage *a_message)
147{
148	if (fTracking)
149	{
150		float dx, dy;
151		dx = where.x - fLastPos.x;
152		dy = where.y - fLastPos.y;
153		fLastPos = where;
154
155		if (dx != 0 || dy != 0)
156		{
157			if (fMovingLayer)
158			{
159bigtime_t now = system_time();
160				if (fIsResize) {
161					fMovingLayer->ResizeBy(dx, dy);
162printf("resizing: %lld\n", system_time() - now);
163				} else {
164					fMovingLayer->MoveBy(dx, dy);
165printf("moving: %lld\n", system_time() - now);
166				}
167			}
168		}
169	}
170	else if (fIs2ndButton)
171	{
172		SetHighColor(0,0,0);
173		StrokeLine(fLastPos, where);
174		Flush();
175		fLastPos = where;
176	}
177}
178
179void MyView::MessageReceived(BMessage *msg)
180{
181	switch(msg->what)
182	{
183		case B_MOUSE_WHEEL_CHANGED:
184		{
185			float	dy;
186			msg->FindFloat("be:wheel_delta_y", &dy);
187
188			BPoint	pt;
189			uint32	buttons;
190			Layer	*lay;
191			GetMouse(&pt, &buttons, false);
192			if ((lay = FindLayer(topLayer, pt)))
193				lay->ScrollBy(0, dy*5);
194			break;
195		}
196		default:
197			BView::MessageReceived(msg);
198	}
199}
200
201void MyView::CopyRegion(BRegion *region, int32 xOffset, int32 yOffset)
202{
203wind->Lock();
204		int32 count = region->CountRects();
205
206		// TODO: make this step unnecessary
207		// (by using different stack impl inside node)
208		node nodes[count];
209		for (int32 i= 0; i < count; i++) {
210			nodes[i].init(region->RectAt(i), count);
211		}
212
213		for (int32 i = 0; i < count; i++) {
214			BRect a = region->RectAt(i);
215			for (int32 k = i + 1; k < count; k++) {
216				BRect b = region->RectAt(k);
217				int cmp = 0;
218				// compare horizontally
219				if (xOffset > 0) {
220					if (is_left_of(a, b)) {
221						cmp -= 1;
222					} else if (is_left_of(b, a)) {
223						cmp += 1;
224					}
225				} else if (xOffset < 0) {
226					if (is_left_of(a, b)) {
227						cmp += 1;
228					} else if (is_left_of(b, a)) {
229						cmp -= 1;
230					}
231				}
232				// compare vertically
233				if (yOffset > 0) {
234					if (is_above(a, b)) {
235						cmp -= 1;
236					} else if (is_above(b, a)) {
237						cmp += 1;
238					}
239				} else if (yOffset < 0) {
240					if (is_above(a, b)) {
241						cmp += 1;
242					} else if (is_above(b, a)) {
243						cmp -= 1;
244					}
245				}
246				// add appropriate node as successor
247				if (cmp > 0) {
248					nodes[i].push(&nodes[k]);
249					nodes[k].in_degree++;
250				} else if (cmp < 0) {
251					nodes[k].push(&nodes[i]);
252					nodes[i].in_degree++;
253				}
254			}
255		}
256		// put all nodes onto a stack that have an "indegree" count of zero
257		stack<node*> inDegreeZeroNodes;
258		for (int32 i = 0; i < count; i++) {
259			if (nodes[i].in_degree == 0) {
260				inDegreeZeroNodes.push(&nodes[i]);
261			}
262		}
263		// pop the rects from the stack, do the actual copy operation
264		// and decrease the "indegree" count of the other rects not
265		// currently on the stack and to which the current rect pointed
266		// to. If their "indegree" count reaches zero, put them onto the
267		// stack as well.
268
269		while (!inDegreeZeroNodes.empty()) {
270			node* n = inDegreeZeroNodes.top();
271			inDegreeZeroNodes.pop();
272
273			CopyBits(n->rect, BRect(n->rect).OffsetByCopy(xOffset, yOffset));
274
275			for (int32 k = 0; k < n->next_pointer; k++) {
276				n->pointers[k]->in_degree--;
277				if (n->pointers[k]->in_degree == 0)
278					inDegreeZeroNodes.push(n->pointers[k]);
279			}
280		}
281wind->Unlock();
282}
283
284void MyView::RequestRedraw()
285{
286	wind->Lock();
287
288	ConstrainClippingRegion(&fRedrawReg);
289	PushState();
290	DrawSubTree(topLayer);
291	PopState();
292	ConstrainClippingRegion(NULL);
293
294	fRedrawReg.MakeEmpty();
295
296	wind->Unlock();
297}
298
299void MyView::Draw(BRect area)
300{
301	// empty. you can trigger a redraw by clicking the middle mouse button.
302}
303
304void MyView::DrawSubTree(Layer* lay)
305{
306//printf("======== %s =======\n", lay->Name());
307//	lay->Visible()->PrintToStream();
308//	lay->FullVisible()->PrintToStream();
309	for (Layer *child = lay->BottomChild(); child; child = lay->UpperSibling())
310		DrawSubTree(child);
311
312	ConstrainClippingRegion(lay->Visible());
313	SetHighColor(lay->HighColor());
314	BRegion	reg;
315	lay->GetWantedRegion(reg);
316	FillRect(reg.Frame());
317	Flush();
318	ConstrainClippingRegion(NULL);
319}
320