xref: /haiku/src/tests/servers/app/playground/ObjectView.cpp (revision c90684742e7361651849be4116d0e5de3a817194)
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 //	SetHighColor(0, 0, 0);
103 //	for (float i = 10; i < 200; i += 4.25) {
104 //		StrokeLine(BPoint(i, 10), BPoint(i, 200));
105 //		StrokeLine(BPoint(10, i), BPoint(200, i));
106 //	}
107 //
108 //	SetHighColor(0, 0, 50);
109 //	for (float i = 10; i < 200; i += 8.25) {
110 //		FillRect(BRect(i, 10 + 230, i + 2, 200 + 230));
111 //		FillRect(BRect(10, i + 230, 200, i + 2 + 230));
112 //	}
113 //
114 //	rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR);
115 //	rgb_color shadow = tint_color(noTint, B_DARKEN_2_TINT);
116 //	rgb_color light = tint_color(noTint, B_LIGHTEN_MAX_TINT);
117 
118 	BRect r(Bounds());
119 
120 /*	BeginLineArray(4);
121 	AddLine(BPoint(r.left, r.top),
122 			BPoint(r.right, r.top), shadow);
123 	AddLine(BPoint(r.right, r.top + 1),
124 			BPoint(r.right, r.bottom), light);
125 	AddLine(BPoint(r.right - 1, r.bottom),
126 			BPoint(r.left, r.bottom), light);
127 	AddLine(BPoint(r.left, r.bottom - 1),
128 			BPoint(r.left, r.top + 1), shadow);
129 	EndLineArray();*/
130 
131 //Sync();
132 //	SetHighColor(200, 200, 200, 255);
133 ////	BRect rect(0.0, 0.0, 10.0, 11.0);
134 //	int32 counter = 0;
135 //	BRegion region;
136 ////	while (rect.top < r.bottom) {
137 ////		while (rect.left < r.right) {
138 ////			region.Include(rect);
139 ////			rect.OffsetBy(rect.Width() + 2, 0.0);
140 ////
141 ////			counter++;
142 ////		}
143 ////		rect.OffsetTo(0.0, rect.top + rect.Height() + 2);
144 ////	}
145 //	BRect rect(0.0, 0.0, 0.0, 10.0);
146 //	for (int32 i = 0; i < 100; i++) {
147 //		region.Include(rect);
148 //		rect.OffsetBy(rect.Width() + 1, 1.0);
149 //		counter++;
150 //	}
151 //bigtime_t now = system_time();
152 //	FillRegion(&region);
153 //Sync();
154 //printf("rendering %ld small rects (region: %ld): %lld\n", counter,
155 //region.CountRects(), system_time() - now);
156 
157 	SetDrawingMode(B_OP_OVER);
158 	SetHighColor(255, 0, 0, 128);
159 
160 	const char* message = "Click and drag to draw an object";
161 	float width = StringWidth(message);
162 
163 	BPoint p((r.Width() - width) / 2.0, r.Height() / 2.0);
164 
165 //Sync();
166 //snooze(1000);
167 //
168 //bigtime_t now = system_time();
169 //
170 //#ifdef __HAIKU__
171 //	BFont font;
172 //	GetFont(&font);
173 //	font.SetFalseBoldWidth(1.0);
174 //	SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
175 //	SetHighColor(0, 0, 0);
176 //	DrawString(message, p);
177 //
178 //	font.SetFalseBoldWidth(0.0);
179 //	SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
180 //	SetHighColor(255, 0, 0);
181 //#endif // __HAIKU__
182 
183 	DrawString(message, p);
184 
185 //Sync();
186 //printf("Drawing Text: %lld\n", system_time() - now);
187 
188 //	r.OffsetTo(B_ORIGIN);
189 //
190 //now = system_time();
191 //	int32 rectCount = 20;
192 //	BeginLineArray(4 * rectCount);
193 //	for (int32 i = 0; i < rectCount; i++) {
194 //		r.InsetBy(5, 5);
195 //
196 //		AddLine(BPoint(r.left, r.top),
197 //				BPoint(r.right, r.top), shadow);
198 //		AddLine(BPoint(r.right, r.top + 1),
199 //				BPoint(r.right, r.bottom), light);
200 //		AddLine(BPoint(r.right - 1, r.bottom),
201 //				BPoint(r.left, r.bottom), light);
202 //		AddLine(BPoint(r.left, r.bottom - 1),
203 //				BPoint(r.left, r.top + 1), shadow);
204 //	}
205 //	EndLineArray();
206 //Sync();
207 //printf("Drawing Lines: %lld\n", system_time() - now);
208 
209 //Flush();
210 //Sync();
211 //bigtime_t start = system_time();
212 //SetDrawingMode(B_OP_ALPHA);
213 //SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
214 //SetHighColor(0, 0, 255, 128);
215 //FillRect(BRect(0, 0, 250, 300));
216 //Sync();
217 //printf("Alpha Fill: %lld\n", system_time() - start);
218 
219 	for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
220 		state->Draw(this);
221 //Sync();
222 //printf("State: %lld\n", system_time() - start);
223 }
224 
225 // MouseDown
226 void
227 ObjectView::MouseDown(BPoint where)
228 {
229 	uint32 buttons;
230 	int32 clicks;
231 //
232 //	snooze(1000000);
233 //	BMessageQueue* queue = Window()->MessageQueue();
234 //	BMessage* msg;
235 //	int32 count = 0;
236 //	for (int32 i = 0; (msg = queue->FindMessage(i)); i++) {
237 //		if (msg->what == B_MOUSE_MOVED)
238 //			count++;
239 //	}
240 //	printf("B_MOUSE_MOVED count before GetMouse(): %ld\n", count);
241 //
242 //	GetMouse(&where, &buttons);
243 //
244 //	count = 0;
245 //	for (int32 i = 0; (msg = queue->FindMessage(i)); i++) {
246 //		if (msg->what == B_MOUSE_MOVED)
247 //			count++;
248 //	}
249 //	printf("B_MOUSE_MOVED count after 1st GetMouse(): %ld\n", count);
250 //
251 //	GetMouse(&where, &buttons);
252 //
253 //	count = 0;
254 //	for (int32 i = 0; (msg = queue->FindMessage(i)); i++) {
255 //		if (msg->what == B_MOUSE_MOVED)
256 //			count++;
257 //	}
258 //	printf("B_MOUSE_MOVED count after 2nd GetMouse(): %ld\n", count);
259 //	return;
260 
261 //be_app->HideCursor();
262 
263 	Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
264 	Window()->CurrentMessage()->FindInt32("clicks", &clicks);
265 //printf("ObjectView::MouseDown() - clicks: %ld\n", clicks);
266 	fInitiatingDrag = buttons & B_SECONDARY_MOUSE_BUTTON;
267 	fScrolling = !fInitiatingDrag && (buttons & B_TERTIARY_MOUSE_BUTTON);
268 
269 	SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
270 
271 	if (fScrolling  || fInitiatingDrag) {
272 		fLastMousePos = where;
273 	} else {
274 		if (!fState)
275 			AddObject(State::StateFor(fObjectType, fColor, fDrawingMode,
276 									  fFill, fPenSize));
277 
278 		if (fState) {
279 			fState->MouseDown(where);
280 		}
281 	}
282 }
283 
284 // MouseUp
285 void
286 ObjectView::MouseUp(BPoint where)
287 {
288 //be_app->ShowCursor();
289 
290 	if (fScrolling) {
291 		fScrolling = false;
292 	} else {
293 		if (fState) {
294 			fState->MouseUp();
295 		}
296 	}
297 }
298 
299 // MouseMoved
300 void
301 ObjectView::MouseMoved(BPoint where, uint32 transit,
302 					   const BMessage* dragMessage)
303 {
304 //	BRect dirty(where, where);
305 //	dirty.InsetBy(-10, -10);
306 //	Invalidate(dirty);
307 
308 if (dragMessage) {
309 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f)) - DRAG MESSAGE\n", where.x, where.y);
310 //Window()->CurrentMessage()->PrintToStream();
311 } else {
312 //printf("ObjectView::MouseMoved(BPoint(%.1f, %.1f))\n", where.x, where.y);
313 }
314 
315 	if (fScrolling) {
316 		BCursor cursor(kGrabCursor);
317 		SetViewCursor(&cursor);
318 
319 		BPoint offset = fLastMousePos - where;
320 		ScrollBy(offset.x, offset.y);
321 		fLastMousePos = where + offset;
322 	} else if (fInitiatingDrag) {
323 		BPoint offset = fLastMousePos - where;
324 		if (sqrtf(offset.x * offset.x + offset.y * offset.y) > 5.0) {
325 			BMessage dragMessage('drag');
326 			BBitmap* dragBitmap = new BBitmap(BRect(0, 0, 40, 40), B_RGBA32, true);
327 			if (dragBitmap->Lock()) {
328 				BView* helper = new BView(dragBitmap->Bounds(), "offscreen view",
329 										  B_FOLLOW_ALL, B_WILL_DRAW);
330 				dragBitmap->AddChild(helper);
331 				helper->SetDrawingMode(B_OP_ALPHA);
332 				helper->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
333 
334 				BRect r(helper->Bounds());
335 				helper->SetHighColor(0, 0, 0, 128);
336 				helper->StrokeRect(r);
337 
338 				helper->SetHighColor(200, 200, 200, 100);
339 				r.InsetBy(1, 1);
340 				helper->FillRect(r);
341 
342 				helper->SetHighColor(0, 0, 0, 255);
343 				const char* text = "Test";
344 				float pos = (r.Width() - helper->StringWidth(text)) / 2;
345 				helper->DrawString(text, BPoint(pos, 25));
346 				helper->Sync();
347 			}
348 
349 			DragMessage(&dragMessage, dragBitmap, B_OP_ALPHA, B_ORIGIN, this);
350 			fInitiatingDrag = false;
351 		}
352 	} else {
353 		BCursor cursor(kMoveCursor);
354 		SetViewCursor(&cursor);
355 
356 		if (fState && fState->IsTracking()) {
357 			BRect before = fState->Bounds();
358 
359 			fState->MouseMoved(where);
360 
361 			BRect after = fState->Bounds();
362 			BRect invalid(before | after);
363 			Invalidate(invalid);
364 		}
365 	}
366 //	SetViewCursor();
367 }
368 
369 // MessageReceived
370 void
371 ObjectView::MessageReceived(BMessage* message)
372 {
373 	switch (message->what) {
374 		case 'drag':
375 			printf("ObjectView::MessageReceived() - received drag message\n");
376 			break;
377 		default:
378 			BView::MessageReceived(message);
379 			break;
380 	}
381 }
382 
383 // SetState
384 void
385 ObjectView::SetState(State* state)
386 {
387 	if (fState != state) {
388 		if (fState) {
389 			fState->SetEditing(false);
390 			Invalidate(fState->Bounds());
391 		}
392 
393 		fState = state;
394 
395 		if (fState) {
396 			fState->SetEditing(true);
397 			Invalidate(fState->Bounds());
398 		}
399 	}
400 }
401 
402 // SetObjectType
403 void
404 ObjectView::SetObjectType(int32 type)
405 {
406 	if (type != fObjectType) {
407 		fObjectType = type;
408 		SetState(NULL);
409 	}
410 }
411 
412 // AddObject
413 void
414 ObjectView::AddObject(State* state)
415 {
416 	if (state) {
417 		fStateList.AddItem((void*)state);
418 
419 		BMessage message(MSG_OBJECT_ADDED);
420 		message.AddPointer("object", state);
421 		Window()->PostMessage(&message);
422 
423 		SetState(state);
424 	}
425 }
426 
427 // RemoveObject
428 void
429 ObjectView::RemoveObject(State* state)
430 {
431 	if (state && fStateList.RemoveItem((void*)state)) {
432 		if (fState == state)
433 			SetState(NULL);
434 		else
435 			Invalidate(state->Bounds());
436 
437 		Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
438 
439 		delete state;
440 	}
441 }
442 
443 // CountObjects
444 int32
445 ObjectView::CountObjects() const
446 {
447 	return fStateList.CountItems();
448 }
449 
450 // MakeEmpty
451 void
452 ObjectView::MakeEmpty()
453 {
454 	for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
455 		delete state;
456 	fStateList.MakeEmpty();
457 
458 	Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
459 
460 	fState = NULL;
461 
462 	Invalidate();
463 }
464 
465 // SetStateColor
466 void
467 ObjectView::SetStateColor(rgb_color color)
468 {
469 	if (color.red != fColor.red ||
470 		color.green != fColor.green ||
471 		color.blue != fColor.blue ||
472 		color.alpha != fColor.alpha) {
473 
474 		fColor = color;
475 
476 		if (fState) {
477 			fState->SetColor(fColor);
478 			Invalidate(fState->Bounds());
479 		}
480 	}
481 }
482 
483 // SetStateDrawingMode
484 void
485 ObjectView::SetStateDrawingMode(drawing_mode mode)
486 {
487 	if (fDrawingMode != mode) {
488 		fDrawingMode = mode;
489 
490 		if (fState) {
491 			fState->SetDrawingMode(fDrawingMode);
492 			Invalidate(fState->Bounds());
493 		}
494 	}
495 }
496 
497 // SetStateFill
498 void
499 ObjectView::SetStateFill(bool fill)
500 {
501 	if (fFill != fill) {
502 		fFill = fill;
503 
504 		if (fState) {
505 			BRect before = fState->Bounds();
506 
507 			fState->SetFill(fFill);
508 
509 			BRect after = fState->Bounds();
510 			BRect invalid(before | after);
511 			Invalidate(invalid);
512 		}
513 	}
514 }
515 
516 // SetStatePenSize
517 void
518 ObjectView::SetStatePenSize(float penSize)
519 {
520 	if (fPenSize != penSize) {
521 		fPenSize = penSize;
522 
523 		if (fState) {
524 			BRect before = fState->Bounds();
525 
526 			fState->SetPenSize(fPenSize);
527 
528 			BRect after = fState->Bounds();
529 			BRect invalid(before | after);
530 			Invalidate(invalid);
531 		}
532 	}
533 }
534