xref: /haiku/src/apps/cortex/DiagramView/DiagramView.cpp (revision 19ae20e67e91fc09cc9fc5c0e60e21e24e7a53eb)
1 /*
2  * Copyright (c) 1999-2000, Eric Moon.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions, and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions, and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 
32 // DiagramView.cpp
33 
34 #include "DiagramView.h"
35 #include "DiagramDefs.h"
36 #include "DiagramBox.h"
37 #include "DiagramEndPoint.h"
38 #include "DiagramWire.h"
39 
40 #include <Bitmap.h>
41 #include <Message.h>
42 #include <ScrollBar.h>
43 
44 __USE_CORTEX_NAMESPACE
45 
46 #include <Debug.h>
47 #define D_METHOD(x) //PRINT (x)
48 #define D_HOOK(x) //PRINT (x)
49 #define D_MESSAGE(x) //PRINT (x)
50 #define D_MOUSE(x) //PRINT (x)
51 #define D_DRAW(x) //PRINT (x)
52 
53 // -------------------------------------------------------- //
54 // *** ctor/dtor
55 // -------------------------------------------------------- //
56 
DiagramView(BRect frame,const char * name,bool multiSelection,uint32 resizingMode,uint32 flags)57 DiagramView::DiagramView(
58 	BRect frame,
59 	const char *name,
60 	bool multiSelection,
61 	uint32 resizingMode,
62 	uint32 flags)
63 	: BView(frame, name, resizingMode, B_WILL_DRAW | B_FRAME_EVENTS | flags),
64 	  DiagramItemGroup(DiagramItem::M_BOX | DiagramItem::M_WIRE),
65 	  m_lastButton(0),
66 	  m_clickCount(0),
67 	  m_lastClickPoint(-1.0, -1.0),
68 	  m_pressedButton(0),
69 	  m_draggedWire(0),
70 	  m_useBackgroundBitmap(false),
71 	  m_backgroundBitmap(0)
72 {
73 	D_METHOD(("DiagramView::DiagramView()\n"));
74 	SetViewColor(B_TRANSPARENT_COLOR);
75 	m_dataRect = Bounds();
76 }
77 
~DiagramView()78 DiagramView::~DiagramView()
79 {
80 	D_METHOD(("DiagramView::~DiagramView()\n"));
81 }
82 
83 // -------------------------------------------------------- //
84 // *** hook functions
85 // -------------------------------------------------------- //
86 
MessageDragged(BPoint point,uint32 transit,const BMessage * message)87 void DiagramView::MessageDragged(
88 	BPoint point,
89 	uint32 transit,
90 	const BMessage *message)
91 {
92 	D_METHOD(("DiagramView::MessageDragged()\n"));
93 	switch (message->what)
94 	{
95 		case M_WIRE_DRAGGED:
96 		{
97 			D_MESSAGE(("DiagramView::MessageDragged(M_WIRE_DROPPED)\n"));
98 			if (!m_draggedWire)
99 			{
100 				DiagramEndPoint *fromEndPoint;
101 				if (message->FindPointer("from", reinterpret_cast<void **>(&fromEndPoint)) == B_OK)
102 				{
103 					_beginWireTracking(fromEndPoint);
104 				}
105 			}
106 			trackWire(point);
107 			break;
108 		}
109 	}
110 }
111 
MessageDropped(BPoint point,BMessage * message)112 void DiagramView::MessageDropped(
113 	BPoint point,
114 	BMessage *message)
115 {
116 	D_METHOD(("DiagramView::MessageDropped()\n"));
117 	switch (message->what)
118 	{
119 		case M_WIRE_DRAGGED:
120 		{
121 			D_MESSAGE(("DiagramView::MessageDropped(M_WIRE_DROPPED)\n"));
122 			DiagramEndPoint *fromWhich = 0;
123 			if (message->FindPointer("from", reinterpret_cast<void **>(&fromWhich)) == B_OK)
124 			{
125 				connectionAborted(fromWhich);
126 			}
127 			break;
128 		}
129 	}
130 }
131 
132 // -------------------------------------------------------- //
133 // *** derived from BView
134 // -------------------------------------------------------- //
135 
136 // initial scrollbar update [e.moon 16nov99]
AttachedToWindow()137 void DiagramView::AttachedToWindow()
138 {
139 	D_METHOD(("DiagramView::AttachedToWindow()\n"));
140 	_updateScrollBars();
141 }
142 
Draw(BRect updateRect)143 void DiagramView::Draw(
144 	BRect updateRect)
145 {
146 	D_METHOD(("DiagramView::Draw()\n"));
147 	drawBackground(updateRect);
148 	DrawItems(updateRect, DiagramItem::M_WIRE);
149 	DrawItems(updateRect, DiagramItem::M_BOX);
150 }
151 
FrameResized(float width,float height)152 void DiagramView::FrameResized(
153 	float width,
154 	float height)
155 {
156 	D_METHOD(("DiagramView::FrameResized()\n"));
157 	_updateScrollBars();
158 }
159 
GetPreferredSize(float * width,float * height)160 void DiagramView::GetPreferredSize(
161 	float *width,
162 	float *height) {
163 	D_HOOK(("DiagramView::GetPreferredSize()\n"));
164 
165 	*width = m_dataRect.Width() + 10.0;
166 	*height = m_dataRect.Height() + 10.0;
167 }
168 
MessageReceived(BMessage * message)169 void DiagramView::MessageReceived(
170 	BMessage *message)
171 {
172 	D_METHOD(("DiagramView::MessageReceived()\n"));
173 	switch (message->what)
174 	{
175 		case M_SELECTION_CHANGED:
176 		{
177 			D_MESSAGE(("DiagramView::MessageReceived(M_SELECTION_CHANGED)\n"));
178 			DiagramItem *item;
179 			if (message->FindPointer("item", reinterpret_cast<void **>(&item)) == B_OK)
180 			{
181 				bool deselectOthers = true;
182 				message->FindBool("replace", &deselectOthers);
183 				if (item->isSelected() && !deselectOthers && MultipleSelection())
184 				{
185 					if (DeselectItem(item))
186 					{
187 						SelectionChanged();
188 					}
189 				}
190 				else if (SelectItem(item, deselectOthers))
191 				{
192 					SortItems(item->type(), &compareSelectionTime);
193 					SelectionChanged();
194 				}
195 			}
196 			break;
197 		}
198 		case M_WIRE_DROPPED:
199 		{
200 			D_MESSAGE(("DiagramView::MessageReceived(M_WIRE_DROPPED)\n"));
201 			DiagramEndPoint *fromWhich = 0;
202 			DiagramEndPoint *toWhich = 0;
203 			bool success = false;
204 			if (message->FindPointer("from", reinterpret_cast<void **>(&fromWhich)) == B_OK)
205 			{
206 				if ((message->FindPointer("to", reinterpret_cast<void **>(&toWhich)) == B_OK)
207 				 && (message->FindBool("success", &success) == B_OK))
208 				{
209 					if (success && fromWhich && toWhich)
210 					{
211 						_endWireTracking();
212 						DiagramWire *wire = createWire(fromWhich, toWhich);
213 						if (wire && AddItem(wire))
214 						{
215 							connectionEstablished(fromWhich, toWhich);
216 							break;
217 						}
218 					}
219 				}
220 			}
221 			connectionAborted(fromWhich);
222 			break;
223 		}
224 		default:
225 		{
226 			if (message->WasDropped())
227 			{
228 				BPoint point = ConvertFromScreen(message->DropPoint());
229 				DiagramItem *item = ItemUnder(point);
230 				if (item)
231 				{
232 					item->MessageDropped(point, message);
233 					return;
234 				}
235 				else
236 				{
237 					MessageDropped(point, message);
238 				}
239 			}
240 			else
241 			{
242 				BView::MessageReceived(message);
243 			}
244 		}
245 	}
246 }
247 
KeyDown(const char * bytes,int32 numBytes)248 void DiagramView::KeyDown(
249 	const char *bytes,
250 	int32 numBytes)
251 {
252 	D_METHOD(("DiagramView::KeyDown()\n"));
253 	switch (bytes[0])
254 	{
255 		case B_LEFT_ARROW:
256 		{
257 			float x;
258 			GetItemAlignment(&x, 0);
259 			BRegion updateRegion;
260 			DragSelectionBy(-x, 0.0, &updateRegion);
261 			for (int32 i = 0; i < updateRegion.CountRects(); i++)
262 				Invalidate(updateRegion.RectAt(i));
263 			updateDataRect();
264 			break;
265 		}
266 		case B_RIGHT_ARROW:
267 		{
268 			float x;
269 			GetItemAlignment(&x, 0);
270 			BRegion updateRegion;
271 			DragSelectionBy(x, 0.0, &updateRegion);
272 			for (int32 i = 0; i < updateRegion.CountRects(); i++)
273 				Invalidate(updateRegion.RectAt(i));
274 			updateDataRect();
275 			break;
276 		}
277 		case B_UP_ARROW:
278 		{
279 			float y;
280 			GetItemAlignment(0, &y);
281 			BRegion updateRegion;
282 			DragSelectionBy(0.0, -y, &updateRegion);
283 			for (int32 i = 0; i < updateRegion.CountRects(); i++)
284 				Invalidate(updateRegion.RectAt(i));
285 			updateDataRect();
286 			break;
287 		}
288 		case B_DOWN_ARROW:
289 		{
290 			float y;
291 			GetItemAlignment(0, &y);
292 			BRegion updateRegion;
293 			DragSelectionBy(0.0, y, &updateRegion);
294 			for (int32 i = 0; i < updateRegion.CountRects(); i++)
295 				Invalidate(updateRegion.RectAt(i));
296 			updateDataRect();
297 			break;
298 		}
299 		default:
300 		{
301 			BView::KeyDown(bytes, numBytes);
302 			break;
303 		}
304 	}
305 }
306 
MouseDown(BPoint point)307 void DiagramView::MouseDown(
308 	BPoint point)
309 {
310 	D_METHOD(("DiagramView::MouseDown()\n"));
311 
312 	SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
313 
314 	// update click count
315 	BMessage* message = Window()->CurrentMessage();
316 	int32 clicks = message->FindInt32("clicks");
317 	int32 buttons = message->FindInt32("buttons");
318 
319 	bool moved = (fabs(point.x - m_lastClickPoint.x) > 2.0 || fabs(point.y - m_lastClickPoint.y) > 2.0);
320 	if (!moved && (buttons == m_lastButton) && (clicks > 1))
321 	{
322 		m_clickCount++;
323 	}
324 	else
325 	{
326 		m_clickCount = 1;
327 	}
328 	m_lastButton = buttons;
329 	m_lastClickPoint = point;
330 	m_lastDragPoint = ConvertToScreen(point);
331 
332 	// [e.moon 16nov99] scroll on 3rd button
333 	m_pressedButton = buttons;
334 	if(m_pressedButton == B_TERTIARY_MOUSE_BUTTON) {
335 		return;
336 	}
337 
338 	// was an item clicked ?
339  	DiagramItem *item = ItemUnder(point);
340 	if (item)
341 	{
342 		item->MouseDown(point, m_lastButton, m_clickCount);
343 	}
344 	else // no, the background was clicked
345 	{
346 		if (!(modifiers() & B_SHIFT_KEY) && DeselectAll(DiagramItem::M_ANY))
347 			SelectionChanged();
348 		if (MultipleSelection() && (m_lastButton == B_PRIMARY_MOUSE_BUTTON) && !(modifiers() & B_CONTROL_KEY))
349 			_beginRectTracking(point);
350 		BackgroundMouseDown(point, m_lastButton, m_clickCount);
351 	}
352 }
353 
MouseMoved(BPoint point,uint32 transit,const BMessage * message)354 void DiagramView::MouseMoved(
355 	BPoint point,
356 	uint32 transit,
357 	const BMessage *message)
358 {
359 	D_METHOD(("DiagramView::MouseMoved()\n"));
360 
361 
362 	// [e.moon 16nov99] 3rd-button scrolling
363 	if(m_pressedButton == B_TERTIARY_MOUSE_BUTTON) {
364 
365 		// fetch/store screen point; calculate distance travelled
366 		ConvertToScreen(&point);
367 		float xDelta = m_lastDragPoint.x - point.x;
368 		float yDelta = m_lastDragPoint.y - point.y;
369 		m_lastDragPoint = point;
370 
371 		// constrain to scrollbar limits
372 		BScrollBar* hScroll = ScrollBar(B_HORIZONTAL);
373 		if(xDelta && hScroll) {
374 			float val = hScroll->Value();
375 			float min, max;
376 			hScroll->GetRange(&min, &max);
377 
378 			if(val + xDelta < min)
379 				xDelta = 0;
380 
381 			if(val + xDelta > max)
382 				xDelta = 0;
383 		}
384 
385 		BScrollBar* vScroll = ScrollBar(B_VERTICAL);
386 		if(yDelta && vScroll) {
387 			float val = vScroll->Value();
388 			float min, max;
389 			vScroll->GetRange(&min, &max);
390 
391 			if(val + yDelta < min)
392 				yDelta = 0;
393 
394 			if(val + yDelta > max)
395 				yDelta = 0;
396 		}
397 
398 		// scroll
399 		if(xDelta == 0.0 && yDelta == 0.0)
400 			return;
401 
402 		ScrollBy(xDelta, yDelta);
403 		 return;
404 	}
405 
406 	if (message)
407 	{
408 		switch (message->what)
409 		{
410 			case M_RECT_TRACKING:
411 			{
412 				BPoint origin;
413 				if (message->FindPoint("origin", &origin) == B_OK)
414 				{
415 					_trackRect(origin, point);
416 				}
417 				break;
418 			}
419 			case M_BOX_DRAGGED:
420 			{
421 				DiagramBox *box;
422 				BPoint offset;
423 				if ((message->FindPointer("item", reinterpret_cast<void **>(&box)) == B_OK)
424 				 && (message->FindPoint("offset", &offset) == B_OK))
425 				{
426 					if (box)
427 					{
428 						BRegion updateRegion;
429 						DragSelectionBy(point.x - box->Frame().left - offset.x,
430 										point.y - box->Frame().top - offset.y,
431 										&updateRegion);
432 						updateDataRect();
433 						for (int32 i = 0; i < updateRegion.CountRects(); i++)
434 						{
435 							Invalidate(updateRegion.RectAt(i));
436 						}
437 					}
438 				}
439 				break;
440 			}
441 			default: // unkwown message -> redirect to MessageDragged()
442 			{
443 				DiagramItem *last = _LastItemUnder();
444 				if (transit == B_EXITED_VIEW)
445 				{
446 					if (last)
447 					{
448 						last->MessageDragged(point, B_EXITED_VIEW, message);
449 						MessageDragged(point, B_EXITED_VIEW, message);
450 					}
451 				}
452 				else
453 				{
454 					DiagramItem *item = ItemUnder(point);
455 					if (item)
456 					{
457 						if (item != last)
458 						{
459 							if (last)
460 								last->MessageDragged(point, B_EXITED_VIEW, message);
461 							item->MessageDragged(point, B_ENTERED_VIEW, message);
462 						}
463 						else
464 						{
465 							item->MessageDragged(point, B_INSIDE_VIEW, message);
466 						}
467 					}
468 					else if (last)
469 					{
470 						last->MessageDragged(point, B_EXITED_VIEW, message);
471 						MessageDragged(point, B_ENTERED_VIEW, message);
472 					}
473 					else
474 					{
475 						MessageDragged(point, transit, message);
476 					}
477 				}
478 				break;
479 			}
480 		}
481 	}
482 	else // no message at all -> redirect to MouseOver()
483 	{
484 		DiagramItem *last = _LastItemUnder();
485 		if ((transit == B_EXITED_VIEW) || (transit == B_OUTSIDE_VIEW))
486 		{
487 			if (last)
488 			{
489 				last->MouseOver(point, B_EXITED_VIEW);
490 				_ResetItemUnder();
491 				MouseOver(point, B_EXITED_VIEW);
492 			}
493 		}
494 		else
495 		{
496 			DiagramItem *item = ItemUnder(point);
497 			if (item)
498 			{
499 				if (item != last)
500 				{
501 					if (last)
502 						last->MouseOver(point, B_EXITED_VIEW);
503 					item->MouseOver(point, B_ENTERED_VIEW);
504 				}
505 				else
506 				{
507 					item->MouseOver(point, B_INSIDE_VIEW);
508 				}
509 			}
510 			else if (last)
511 			{
512 				last->MouseOver(point, B_EXITED_VIEW);
513 				MouseOver(point, B_ENTERED_VIEW);
514 			}
515 		}
516 	}
517 }
518 
MouseUp(BPoint point)519 void DiagramView::MouseUp(
520 	BPoint point)
521 {
522 	D_METHOD(("DiagramView::MouseUp()\n"));
523 	if (MultipleSelection())
524 		EndRectTracking();
525 	_endWireTracking();
526 
527 	// [e.moon 16nov99] mark no button as down
528 	m_pressedButton = 0;
529 }
530 
531 // -------------------------------------------------------- //
532 // *** derived from DiagramItemGroup (public)
533 // -------------------------------------------------------- //
534 
AddItem(DiagramItem * item)535 bool DiagramView::AddItem(
536 	DiagramItem *item)
537 {
538 	D_METHOD(("DiagramBox::AddItem()\n"));
539 	if (item)
540 	{
541 		if (DiagramItemGroup::AddItem(item))
542 		{
543 			item->_SetOwner(this);
544 			item->attachedToDiagram();
545 			if (item->type() == DiagramItem::M_BOX)
546 			{
547 				updateDataRect();
548 			}
549 			return true;
550 		}
551 	}
552 	return false;
553 }
554 
RemoveItem(DiagramItem * item)555 bool DiagramView::RemoveItem(
556 	DiagramItem *item)
557 {
558 	D_METHOD(("DiagramBox::RemoveItem()\n"));
559 	if (item)
560 	{
561 		item->detachedFromDiagram();
562 		if (DiagramItemGroup::RemoveItem(item))
563 		{
564 			item->_SetOwner(0);
565 			if (item->type() == DiagramItem::M_BOX)
566 			{
567 				updateDataRect();
568 			}
569 			return true;
570 		}
571 	}
572 	return false;
573 }
574 
575 // -------------------------------------------------------- //
576 // *** operations (public)
577 // -------------------------------------------------------- //
578 
trackWire(BPoint point)579 void DiagramView::trackWire(
580 	BPoint point)
581 {
582 	D_MOUSE(("DiagramView::trackWire()\n"));
583 	if (m_draggedWire)
584 	{
585 		BRegion region;
586 		region.Include(m_draggedWire->Frame());
587 		m_draggedWire->m_dragEndPoint = point;
588 		m_draggedWire->endPointMoved();
589 		region.Include(m_draggedWire->Frame());
590 		region.Exclude(&m_boxRegion);
591 		for (int32 i = 0; i < region.CountRects(); i++)
592 		{
593 			Invalidate(region.RectAt(i));
594 		}
595 	}
596 }
597 
598 // -------------------------------------------------------- //
599 // *** internal operations (protected)
600 // -------------------------------------------------------- //
601 
drawBackground(BRect updateRect)602 void DiagramView::drawBackground(
603 	BRect updateRect)
604 {
605 	D_METHOD(("DiagramView::drawBackground()\n"));
606 	if (m_useBackgroundBitmap)
607 	{
608 		BRegion region;
609 		region.Include(updateRect);
610 		region.Exclude(&m_boxRegion);
611 		BRect bounds = Bounds();
612 		PushState();
613 		{
614 			ConstrainClippingRegion(&region);
615 			for (float y = 0; y < bounds.bottom; y += m_backgroundBitmap->Bounds().Height())
616 			{
617 				for (float x = 0; x < bounds.right; x += m_backgroundBitmap->Bounds().Width())
618 				{
619 					DrawBitmapAsync(m_backgroundBitmap, BPoint(x, y));
620 				}
621 			}
622 		}
623 		PopState();
624 	}
625 	else
626 	{
627 		BRegion region;
628 		region.Include(updateRect);
629 		region.Exclude(&m_boxRegion);
630 		PushState();
631 		{
632 			SetLowColor(m_backgroundColor);
633 			FillRegion(&region, B_SOLID_LOW);
634 		}
635 		PopState();
636 	}
637 }
638 
setBackgroundColor(rgb_color color)639 void DiagramView::setBackgroundColor(
640 	rgb_color color)
641 {
642 	D_METHOD(("DiagramView::setBackgroundColor()\n"));
643 	m_backgroundColor = color;
644 	m_useBackgroundBitmap = false;
645 }
646 
647 
648 void
setBackgroundBitmap(BBitmap * bitmap)649 DiagramView::setBackgroundBitmap(BBitmap* bitmap)
650 {
651 	D_METHOD(("DiagramView::setBackgroundBitmap()\n"));
652 	if (m_backgroundBitmap)
653 		delete m_backgroundBitmap;
654 
655 	m_backgroundBitmap = new BBitmap(bitmap);
656 	m_useBackgroundBitmap = true;
657 }
658 
659 
660 void
updateDataRect()661 DiagramView::updateDataRect()
662 {
663 	D_METHOD(("DiagramView::updateDataRect()\n"));
664 	// calculate the area in which boxes display
665 	m_boxRegion.MakeEmpty();
666 	for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++) {
667 		m_boxRegion.Include(ItemAt(i, DiagramItem::M_BOX)->Frame());
668 	}
669 	// adapt the data rect to the new region of boxes
670 	BRect boxRect = m_boxRegion.Frame();
671 	m_dataRect.right = boxRect.right;
672 	m_dataRect.bottom = boxRect.bottom;
673 	// update the scroll bars
674 	_updateScrollBars();
675 }
676 
677 
678 //	#pragma mark - internal operations (private)
679 
680 
681 void
_beginWireTracking(DiagramEndPoint * startPoint)682 DiagramView::_beginWireTracking(DiagramEndPoint *startPoint)
683 {
684 	D_METHOD(("DiagramView::beginWireTracking()\n"));
685 	m_draggedWire = createWire(startPoint);
686 	AddItem(m_draggedWire);
687 	SelectItem(m_draggedWire, true);
688 	Invalidate(startPoint->Frame());
689 }
690 
_endWireTracking()691 void DiagramView::_endWireTracking()
692 {
693 	D_METHOD(("DiagramView::endWireTracking()\n"));
694 	if (m_draggedWire)
695 	{
696 		RemoveItem(m_draggedWire);
697 		Invalidate(m_draggedWire->Frame());
698 		DiagramEndPoint *endPoint = m_draggedWire->startPoint();
699 		if (!endPoint)
700 		{
701 			endPoint = m_draggedWire->endPoint();
702 		}
703 		if (endPoint)
704 		{
705 			Invalidate(endPoint->Frame());
706 		}
707 		delete m_draggedWire;
708 		m_draggedWire = 0;
709 	}
710 }
711 
_beginRectTracking(BPoint origin)712 void DiagramView::_beginRectTracking(
713 	BPoint origin)
714 {
715 	D_METHOD(("DiagramView::beginRectTracking()\n"));
716 	BMessage message(M_RECT_TRACKING);
717 	message.AddPoint("origin", origin);
718 	DragMessage(&message, BRect(0.0, 0.0, -1.0, -1.0));
719 	BView::BeginRectTracking(BRect(origin, origin), B_TRACK_RECT_CORNER);
720 }
721 
722 
723 void
_trackRect(BPoint origin,BPoint current)724 DiagramView::_trackRect(BPoint origin, BPoint current)
725 {
726 	D_METHOD(("DiagramView::trackRect()\n"));
727 	bool changed = false;
728 	BRect rect;
729 	rect.left = origin.x < current.x ? origin.x : current.x;
730 	rect.top = origin.y < current.y ? origin.y : current.y;
731 	rect.right = origin.x < current.x ? current.x : origin.x;
732 	rect.bottom = origin.y < current.y ? current.y : origin.y;
733 	for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++) {
734 		DiagramBox *box = dynamic_cast<DiagramBox *>(ItemAt(i, DiagramItem::M_BOX));
735 		if (box) {
736 			if (rect.Intersects(box->Frame()))
737 				changed  |= SelectItem(box, false);
738 			else
739 				changed |= DeselectItem(box);
740 		}
741 	}
742 
743 	if (changed) {
744 		SortItems(DiagramItem::M_BOX, &compareSelectionTime);
745 		SelectionChanged();
746 	}
747 }
748 
749 
750 void
_updateScrollBars()751 DiagramView::_updateScrollBars()
752 {
753 	D_METHOD(("DiagramView::_updateScrollBars()\n"));
754 	// fetch the vertical ScrollBar
755 	BScrollBar *scrollBar = ScrollBar(B_VERTICAL);
756 	if (scrollBar)
757 	{
758 		 // Disable the ScrollBar if the view is large enough to display
759 		 // the entire data-rect
760 		if (Bounds().Height() > m_dataRect.Height())
761 		{
762 			scrollBar->SetRange(0.0, 0.0);
763 			scrollBar->SetProportion(1.0);
764 		}
765 		else
766 		{
767 			scrollBar->SetRange(m_dataRect.top, m_dataRect.bottom - Bounds().Height());
768 			scrollBar->SetProportion(Bounds().Height() / m_dataRect.Height());
769 		}
770 	}
771 	scrollBar = ScrollBar(B_HORIZONTAL);
772 	if (scrollBar)
773 	{
774 		 // Disable the ScrollBar if the view is large enough to display
775 		 // the entire data-rect
776 		if (Bounds().Width() > m_dataRect.Width())
777 		{
778 			scrollBar->SetRange(0.0, 0.0);
779 			scrollBar->SetProportion(1.0);
780 		}
781 		else
782 		{
783 			scrollBar->SetRange(m_dataRect.left, m_dataRect.right - Bounds().Width());
784 			scrollBar->SetProportion(Bounds().Width() / m_dataRect.Width());
785 		}
786 	}
787 }
788 
789 // END -- DiagramView.cpp --
790