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 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 78 DiagramView::~DiagramView() 79 { 80 D_METHOD(("DiagramView::~DiagramView()\n")); 81 } 82 83 // -------------------------------------------------------- // 84 // *** hook functions 85 // -------------------------------------------------------- // 86 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 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] 137 void DiagramView::AttachedToWindow() 138 { 139 D_METHOD(("DiagramView::AttachedToWindow()\n")); 140 _updateScrollBars(); 141 } 142 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 152 void DiagramView::FrameResized( 153 float width, 154 float height) 155 { 156 D_METHOD(("DiagramView::FrameResized()\n")); 157 _updateScrollBars(); 158 } 159 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 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 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 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 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 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 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 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 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 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(®ion); 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(®ion, B_SOLID_LOW); 634 } 635 PopState(); 636 } 637 } 638 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 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 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 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 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 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 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 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