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