1139823Simp/* 21541Srgrimes * Copyright 2006-2007, 2011, Stephan A��mus <superstippi@gmx.de> 31541Srgrimes * All rights reserved. Distributed under the terms of the MIT License. 41541Srgrimes */ 51541Srgrimes 61541Srgrimes 71541Srgrimes#include "CanvasView.h" 81541Srgrimes 91541Srgrimes#include <Bitmap.h> 101541Srgrimes#include <Cursor.h> 111541Srgrimes#include <Message.h> 121541Srgrimes#include <Region.h> 131541Srgrimes#include <Window.h> 141541Srgrimes 151541Srgrimes#include <stdio.h> 161541Srgrimes 171541Srgrimes#include "cursors.h" 181541Srgrimes#include "ui_defines.h" 191541Srgrimes 201541Srgrimes#include "CommandStack.h" 211541Srgrimes#include "IconRenderer.h" 221541Srgrimes 231541Srgrimes 241541Srgrimesusing std::nothrow; 251541Srgrimes 261541Srgrimes 271541SrgrimesCanvasView::CanvasView(BRect frame) 281541Srgrimes : 291541Srgrimes StateView(frame, "canvas view", B_FOLLOW_ALL, 301541Srgrimes B_WILL_DRAW | B_FRAME_EVENTS), 311541Srgrimes fBitmap(new BBitmap(BRect(0, 0, 63, 63), 0, B_RGB32)), 3236503Speter fBackground(new BBitmap(BRect(0, 0, 63, 63), 0, B_RGB32)), 331541Srgrimes fIcon(NULL), 341541Srgrimes fRenderer(new IconRenderer(fBitmap)), 3583651Speter fDirtyIconArea(fBitmap->Bounds()), 3683651Speter 3783651Speter fCanvasOrigin(0.0, 0.0), 381541Srgrimes fZoomLevel(8.0), 391541Srgrimes 401541Srgrimes fSpaceHeldDown(false), 411541Srgrimes fInScrollTo(false), 421541Srgrimes fScrollTracking(false), 4383651Speter fScrollTrackingStart(0.0, 0.0), 44190380Srwatson 45190380Srwatson fMouseFilterMode(SNAPPING_OFF) 461541Srgrimes{ 4748274Speter _MakeBackground(); 4848274Speter fRenderer->SetBackground(fBackground); 4960041Sphk} 5031886Sbde 511541Srgrimes 521541SrgrimesCanvasView::~CanvasView() 531541Srgrimes{ 541541Srgrimes SetIcon(NULL); 551541Srgrimes delete fRenderer; 561541Srgrimes delete fBitmap; 571541Srgrimes delete fBackground; 589336Sdfr} 592997Swollman 602997Swollman 6183651Speter// #pragma mark - 62212506Skib 631541Srgrimes 643305Sphkvoid 6512662SdgCanvasView::AttachedToWindow() 6612662Sdg{ 6792783Sjeff StateView::AttachedToWindow(); 683305Sphk 699336Sdfr SetViewColor(B_TRANSPARENT_COLOR); 7083651Speter SetLowColor(kStripesHigh); 7183651Speter SetHighColor(kStripesLow); 72221543Srmacklem 731541Srgrimes // init data rect for scrolling and center bitmap in the view 7483651Speter BRect dataRect = _LayoutCanvas(); 7583651Speter SetDataRect(dataRect); 761541Srgrimes BRect bounds(Bounds()); 771541Srgrimes BPoint dataRectCenter((dataRect.left + dataRect.right) / 2, 781541Srgrimes (dataRect.top + dataRect.bottom) / 2); 791541Srgrimes BPoint boundsCenter((bounds.left + bounds.right) / 2, 80158739Smohans (bounds.top + bounds.bottom) / 2); 81158739Smohans BPoint offset = ScrollOffset(); 82158739Smohans offset.x = roundf(offset.x + dataRectCenter.x - boundsCenter.x); 83158739Smohans offset.y = roundf(offset.y + dataRectCenter.y - boundsCenter.y); 84158739Smohans SetScrollOffset(offset); 85190380Srwatson} 86190380Srwatson 87190380Srwatson 88190380Srwatsonvoid 89190380SrwatsonCanvasView::FrameResized(float width, float height) 90190380Srwatson{ 91190380Srwatson // keep canvas centered 92190380Srwatson BPoint oldCanvasOrigin = fCanvasOrigin; 93190380Srwatson SetDataRect(_LayoutCanvas()); 94190380Srwatson if (oldCanvasOrigin != fCanvasOrigin) 95190380Srwatson Invalidate(); 96190380Srwatson} 97190380Srwatson 98190380Srwatson 99190380Srwatsonvoid 100190380SrwatsonCanvasView::Draw(BRect updateRect) 101190380Srwatson{ 102190380Srwatson _DrawInto(this, updateRect); 103158739Smohans} 1041541Srgrimes 1051541Srgrimes 1061541Srgrimes// #pragma mark - 10783651Speter 10883651Speter 1091541Srgrimesvoid 1101541SrgrimesCanvasView::MouseDown(BPoint where) 111176224Sjhb{ 11212911Sphk if (!IsFocus()) 11383651Speter MakeFocus(true); 11412911Sphk 11512911Sphk int32 buttons; 11683651Speter if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) < B_OK) 11783651Speter buttons = 0; 1189336Sdfr 11983651Speter // handle clicks of the third mouse button ourselves (panning), 120176224Sjhb // otherwise have StateView handle it (normal clicks) 121212506Skib if (fSpaceHeldDown || (buttons & B_TERTIARY_MOUSE_BUTTON) != 0) { 1229759Sbde // switch into scrolling mode and update cursor 1239336Sdfr fScrollTracking = true; 1249336Sdfr where.x = roundf(where.x); 1259336Sdfr where.y = roundf(where.y); 1269336Sdfr fScrollOffsetStart = ScrollOffset(); 1279336Sdfr fScrollTrackingStart = where - fScrollOffsetStart; 1289336Sdfr _UpdateToolCursor(); 1299336Sdfr SetMouseEventMask(B_POINTER_EVENTS, 1309336Sdfr B_LOCK_WINDOW_FOCUS | B_SUSPEND_VIEW_FOCUS); 1319336Sdfr } else { 1329336Sdfr StateView::MouseDown(where); 1339336Sdfr } 1349336Sdfr} 1359336Sdfr 1369336Sdfr 1379336Sdfrvoid 1389336SdfrCanvasView::MouseUp(BPoint where) 1399336Sdfr{ 1409336Sdfr if (fScrollTracking) { 1419336Sdfr // stop scroll tracking and update cursor 1429336Sdfr fScrollTracking = false; 1439336Sdfr _UpdateToolCursor(); 1449336Sdfr // update StateView mouse position 1459336Sdfr uint32 transit = Bounds().Contains(where) ? 1469336Sdfr B_INSIDE_VIEW : B_OUTSIDE_VIEW; 1479336Sdfr StateView::MouseMoved(where, transit, NULL); 1489336Sdfr } else { 1499336Sdfr StateView::MouseUp(where); 1509336Sdfr } 1519336Sdfr} 15260938Sjake 1533664Sphk 154176224Sjhbvoid 155176224SjhbCanvasView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) 156176224Sjhb{ 157176224Sjhb if (fScrollTracking) { 158176224Sjhb uint32 buttons; 159176224Sjhb GetMouse(&where, &buttons, false); 160176224Sjhb if (!buttons) { 161176224Sjhb MouseUp(where); 162176224Sjhb return; 163176224Sjhb } 164176224Sjhb where.x = roundf(where.x); 165176224Sjhb where.y = roundf(where.y); 166176224Sjhb where -= ScrollOffset(); 167176224Sjhb BPoint offset = where - fScrollTrackingStart; 168176224Sjhb SetScrollOffset(fScrollOffsetStart - offset); 169176224Sjhb } else { 170176224Sjhb // normal mouse movement handled by StateView 171176224Sjhb if (!fSpaceHeldDown) 172176224Sjhb StateView::MouseMoved(where, transit, dragMessage); 173176224Sjhb } 1741541Srgrimes} 1751541Srgrimes 1761541Srgrimes 1771541Srgrimesvoid 1781541SrgrimesCanvasView::FilterMouse(BPoint* where) const 1791541Srgrimes{ 18083651Speter switch (fMouseFilterMode) { 1811541Srgrimes 18283651Speter case SNAPPING_64: 1831541Srgrimes ConvertToCanvas(where); 184177599Sru where->x = floorf(where->x + 0.5); 1851541Srgrimes where->y = floorf(where->y + 0.5); 186177599Sru ConvertFromCanvas(where); 1871541Srgrimes break; 1881541Srgrimes 1891541Srgrimes case SNAPPING_32: 1901541Srgrimes ConvertToCanvas(where); 1911541Srgrimes where->x /= 2.0; 19217186Sdfr where->y /= 2.0; 19317186Sdfr where->x = floorf(where->x + 0.5); 1941541Srgrimes where->y = floorf(where->y + 0.5); 1951549Srgrimes where->x *= 2.0; 19683651Speter where->y *= 2.0; 1971541Srgrimes ConvertFromCanvas(where); 19883651Speter break; 19983651Speter 20083651Speter case SNAPPING_16: 2011541Srgrimes ConvertToCanvas(where); 2021541Srgrimes where->x /= 4.0; 2031541Srgrimes where->y /= 4.0; 204209120Skib where->x = floorf(where->x + 0.5); 20517186Sdfr where->y = floorf(where->y + 0.5); 2061541Srgrimes where->x *= 4.0; 2071541Srgrimes where->y *= 4.0; 2081541Srgrimes ConvertFromCanvas(where); 2091541Srgrimes break; 2101541Srgrimes 2111541Srgrimes case SNAPPING_OFF: 2121541Srgrimes default: 2131541Srgrimes break; 2141541Srgrimes } 2151541Srgrimes} 2161541Srgrimes 2171541Srgrimes 2181541Srgrimesbool 2191541SrgrimesCanvasView::MouseWheelChanged(BPoint where, float x, float y) 2201541Srgrimes{ 221177599Sru if (!Bounds().Contains(where)) 2221541Srgrimes return false; 223177599Sru 2241541Srgrimes if (y > 0.0) { 2251541Srgrimes _SetZoom(_NextZoomOutLevel(fZoomLevel), true); 2261541Srgrimes return true; 2271541Srgrimes } else if (y < 0.0) { 2281541Srgrimes _SetZoom(_NextZoomInLevel(fZoomLevel), true); 2291541Srgrimes return true; 2301541Srgrimes } 2311541Srgrimes return false; 2321541Srgrimes} 2331541Srgrimes 2341541Srgrimes 2351541Srgrimes// #pragma mark - 2361541Srgrimes 2371541Srgrimes 2381541Srgrimesvoid 2391541SrgrimesCanvasView::SetScrollOffset(BPoint newOffset) 2401541Srgrimes{ 2411541Srgrimes if (fInScrollTo) 2421541Srgrimes return; 2431541Srgrimes 2441541Srgrimes fInScrollTo = true; 2451541Srgrimes 2461541Srgrimes newOffset = ValidScrollOffsetFor(newOffset); 247104908Smike if (!fScrollTracking) { 248104908Smike BPoint mouseOffset = newOffset - ScrollOffset(); 24917186Sdfr MouseMoved(fMouseInfo.position + mouseOffset, fMouseInfo.transit, 2501541Srgrimes NULL); 2511541Srgrimes } 2521541Srgrimes 2531541Srgrimes Scrollable::SetScrollOffset(newOffset); 254177599Sru 2551541Srgrimes fInScrollTo = false; 2561541Srgrimes} 2571541Srgrimes 2581541Srgrimes 2591541Srgrimesvoid 2601541SrgrimesCanvasView::ScrollOffsetChanged(BPoint oldOffset, BPoint newOffset) 2611541Srgrimes{ 2621541Srgrimes BPoint offset = newOffset - oldOffset; 2631541Srgrimes 2641541Srgrimes if (offset == B_ORIGIN) { 2651541Srgrimes // prevent circular code (MouseMoved might call ScrollBy...) 2661541Srgrimes return; 2671541Srgrimes } 2681541Srgrimes 2691541Srgrimes ScrollBy(offset.x, offset.y); 2701541Srgrimes} 2711541Srgrimes 2721549Srgrimes 27383651Spetervoid 2741541SrgrimesCanvasView::VisibleSizeChanged(float oldWidth, float oldHeight, float newWidth, 27583651Speter float newHeight) 2761541Srgrimes{ 27736541Speter BRect dataRect(_LayoutCanvas()); 2781541Srgrimes SetDataRect(dataRect); 2791541Srgrimes} 2801541Srgrimes 2811541Srgrimes 2821541Srgrimes// #pragma mark - 2831541Srgrimes 28436541Speter 2851541Srgrimesvoid 2861541SrgrimesCanvasView::AreaInvalidated(const BRect& area) 2871541Srgrimes{ 2881541Srgrimes if (fDirtyIconArea.Contains(area)) 2891541Srgrimes return; 2901541Srgrimes 2911541Srgrimes fDirtyIconArea = fDirtyIconArea | area; 2921541Srgrimes 2931541Srgrimes BRect viewArea(area); 2941541Srgrimes ConvertFromCanvas(&viewArea); 2951541Srgrimes Invalidate(viewArea); 2961541Srgrimes} 2971541Srgrimes 2981541Srgrimes 299177599Sru// #pragma mark - 3001541Srgrimes 301177599Sru 3021541Srgrimesvoid 3031541SrgrimesCanvasView::SetIcon(Icon* icon) 3041541Srgrimes{ 30536541Speter if (fIcon == icon) 3061541Srgrimes return; 3071541Srgrimes 3081541Srgrimes if (fIcon) 3091541Srgrimes fIcon->RemoveListener(this); 3101541Srgrimes 3111541Srgrimes fIcon = icon; 3121541Srgrimes fRenderer->SetIcon(icon); 3131541Srgrimes 3141541Srgrimes if (fIcon) 3151541Srgrimes fIcon->AddListener(this); 3161541Srgrimes} 3171541Srgrimes 3181541Srgrimes 3191541Srgrimesvoid 3201541SrgrimesCanvasView::SetMouseFilterMode(uint32 mode) 3211541Srgrimes{ 3221541Srgrimes if (fMouseFilterMode == mode) 3231541Srgrimes return; 3241541Srgrimes 3251541Srgrimes fMouseFilterMode = mode; 3261541Srgrimes Invalidate(_CanvasRect()); 3271541Srgrimes} 3281541Srgrimes 3291541Srgrimes 3301541Srgrimesvoid 3311541SrgrimesCanvasView::ConvertFromCanvas(BPoint* point) const 3321541Srgrimes{ 3331541Srgrimes point->x = point->x * fZoomLevel + fCanvasOrigin.x; 3341549Srgrimes point->y = point->y * fZoomLevel + fCanvasOrigin.y; 33583651Speter} 3361541Srgrimes 33783651Speter 3381541Srgrimesvoid 33992783SjeffCanvasView::ConvertToCanvas(BPoint* point) const 34092783Sjeff{ 3411541Srgrimes point->x = (point->x - fCanvasOrigin.x) / fZoomLevel; 3421541Srgrimes point->y = (point->y - fCanvasOrigin.y) / fZoomLevel; 3433664Sphk} 3449336Sdfr 3459336Sdfr 3469336Sdfrvoid 3471541SrgrimesCanvasView::ConvertFromCanvas(BRect* r) const 34819449Sdfr{ 349203072Srmacklem r->left = r->left * fZoomLevel + fCanvasOrigin.x; 35099797Sdillon r->top = r->top * fZoomLevel + fCanvasOrigin.y; 35119449Sdfr r->right++; 3521541Srgrimes r->bottom++; 3531541Srgrimes r->right = r->right * fZoomLevel + fCanvasOrigin.x; 3541541Srgrimes r->bottom = r->bottom * fZoomLevel + fCanvasOrigin.y; 3551541Srgrimes r->right--; 3561541Srgrimes r->bottom--; 357158739Smohans} 358172600Smohans 359212506Skib 36016365Sphkvoid 36142957SdillonCanvasView::ConvertToCanvas(BRect* r) const 36242957Sdillon{ 3631549Srgrimes r->left = (r->left - fCanvasOrigin.x) / fZoomLevel; 3641541Srgrimes r->top = (r->top - fCanvasOrigin.y) / fZoomLevel; 3651541Srgrimes r->right = (r->right - fCanvasOrigin.x) / fZoomLevel; 36638894Sbde r->bottom = (r->bottom - fCanvasOrigin.y) / fZoomLevel; 36783651Speter} 36838894Sbde 369128111Speadar 37038894Sbde// #pragma mark - 371128111Speadar 372128111Speadar 373128111Speadarbool 374212506SkibCanvasView::_HandleKeyDown(uint32 key, uint32 modifiers) 375128111Speadar{ 376158739Smohans switch (key) { 377128111Speadar case 'z': 378212506Skib case 'y': 379212506Skib if (modifiers & B_SHIFT_KEY) 380212506Skib CommandStack()->Redo(); 381128111Speadar else 382203072Srmacklem CommandStack()->Undo(); 383128111Speadar break; 384128111Speadar 385128111Speadar case '+': 386158739Smohans _SetZoom(_NextZoomInLevel(fZoomLevel)); 387158739Smohans break; 388128111Speadar case '-': 389128111Speadar _SetZoom(_NextZoomOutLevel(fZoomLevel)); 39038894Sbde break; 39138894Sbde 39238894Sbde case B_SPACE: 393158739Smohans fSpaceHeldDown = true; 394158739Smohans _UpdateToolCursor(); 395158739Smohans break; 396158739Smohans 397158739Smohans default: 398158739Smohans return StateView::_HandleKeyDown(key, modifiers); 399158739Smohans } 400158739Smohans 401158739Smohans return true; 402158739Smohans} 403158739Smohans 404158739Smohans 405158739Smohansbool 406158739SmohansCanvasView::_HandleKeyUp(uint32 key, uint32 modifiers) 407158739Smohans{ 408158739Smohans switch (key) { 409158739Smohans case B_SPACE: 410158739Smohans fSpaceHeldDown = false; 411158739Smohans _UpdateToolCursor(); 412158739Smohans break; 413176134Sattilio 414158739Smohans default: 415158739Smohans return StateView::_HandleKeyUp(key, modifiers); 416196205Skib } 417196205Skib 418196205Skib return true; 419196205Skib} 420196205Skib 421196205Skib 422196205SkibBRect 423196205SkibCanvasView::_CanvasRect() const 424158739Smohans{ 425196205Skib BRect r; 426158739Smohans if (fBitmap == NULL) 427158739Smohans return r; 428158739Smohans r = fBitmap->Bounds(); 429176134Sattilio ConvertFromCanvas(&r); 430158739Smohans return r; 431158739Smohans} 432196205Skib 433196205Skib 434196205Skibvoid 435158739SmohansCanvasView::_DrawInto(BView* view, BRect updateRect) 436158739Smohans{ 437158739Smohans if (fDirtyIconArea.IsValid()) { 438158739Smohans fRenderer->Render(fDirtyIconArea, true); 439158739Smohans fDirtyIconArea.Set(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN); 440158739Smohans } 441158739Smohans 442158739Smohans // icon 443158739Smohans BRect canvas(_CanvasRect()); 444158739Smohans view->DrawBitmap(fBitmap, fBitmap->Bounds(), canvas); 445220595Sru 446158739Smohans // grid 447158739Smohans int32 gridLines = 0; 448158739Smohans int32 scale = 1; 449158739Smohans switch (fMouseFilterMode) { 4501541Srgrimes case SNAPPING_64: 4511541Srgrimes gridLines = 63; 4521541Srgrimes break; 4531541Srgrimes case SNAPPING_32: 4541541Srgrimes gridLines = 31; 4551541Srgrimes scale = 2; 4561541Srgrimes break; 4571541Srgrimes case SNAPPING_16: 4581541Srgrimes gridLines = 15; 4591541Srgrimes scale = 4; 4601541Srgrimes break; 4611541Srgrimes case SNAPPING_OFF: 4621541Srgrimes default: 4631541Srgrimes break; 4641549Srgrimes } 46583651Speter view->SetDrawingMode(B_OP_BLEND); 466158739Smohans for (int32 i = 1; i <= gridLines; i++) { 4671541Srgrimes BPoint cross(i * scale, i * scale); 46883651Speter ConvertFromCanvas(&cross); 46983651Speter view->StrokeLine(BPoint(canvas.left, cross.y), 47083651Speter BPoint(canvas.right, cross.y)); 471190380Srwatson view->StrokeLine(BPoint(cross.x, canvas.top), 47283651Speter BPoint(cross.x, canvas.bottom)); 4739336Sdfr } 47484057Speter view->SetDrawingMode(B_OP_COPY); 4751541Srgrimes 4761541Srgrimes // outside icon 4771541Srgrimes BRegion outside(Bounds() & updateRect); 478171190Sjhb outside.Exclude(canvas); 4799336Sdfr view->FillRegion(&outside, kStripes); 480190380Srwatson 4811541Srgrimes StateView::Draw(view, updateRect); 4821541Srgrimes} 4839336Sdfr 484177599Sru 485190380Srwatsonvoid 486190380SrwatsonCanvasView::_MakeBackground() 487190380Srwatson{ 488190380Srwatson uint8* row = (uint8*)fBackground->Bits(); 4899336Sdfr uint32 bpr = fBackground->BytesPerRow(); 4909336Sdfr uint32 width = fBackground->Bounds().IntegerWidth() + 1; 4919336Sdfr uint32 height = fBackground->Bounds().IntegerHeight() + 1; 4929336Sdfr 493130640Sphk const GammaTable& lut = fRenderer->GammaTable(); 49416634Sbde uint8 redLow = lut.dir(kAlphaLow.red); 4959336Sdfr uint8 greenLow = lut.dir(kAlphaLow.blue); 4961541Srgrimes uint8 blueLow = lut.dir(kAlphaLow.green); 4979336Sdfr uint8 redHigh = lut.dir(kAlphaHigh.red); 4989336Sdfr uint8 greenHigh = lut.dir(kAlphaHigh.blue); 4999336Sdfr uint8 blueHigh = lut.dir(kAlphaHigh.green); 5009336Sdfr 5019336Sdfr for (uint32 y = 0; y < height; y++) { 5029336Sdfr uint8* p = row; 5039336Sdfr for (uint32 x = 0; x < width; x++) { 5049336Sdfr p[3] = 255; 5059336Sdfr if (x % 8 >= 4) { 5069336Sdfr if (y % 8 >= 4) { 5079336Sdfr p[0] = blueLow; 5089336Sdfr p[1] = greenLow; 5099336Sdfr p[2] = redLow; 5109336Sdfr } else { 5119336Sdfr p[0] = blueHigh; 5129336Sdfr p[1] = greenHigh; 5139336Sdfr p[2] = redHigh; 5149336Sdfr } 5159336Sdfr } else { 5169336Sdfr if (y % 8 >= 4) { 5179336Sdfr p[0] = blueHigh; 5189336Sdfr p[1] = greenHigh; 5199336Sdfr p[2] = redHigh; 52036541Speter } else { 5219336Sdfr p[0] = blueLow; 5229336Sdfr p[1] = greenLow; 5239336Sdfr p[2] = redLow; 5249336Sdfr } 5259336Sdfr } 5269336Sdfr p += 4; 5279336Sdfr } 5281541Srgrimes row += bpr; 5299336Sdfr } 5301541Srgrimes} 5311541Srgrimes 5328876Srgrimes 5331541Srgrimesvoid 5341541SrgrimesCanvasView::_UpdateToolCursor() 5351541Srgrimes{ 5361541Srgrimes if (fIcon) { 5371541Srgrimes if (fScrollTracking || fSpaceHeldDown) { 538158739Smohans // indicate scrolling mode 53910219Sdfr const uchar* cursorData = fScrollTracking ? kGrabCursor : kHandCursor; 5409336Sdfr BCursor cursor(cursorData); 541126851Sphk SetViewCursor(&cursor, true); 542138290Sphk } else { 543138473Sps // pass on to current state of StateView 5441541Srgrimes UpdateStateCursor(); 5451541Srgrimes } 5461541Srgrimes } else { 5471541Srgrimes BCursor cursor(kStopCursor); 54847028Sphk SetViewCursor(&cursor, true); 549171190Sjhb } 5501541Srgrimes} 5511541Srgrimes 5529336Sdfr 5539336Sdfr// #pragma mark - 5549336Sdfr 5559336Sdfr 55647751Speterdouble 5579336SdfrCanvasView::_NextZoomInLevel(double zoom) const 55847751Speter{ 55936541Speter if (zoom < 1) 56036541Speter return 1; 5619336Sdfr if (zoom < 1.5) 5629336Sdfr return 1.5; 5639336Sdfr if (zoom < 2) 5649336Sdfr return 2; 5651541Srgrimes if (zoom < 3) 5669336Sdfr return 3; 5679336Sdfr if (zoom < 4) 5689336Sdfr return 4; 56936541Speter if (zoom < 6) 57036541Speter return 6; 57147751Speter if (zoom < 8) 57236541Speter return 8; 57336541Speter if (zoom < 16) 5749336Sdfr return 16; 5751541Srgrimes if (zoom < 32) 57636541Speter return 32; 57736541Speter return 64; 57818397Snate} 57983651Speter 5801541Srgrimes 5811541Srgrimesdouble 58267486SdwmaloneCanvasView::_NextZoomOutLevel(double zoom) const 5831541Srgrimes{ 5841541Srgrimes if (zoom > 32) 58567486Sdwmalone return 32; 58667486Sdwmalone if (zoom > 16) 58767486Sdwmalone return 16; 58867486Sdwmalone if (zoom > 8) 58967486Sdwmalone return 8; 59067486Sdwmalone if (zoom > 6) 59167486Sdwmalone return 6; 59267486Sdwmalone if (zoom > 4) 593190380Srwatson return 4; 59467486Sdwmalone if (zoom > 3) 595128263Speadar return 3; 596128263Speadar if (zoom > 2) 597128263Speadar return 2; 598128263Speadar if (zoom > 1.5) 599128263Speadar return 1.5; 6001541Srgrimes return 1; 601128263Speadar} 6021541Srgrimes 603128263Speadar 604128263Speadarvoid 60554480SdillonCanvasView::_SetZoom(double zoomLevel, bool mouseIsAnchor) 6061541Srgrimes{ 607128263Speadar if (fZoomLevel == zoomLevel) 60854480Sdillon return; 60941026Speter 61054480Sdillon BPoint anchor; 6111541Srgrimes if (mouseIsAnchor) { 61254480Sdillon // zoom into mouse position 6131541Srgrimes anchor = MouseInfo()->position; 614171190Sjhb } else { 615171190Sjhb // zoom into center of view 616171190Sjhb BRect bounds(Bounds()); 617171190Sjhb anchor.x = (bounds.left + bounds.right + 1) / 2.0; 618171190Sjhb anchor.y = (bounds.top + bounds.bottom + 1) / 2.0; 619171190Sjhb } 620171190Sjhb 621171190Sjhb BPoint canvasAnchor = anchor; 622171190Sjhb ConvertToCanvas(&canvasAnchor); 623171190Sjhb 624171190Sjhb fZoomLevel = zoomLevel; 625171190Sjhb BRect dataRect = _LayoutCanvas(); 626190380Srwatson 627171190Sjhb ConvertFromCanvas(&canvasAnchor); 628171190Sjhb 629190380Srwatson BPoint offset = ScrollOffset(); 630190380Srwatson offset.x = roundf(offset.x + canvasAnchor.x - anchor.x); 6311541Srgrimes offset.y = roundf(offset.y + canvasAnchor.y - anchor.y); 6321541Srgrimes 6331541Srgrimes Invalidate(); 6349336Sdfr 6359336Sdfr SetDataRectAndScrollOffset(dataRect, offset); 6369336Sdfr} 6379336Sdfr 6381541Srgrimes 6391541SrgrimesBRect 640190396SrwatsonCanvasView::_LayoutCanvas() 641190396Srwatson{ 642190396Srwatson // size of zoomed bitmap 643190396Srwatson BRect r(_CanvasRect()); 644190396Srwatson r.OffsetTo(B_ORIGIN); 645158739Smohans 646190380Srwatson // ask current view state to extend size 647190396Srwatson // TODO: Ask StateViewState to extend bounds... 648190396Srwatson BRect stateBounds = r; //ViewStateBounds(); 649190396Srwatson 650190380Srwatson // resize for empty area around bitmap 651190380Srwatson // (the size we want, but might still be much smaller than view) 6521541Srgrimes r.InsetBy(-50, -50); 6531541Srgrimes 65436176Speter // center data rect in bounds 65536176Speter BRect bounds(Bounds()); 656221973Srmacklem if (bounds.Width() > r.Width()) 65736176Speter r.InsetBy(-ceilf((bounds.Width() - r.Width()) / 2), 0); 658221973Srmacklem if (bounds.Height() > r.Height()) 659220595Sru r.InsetBy(0, -ceilf((bounds.Height() - r.Height()) / 2)); 66036176Speter 66136176Speter if (stateBounds.IsValid()) { 6621541Srgrimes stateBounds.InsetBy(-20, -20); 6631541Srgrimes r = r | stateBounds; 6641541Srgrimes } 6651541Srgrimes 6661541Srgrimes return r; 6671549Srgrimes} 66883651Speter 6691541Srgrimes