xref: /haiku/src/tests/servers/app/playground/ObjectView.cpp (revision ac078a5b110045de12089052a685a6a080545db1)
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 newDragMessage('drag');
326 			BBitmap* dragBitmap = new BBitmap(BRect(0, 0, 40, 40), B_RGBA32,
327 				true);
328 			if (dragBitmap->Lock()) {
329 				BView* helper = new BView(dragBitmap->Bounds(),
330 					"offscreen view", B_FOLLOW_ALL, B_WILL_DRAW);
331 				dragBitmap->AddChild(helper);
332 				helper->SetDrawingMode(B_OP_ALPHA);
333 				helper->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE);
334 
335 				BRect r(helper->Bounds());
336 				helper->SetHighColor(0, 0, 0, 128);
337 				helper->StrokeRect(r);
338 
339 				helper->SetHighColor(200, 200, 200, 100);
340 				r.InsetBy(1, 1);
341 				helper->FillRect(r);
342 
343 				helper->SetHighColor(0, 0, 0, 255);
344 				const char* text = "Test";
345 				float pos = (r.Width() - helper->StringWidth(text)) / 2;
346 				helper->DrawString(text, BPoint(pos, 25));
347 				helper->Sync();
348 			}
349 
350 			DragMessage(&newDragMessage, dragBitmap, B_OP_ALPHA, B_ORIGIN,
351 				this);
352 			fInitiatingDrag = false;
353 		}
354 	} else {
355 		BCursor cursor(kMoveCursor);
356 		SetViewCursor(&cursor);
357 
358 		if (fState && fState->IsTracking()) {
359 			BRect before = fState->Bounds();
360 
361 			fState->MouseMoved(where);
362 
363 			BRect after = fState->Bounds();
364 			BRect invalid(before | after);
365 			Invalidate(invalid);
366 		}
367 	}
368 //	SetViewCursor();
369 }
370 
371 // MessageReceived
372 void
373 ObjectView::MessageReceived(BMessage* message)
374 {
375 	switch (message->what) {
376 		case 'drag':
377 			printf("ObjectView::MessageReceived() - received drag message\n");
378 			break;
379 		default:
380 			BView::MessageReceived(message);
381 			break;
382 	}
383 }
384 
385 // SetState
386 void
387 ObjectView::SetState(State* state)
388 {
389 	if (fState != state) {
390 		if (fState) {
391 			fState->SetEditing(false);
392 			Invalidate(fState->Bounds());
393 		}
394 
395 		fState = state;
396 
397 		if (fState) {
398 			fState->SetEditing(true);
399 			Invalidate(fState->Bounds());
400 		}
401 	}
402 }
403 
404 // SetObjectType
405 void
406 ObjectView::SetObjectType(int32 type)
407 {
408 	if (type != fObjectType) {
409 		fObjectType = type;
410 		SetState(NULL);
411 	}
412 }
413 
414 // AddObject
415 void
416 ObjectView::AddObject(State* state)
417 {
418 	if (state) {
419 		fStateList.AddItem((void*)state);
420 
421 		BMessage message(MSG_OBJECT_ADDED);
422 		message.AddPointer("object", state);
423 		Window()->PostMessage(&message);
424 
425 		SetState(state);
426 	}
427 }
428 
429 // RemoveObject
430 void
431 ObjectView::RemoveObject(State* state)
432 {
433 	if (state && fStateList.RemoveItem((void*)state)) {
434 		if (fState == state)
435 			SetState(NULL);
436 		else
437 			Invalidate(state->Bounds());
438 
439 		Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
440 
441 		delete state;
442 	}
443 }
444 
445 // CountObjects
446 int32
447 ObjectView::CountObjects() const
448 {
449 	return fStateList.CountItems();
450 }
451 
452 // MakeEmpty
453 void
454 ObjectView::MakeEmpty()
455 {
456 	for (int32 i = 0; State* state = (State*)fStateList.ItemAt(i); i++)
457 		delete state;
458 	fStateList.MakeEmpty();
459 
460 	Window()->PostMessage(MSG_OBJECT_COUNT_CHANGED);
461 
462 	fState = NULL;
463 
464 	Invalidate();
465 }
466 
467 // SetStateColor
468 void
469 ObjectView::SetStateColor(rgb_color color)
470 {
471 	if (color.red != fColor.red ||
472 		color.green != fColor.green ||
473 		color.blue != fColor.blue ||
474 		color.alpha != fColor.alpha) {
475 
476 		fColor = color;
477 
478 		if (fState) {
479 			fState->SetColor(fColor);
480 			Invalidate(fState->Bounds());
481 		}
482 	}
483 }
484 
485 // SetStateDrawingMode
486 void
487 ObjectView::SetStateDrawingMode(drawing_mode mode)
488 {
489 	if (fDrawingMode != mode) {
490 		fDrawingMode = mode;
491 
492 		if (fState) {
493 			fState->SetDrawingMode(fDrawingMode);
494 			Invalidate(fState->Bounds());
495 		}
496 	}
497 }
498 
499 // SetStateFill
500 void
501 ObjectView::SetStateFill(bool fill)
502 {
503 	if (fFill != fill) {
504 		fFill = fill;
505 
506 		if (fState) {
507 			BRect before = fState->Bounds();
508 
509 			fState->SetFill(fFill);
510 
511 			BRect after = fState->Bounds();
512 			BRect invalid(before | after);
513 			Invalidate(invalid);
514 		}
515 	}
516 }
517 
518 // SetStatePenSize
519 void
520 ObjectView::SetStatePenSize(float penSize)
521 {
522 	if (fPenSize != penSize) {
523 		fPenSize = penSize;
524 
525 		if (fState) {
526 			BRect before = fState->Bounds();
527 
528 			fState->SetPenSize(fPenSize);
529 
530 			BRect after = fState->Bounds();
531 			BRect invalid(before | after);
532 			Invalidate(invalid);
533 		}
534 	}
535 }
536