xref: /haiku/src/tests/servers/app/playground/ObjectView.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
1 // ObjectView.cpp
2 
3 #include <stdio.h>
4 
5 #include <Application.h>
6 #include <Bitmap.h>
7 #include <Cursor.h>
8 #include <Message.h>
9 #include <MessageQueue.h>
10 #include <Region.h>
11 #include <Shape.h>
12 #include <String.h>
13 #include <Window.h>
14 
15 #include "States.h"
16 
17 #include "ObjectView.h"
18 
19 const unsigned char kMoveCursor[] = { 16, 1, 8, 8,
20 	0x01, 0x80, 0x02, 0x40, 0x04, 0x20, 0x08, 0x10,
21 	0x1e, 0x78, 0x2a, 0x54, 0x4e, 0x72, 0x80, 0x01,
22 	0x80, 0x01, 0x4e, 0x72, 0x2a, 0x54, 0x1e, 0x78,
23 	0x08, 0x10, 0x04, 0x20, 0x02, 0x40, 0x01, 0x80,
24 
25 	0x01, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0,
26 	0x1f, 0xf8, 0x3b, 0xdc, 0x7f, 0xfe, 0xff, 0xff,
27 	0xff, 0xff, 0x7f, 0xfe, 0x3b, 0xdc, 0x1f, 0xf8,
28 	0x0f, 0xf0, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0x80 };
29 
30 const unsigned char kGrabCursor[] = { 16, 1, 8, 9,
31 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 	0x0d, 0xb0, 0x12, 0x4c, 0x10, 0x0a, 0x08, 0x02,
33 	0x18, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x04,
34 	0x10, 0x04, 0x08, 0x08, 0x04, 0x08, 0x04, 0x08,
35 
36 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 	0x0d, 0xb0, 0x1f, 0xfc, 0x1f, 0xfe, 0x0f, 0xfe,
38 	0x1f, 0xfe, 0x3f, 0xfe, 0x3f, 0xfe, 0x3f, 0xfc,
39 	0x1f, 0xfc, 0x0f, 0xf8, 0x07, 0xf8, 0x07, 0xf8 };
40 
41 
42 // constructor
43 ObjectView::ObjectView(BRect frame, const char* name,
44 					 uint32 resizeFlags, uint32 flags)
45 	: BView(frame, name, resizeFlags, flags),
46 	  fState(NULL),
47 	  fObjectType(OBJECT_LINE),
48 	  fStateList(20),
49 	  fColor((rgb_color){ 0, 80, 255, 100 }),
50 	  fDrawingMode(B_OP_ALPHA),
51 	  fFill(false),
52 	  fPenSize(10.0),
53 	  fScrolling(false),
54 	  fInitiatingDrag(false),
55 	  fLastMousePos(0.0, 0.0)
56 {
57 
58 	SetLowColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_1_TINT));
59 
60 //	BFont font;
61 //	GetFont(&font);
62 //	font.SetFamilyAndStyle("Bitstream Vera Serif", "Roman");
63 //	font.SetSize(20.0);
64 ////	font.SetRotation(6.0);
65 //	SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_ROTATION | B_FONT_SIZE);
66 
67 //	State* state = State::StateFor(OBJECT_ROUND_RECT, fColor, B_OP_COPY,
68 //								   false, 50.0);
69 //	state->MouseDown(BPoint(15, 15));
70 //	state->MouseMoved(BPoint(255, 305));
71 //	state->MouseUp();
72 //
73 //	AddObject(state);
74 
75 	SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
76 }
77 
78 // destructor
79 ObjectView::~ObjectView()
80 {
81 }
82 
83 // AttachedToWindow
84 void
85 ObjectView::AttachedToWindow()
86 {
87 	SetViewColor(B_TRANSPARENT_COLOR);
88 }
89 
90 // DetachedFromWindow
91 void
92 ObjectView::DetachedFromWindow()
93 {
94 }
95 
96 // Draw
97 void
98 ObjectView::Draw(BRect updateRect)
99 {
100 	FillRect(updateRect, B_SOLID_LOW);
101 
102 	rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR);
103 	rgb_color shadow = tint_color(noTint, B_DARKEN_2_TINT);
104 	rgb_color light = tint_color(noTint, B_LIGHTEN_MAX_TINT);
105 
106 	BRect r(Bounds());
107 
108 /*	BeginLineArray(4);
109 	AddLine(BPoint(r.left, r.top),
110 			BPoint(r.right, r.top), shadow);
111 	AddLine(BPoint(r.right, r.top + 1),
112 			BPoint(r.right, r.bottom), light);
113 	AddLine(BPoint(r.right - 1, r.bottom),
114 			BPoint(r.left, r.bottom), light);
115 	AddLine(BPoint(r.left, r.bottom - 1),
116 			BPoint(r.left, r.top + 1), shadow);
117 	EndLineArray();*/
118 
119 //Sync();
120 //	SetHighColor(200, 200, 200, 255);
121 ////	BRect rect(0.0, 0.0, 10.0, 11.0);
122 //	int32 counter = 0;
123 //	BRegion region;
124 ////	while (rect.top < r.bottom) {
125 ////		while (rect.left < r.right) {
126 ////			region.Include(rect);
127 ////			rect.OffsetBy(rect.Width() + 2, 0.0);
128 ////
129 ////			counter++;
130 ////		}
131 ////		rect.OffsetTo(0.0, rect.top + rect.Height() + 2);
132 ////	}
133 //	BRect rect(0.0, 0.0, 0.0, 10.0);
134 //	for (int32 i = 0; i < 100; i++) {
135 //		region.Include(rect);
136 //		rect.OffsetBy(rect.Width() + 1, 1.0);
137 //		counter++;
138 //	}
139 //bigtime_t now = system_time();
140 //	FillRegion(&region);
141 //Sync();
142 //printf("rendering %ld small rects (region: %ld): %lld\n", counter,
143 //region.CountRects(), system_time() - now);
144 
145 	SetDrawingMode(B_OP_COPY);
146 	SetHighColor(255, 0, 0, 128);
147 
148 	const char* message = "Click and drag to draw an object";
149 	float width = StringWidth(message);
150 
151 	BPoint p((r.Width() - width) / 2.0, r.Height() / 2.0);
152 
153 //Sync();
154 //snooze(1000);
155 //
156 //bigtime_t now = system_time();
157 	DrawString(message, p);
158 
159 //Sync();
160 //printf("Drawing Text: %lld\n", system_time() - now);
161 
162 //	r.OffsetTo(B_ORIGIN);
163 //
164 //now = system_time();
165 //	int32 rectCount = 20;
166 //	BeginLineArray(4 * rectCount);
167 //	for (int32 i = 0; i < rectCount; i++) {
168 //		r.InsetBy(5, 5);
169 //
170 //		AddLine(BPoint(r.left, r.top),
171 //				BPoint(r.right, r.top), shadow);
172 //		AddLine(BPoint(r.right, r.top + 1),
173 //				BPoint(r.right, r.bottom), light);
174 //		AddLine(BPoint(r.right - 1, r.bottom),
175 //				BPoint(r.left, r.bottom), light);
176 //		AddLine(BPoint(r.left, r.bottom - 1),
177 //				BPoint(r.left, r.top + 1), shadow);
178 //	}
179 //	EndLineArray();
180 //Sync();
181 //printf("Drawing Lines: %lld\n", system_time() - now);
182 
183 //Flush();
184 //Sync();
185 //bigtime_t start = system_time();
186 //SetDrawingMode(B_OP_ALPHA);
187 //SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
188 //SetHighColor(0, 0, 255, 128);
189 //FillRect(BRect(0, 0, 250, 300));
190 //Sync();
191 //printf("Alpha Fill: %lld\n", system_time() - start);
192 
193 	for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
194 		state->Draw(this);
195 //Sync();
196 //printf("State: %lld\n", system_time() - start);
197 }
198 
199 // MouseDown
200 void
201 ObjectView::MouseDown(BPoint where)
202 {
203 	uint32 buttons;
204 	int32 clicks;
205 //
206 //	snooze(1000000);
207 //	BMessageQueue* queue = Window()->MessageQueue();
208 //	BMessage* msg;
209 //	int32 count = 0;
210 //	for (int32 i = 0; (msg = queue->FindMessage(i)); i++) {
211 //		if (msg->what == B_MOUSE_MOVED)
212 //			count++;
213 //	}
214 //	printf("B_MOUSE_MOVED count before GetMouse(): %ld\n", count);
215 //
216 //	GetMouse(&where, &buttons);
217 //
218 //	count = 0;
219 //	for (int32 i = 0; (msg = queue->FindMessage(i)); i++) {
220 //		if (msg->what == B_MOUSE_MOVED)
221 //			count++;
222 //	}
223 //	printf("B_MOUSE_MOVED count after 1st GetMouse(): %ld\n", count);
224 //
225 //	GetMouse(&where, &buttons);
226 //
227 //	count = 0;
228 //	for (int32 i = 0; (msg = queue->FindMessage(i)); i++) {
229 //		if (msg->what == B_MOUSE_MOVED)
230 //			count++;
231 //	}
232 //	printf("B_MOUSE_MOVED count after 2nd GetMouse(): %ld\n", count);
233 //	return;
234 
235 //be_app->HideCursor();
236 
237 	Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
238 	Window()->CurrentMessage()->FindInt32("clicks", &clicks);
239 //printf("ObjectView::MouseDown() - clicks: %ld\n", clicks);
240 	fInitiatingDrag = buttons & B_SECONDARY_MOUSE_BUTTON;
241 	fScrolling = !fInitiatingDrag && (buttons & B_TERTIARY_MOUSE_BUTTON);
242 
243 	SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
244 
245 	if (fScrolling  || fInitiatingDrag) {
246 		fLastMousePos = where;
247 	} else {
248 		if (!fState)
249 			AddObject(State::StateFor(fObjectType, fColor, fDrawingMode,
250 									  fFill, fPenSize));
251 
252 		if (fState) {
253 			fState->MouseDown(where);
254 		}
255 	}
256 }
257 
258 // MouseUp
259 void
260 ObjectView::MouseUp(BPoint where)
261 {
262 //be_app->ShowCursor();
263 
264 	if (fScrolling) {
265 		fScrolling = false;
266 	} else {
267 		if (fState) {
268 			fState->MouseUp();
269 		}
270 	}
271 }
272 
273 // MouseMoved
274 void
275 ObjectView::MouseMoved(BPoint where, uint32 transit,
276 					   const BMessage* dragMessage)
277 {
278 if (dragMessage) {
279 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f)) - DRAG MESSAGE\n", where.x, where.y);
280 //Window()->CurrentMessage()->PrintToStream();
281 } else {
282 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f))\n", where.x, where.y);
283 }
284 
285 	if (fScrolling) {
286 		BCursor cursor(kGrabCursor);
287 		SetViewCursor(&cursor);
288 
289 		BPoint offset = fLastMousePos - where;
290 		ScrollBy(offset.x, offset.y);
291 		fLastMousePos = where + offset;
292 	} else if (fInitiatingDrag) {
293 		BPoint offset = fLastMousePos - where;
294 		if (sqrtf(offset.x * offset.x + offset.y * offset.y) > 5.0) {
295 			BMessage dragMessage('drag');
296 			BBitmap* dragBitmap = new BBitmap(BRect(0, 0, 40, 40), B_RGBA32, true);
297 			if (dragBitmap->Lock()) {
298 				BView* helper = new BView(dragBitmap->Bounds(), "offscreen view",
299 										  B_FOLLOW_ALL, B_WILL_DRAW);
300 				dragBitmap->AddChild(helper);
301 				helper->SetDrawingMode(B_OP_ALPHA);
302 				helper->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
303 
304 				BRect r(helper->Bounds());
305 				helper->SetHighColor(0, 0, 0, 128);
306 				helper->StrokeRect(r);
307 
308 				helper->SetHighColor(200, 200, 200, 100);
309 				r.InsetBy(1, 1);
310 				helper->FillRect(r);
311 
312 				helper->SetHighColor(0, 0, 0, 255);
313 				const char* text = "Test";
314 				float pos = (r.Width() - helper->StringWidth(text)) / 2;
315 				helper->DrawString(text, BPoint(pos, 25));
316 				helper->Sync();
317 			}
318 
319 			DragMessage(&dragMessage, dragBitmap, B_OP_ALPHA, B_ORIGIN, this);
320 			fInitiatingDrag = false;
321 		}
322 	} else {
323 		BCursor cursor(kMoveCursor);
324 		SetViewCursor(&cursor);
325 
326 		if (fState && fState->IsTracking()) {
327 			BRect before = fState->Bounds();
328 
329 			fState->MouseMoved(where);
330 
331 			BRect after = fState->Bounds();
332 			BRect invalid(before | after);
333 			Invalidate(invalid);
334 		}
335 	}
336 //	SetViewCursor();
337 }
338 
339 // MessageReceived
340 void
341 ObjectView::MessageReceived(BMessage* message)
342 {
343 	switch (message->what) {
344 		case 'drag':
345 			printf("ObjectView::MessageReceived() - received drag message\n");
346 			break;
347 		default:
348 			BView::MessageReceived(message);
349 			break;
350 	}
351 }
352 
353 // SetState
354 void
355 ObjectView::SetState(State* state)
356 {
357 	if (fState != state) {
358 		if (fState) {
359 			fState->SetEditing(false);
360 			Invalidate(fState->Bounds());
361 		}
362 
363 		fState = state;
364 
365 		if (fState) {
366 			fState->SetEditing(true);
367 			Invalidate(fState->Bounds());
368 		}
369 	}
370 }
371 
372 // SetObjectType
373 void
374 ObjectView::SetObjectType(int32 type)
375 {
376 	if (type != fObjectType) {
377 		fObjectType = type;
378 		SetState(NULL);
379 	}
380 }
381 
382 // AddObject
383 void
384 ObjectView::AddObject(State* state)
385 {
386 	if (state) {
387 		fStateList.AddItem((void*)state);
388 
389 		BMessage message(MSG_OBJECT_ADDED);
390 		message.AddPointer("object", state);
391 		Window()->PostMessage(&message);
392 
393 		SetState(state);
394 	}
395 }
396 
397 // RemoveObject
398 void
399 ObjectView::RemoveObject(State* state)
400 {
401 	if (state && fStateList.RemoveItem((void*)state)) {
402 		if (fState == state)
403 			SetState(NULL);
404 		else
405 			Invalidate(state->Bounds());
406 
407 		Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
408 
409 		delete state;
410 	}
411 }
412 
413 // CountObjects
414 int32
415 ObjectView::CountObjects() const
416 {
417 	return fStateList.CountItems();
418 }
419 
420 // MakeEmpty
421 void
422 ObjectView::MakeEmpty()
423 {
424 	for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
425 		delete state;
426 	fStateList.MakeEmpty();
427 
428 	Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
429 
430 	fState = NULL;
431 
432 	Invalidate();
433 }
434 
435 // SetStateColor
436 void
437 ObjectView::SetStateColor(rgb_color color)
438 {
439 	if (color.red != fColor.red ||
440 		color.green != fColor.green ||
441 		color.blue != fColor.blue ||
442 		color.alpha != fColor.alpha) {
443 
444 		fColor = color;
445 
446 		if (fState) {
447 			fState->SetColor(fColor);
448 			Invalidate(fState->Bounds());
449 		}
450 	}
451 }
452 
453 // SetStateDrawingMode
454 void
455 ObjectView::SetStateDrawingMode(drawing_mode mode)
456 {
457 	if (fDrawingMode != mode) {
458 		fDrawingMode = mode;
459 
460 		if (fState) {
461 			fState->SetDrawingMode(fDrawingMode);
462 			Invalidate(fState->Bounds());
463 		}
464 	}
465 }
466 
467 // SetStateFill
468 void
469 ObjectView::SetStateFill(bool fill)
470 {
471 	if (fFill != fill) {
472 		fFill = fill;
473 
474 		if (fState) {
475 			BRect before = fState->Bounds();
476 
477 			fState->SetFill(fFill);
478 
479 			BRect after = fState->Bounds();
480 			BRect invalid(before | after);
481 			Invalidate(invalid);
482 		}
483 	}
484 }
485 
486 // SetStatePenSize
487 void
488 ObjectView::SetStatePenSize(float penSize)
489 {
490 	if (fPenSize != penSize) {
491 		fPenSize = penSize;
492 
493 		if (fState) {
494 			BRect before = fState->Bounds();
495 
496 			fState->SetPenSize(fPenSize);
497 
498 			BRect after = fState->Bounds();
499 			BRect invalid(before | after);
500 			Invalidate(invalid);
501 		}
502 	}
503 }
504