piDogScrollingCanvas
Super
Canvas
Notes
About
Written for Cocoa, Carbon, Win32, and Linux by Jim McKay, ©2014 piDog Software
This control requires the piDogGeometry Module and the piDogScrollerClass
The control is designed to provide a natural feel with scroll, zoom and rotate gestures (Cocoa only).
Scrolling is handled by assigning a value to ScrollingLayerSize. You may then call RefreshRectScrollingLayer when a part of the layer has changed.
The PaintScrollingLayer Event will then be fired, allowing the drawing code to proceed.
The same is true for the DragLayer and OverlayLayer
One of the benefits of this system is that non-visible areas will not be drawn, but will remain "dirty" until they become visible reducing cpu usage.
When dirty areas in the ScrollingLayer, DragLayer, and/or OverlayLayer overlap, then areas are combined to reduce rendering steps.
When scrolling with a Magic Trackpad, the trackpad's inertial scrolling superceeds the canvas's inertial scrolling for a natural feel.
Zooming with a Magic Trackpad will focus the zoom area so as to keep the same point in the image under the mouse pointer through the zoom gesture.
The canvas has several modes:
Raster - The ScrollingLayer is rendered at 1:1 and scaled to zoom
Vector - The PaintScrollingLayer event is given a zoom factor for rendering, so rendering always appears at screen resolution.
Hybrid - Uses Raster mode when under 100% zoom and Vector otherwise
ReverseHybrid - Uses Vector mode when under 100% zoom and Raster otherwise
ScrollingImage and OverlayImage are non-dynamic versions of the similarly named dynamic layers and can be assigned in the IDE or at runtime.
To use piDogScrollingCanvas in your Xojo app, simply drag the canvas to a window and add needed events.
License
piDogScrollingCanvas is a custom Canvas subclass by piDog Software and is a part of the piDog Bundle for Xojo.
As a licensed user you have the right to use this class in your Xojo projects. Reverse engineering or breaking the encryption is prohibited.
Release Notes
1.4.0
64bit compatible!
Improved rendering time and responsiveness
Fixed Vibrancy.
v1.3.1.1
Fixed an issue with scrollerbounds not adjusting correctly
ScrollerBounds property removed
AdjustScrolerBounds event added
Window resizing flicker fixed
Win32 rendering/scrolling improved
SnapBackDuration replaced with ScrollWheelDuration
v1.2
Added UseNSScrollers property to use Native scrolling on MacOS
Now gets notifications to update AutoHideScrollers when the user changes the system settings
Added ScrollerBounds property to set the area where scrollers will reside
Several internal optimizations
Fixed up Enumeration scope for Xojo2014r3 in the draggableObjects module
v1.1
Added Resizing event
Now renders OverlayLayer as a buffered object under MacOS
Single scrollers now occupies full width/height
Improved rendering by combining BackgroundColor and BackgroundPattern into a single operation
Fixed some possible crashing bugs
Fixed DraggableImage rotation bug in demo
Scrolling inertia now cancelled when mouse moved or clicked
Added MaxZoom and MinZoom properties
Added snapback behavior when zoom exceeds max or min with Cocoa gestures
Now uses an NSView instance to track gestures
Constants
RenderModeHybrid
Renders in Vector mode below 100% zoom, Raster above
RenderModeRaster
Rendering is scaled after painting at 100% zoom
RenderModeReverseHybrid
Vector mode above 100%, Raster mode below
RenderModeVector
Content is drawn on-demand at screen (Zoom) resolution
Events
AdjustScrollerBounds(bounds As REALbasic.Rect)
Called when scrollerbounds need adjusting. Change the properties of the bounds parameter to the desired area.
BackingScaleChanged(Scale As Double)
Claaed when the BackingScale of the window changes. ie moving from retina-to non-retina.
Close
The control is about to close
ConstructContextualMenuOverlayLayer(base As MenuItem,x As integer,y As Integer) as Boolean
The user has right-clicked in the canvas at x,y. Return true to handle the event in the OverlayLayer.
ConstructContextualMenuScrollingLayer(base As MenuItem,x As integer,y As Integer) as Boolean
The user has right-clicked in the canvas at x,y. Return true to handle the event in the ScrollingLayer.
ContextualMenuActionOverlayLayer(HitItem As MenuItem) as Boolean
The user has selected a menuItem created in ConstructContextualMenuOverlayLayer.
ContextualMenuActionScrollingLayer(HitItem As MenuItem) as Boolean
The user has selected a menuItem created in ConstructContextualMenuScrollingLayer.
DragOver(x As integer,y as integer,obj As DragItem,action as integer) as Boolean
A drag event is occurring at x,y. Return false to pass the event throught to individual layers.
DragOverOverlayLayer(x As integer,y as integer,obj As DragItem,action as integer) as Boolean
A drag event is occuring at x,y. Return false to pass the event throught to scrolling layer.
DragOverScrollingLayer(x As double,y as double,obj As DragItem,action as integer) as Boolean
A drag event is occuring at x,y relative to the scrollbounds.
DropObject(obj as DragItem,action as integer)
Standard DropObjec event.
DropObjectOverlayLayer(obj as DragItem,action as integer)
A drop occurred after true was returned from DragOverOverlayLayer.
DropObjectScrollingLayer(obj as DragItem,action as integer)
A Drop occurred after true was returned from DragOverScrollingLayer.
EdgeScroll(x As integer, y as integer) as Boolean
Return true from this event to prevent automated drag-scrolling behavior
LostFocus
Standard LostFocus event
Magnify(ZoomOffset As Double,x as Double,y as double) as boolean
The user has used a pinch to zoom gesture. Return true to handle the zoom, otherwise automatic zooming is performed.
MouseDown(x As integer, y as integer) as Boolean
The user has clicked in the control at x,y
MouseDownOverlayLayer(X As integer,Y As Integer) as Boolean
The User has clicked the mouse within the control at x,y. Return true to handle the event and receive subsequent overlay layer mouse events or false to pass it through to MouseDownScrollingLayer.
MouseDownScrollingLayer(X As double,Y As double) as Boolean
The User has clicked the mouse within the control at x,y adjusted for scrolling and zooming. Return true to handle the event and receive subsequent scrolling layer mouse events
MouseDrag(x as integer, y as integer)
The user has dragged the mouse at x,y
MouseDragOverlayLayer(X As integer,Y As Integer)
User is dragging at x,y.
MouseDragScrollingLayer(X As double,Y As double)
User is dragging at x,y relative to scrollingarea, adjusted for scroll/zoom
MouseEnter
The mouse entered the control
MouseExit
The mouse has left the control
MouseMove(X as integer, Y as integer)
the mouse moved in the control at x,y
MouseMoveOverlayLayer(X As integer,Y As Integer) as Boolean
The mouse moved at x,y. Return true to prevent scrolling layer mouse moved event.
MouseMoveScrollingLayer(X As double,Y As double) as Boolean
The mouse moved at x,y relative to the scrollig area, adjusted for zoom and not handled in overlay layer.
MouseUp(X as integer, Y as integer)
The mouse button has been released as x,y
MouseUpOverlayLayer(X As integer,Y As Integer)
MouseUp occurred at x,y after a MouseDownOverlay returned true.
MouseUpScrollingLayer(X As double,Y As double)
A MouseUp occurred at x,y relative to the scollbounds adjusted for scroll/zoom after true was returned from a MouseDownScrollingLayer Event.
MouseWheelOverlayLayer(X As integer,Y As Integer,deltaX As integer,deltaY As Integer) as boolean
The scrollwheel was turned at x,y. Return true to handle the event, otherwise it will pass through to the scrolling layer
MouseWheelScrollingLayer(X As double,Y As double,byref deltaX As double,byref deltaY As Double) as boolean
A MouseWheel occurred at x,y relative to the scroll bounds, adjusted for scroll/zoom. Return true to handle the event or it will be handled automatically by the canvas.
Open
The canvas is about to open.
PaintDragLayer(g as Graphics, area As piDogGeometry.DoubleRect,zoom as double=1,xOffset As double=0,yOffset As double=0) as boolean
area needs to be redrawn. g is the main graphics. m is the graphcs for masking under carbon/win32. Zoom is the scale. xOffset/yOffset should be subtracted from coordinates before drawing.
PaintOverlayLayer(g As graphics,area As REALbasic.Rect,zoom as double=1,xOffset As double=0,yOffset As double=0) as Boolean
area needs to be redrawn. g is the main graphics. m is the graphcs for masking under carbon/win32.
PaintScrollers(g As Graphics) as Boolean
Return true to handle scroller painting and prevent built-in drawing
PaintScrollingLayer(g as Graphics,area As piDogGeometry.DoubleRect,zoom as double=1,xOffset As double=0,yOffset As double=0) as Boolean
area needs to be redrawn. g is the main graphics. m is the graphcs for masking under carbon/win32. Zoom is the scale. xOffset/yOffset should be subtracted from coordinates before drawing.
Resized
The Canvas was resized. Called after painting.
Resizing
The Canvas is resizing. Called before painting
Rotate(angle as Double,x As Double,y As Double)
A rotate gesture occurred at x,y. Angle is the rotation delta.
Scrolled
The scrollbounds have moved.
ScrollingLayerSizeChanged
Use this event to make adjusments based on the size of the scrolling layer.
ScrollPastX(leftBound as Boolean)
The user has scrolled past a horizontal limit. leftBound will be true if the scroll was past the left edge and false if past the right edge.
ScrollPastY(topBound as Boolean)
The user has scrolled past a vertical limit. topBound will be true if the scroll was past the top edge and false if past the bottom edge.
ZoomChanged
The current zoom value has changed, either through code or by a zoom gesture.
Methods
Sub Constructor()
Standard Constructor
Function EnableVibrancy(includeTitleBar as Boolean = false, wholeWindow as Boolean = false, Appearance as integer = 0) As Boolean
Under MacOSX 10.10 calling this Method will enable vibrancy for the canvas and (optionally) the titlebar of the window
Appearance 0=default 1=light 2=dark 3=titlebar(brighter than light)
Sub Invalidate()
Requests that the entire Canvas be redrawn.
Sub PageDown()
Causes the view to scroll down by one page (the height of the control)
Sub PageLeft()
Causes the view to scroll left by one page (the width of the control)
Sub PageRight()
Causes the view to scroll right by one page (the width of the control)
Sub PageUp()
Causes the view to scroll up by one page (the height of the control)
Sub Refresh()
Requests that the entire canvas be redrawn. Also clears cached renderings.
Sub RefreshRect(x As Integer, y As Integer, width As Integer, height As Integer)
Sets an area to be redrawn (all layers)
Sub RefreshRectDragLayer(x As integer, y As integer, width As integer, height As Integer)
Sets an area in the drag layer to be redrawn.
Sub RefreshRectScrollingLayer(x As integer, y As integer, width As integer, height As Integer)
Sets an area in the scrolling layer to be redrawn,
Sub RefreshRectStaticLayer(x As integer, y As integer, width As integer, height As Integer)
Sets an area in the Overlay layer to be redrawn.
Sub RenderToGraphics(g as graphics, scrollingLayer As Boolean, Draglayer As Boolean, OverlayLayer As Boolean)
Draws the layers to the passed graphics object rather than to screen
Sub ScrollToRect(x as integer, y as integer, width as integer, height as integer, duration As Double)
Scrolls the specified rectangle into view
Function Snapshot(ScrollingLayer As Boolean, DragLayer As Boolean, OverlayLayer As Boolean) As Picture
Returns a picture of the specified layers at 100% scale.
Function TranslatePointToView(point as REALbasic.Point) As REALbasic.Point
Translates a point in scrollingLayer coords to position in View coordinates
Function TranslateRectToView(rect as REALbasic.Rect) As REALbasic.Rect
Translates a rect in scrollingLayer coords to area in View coordinates
Function trueLeft() As integer
left relative to truewindow
Function trueTop() As integer
top relative to truewindow
Properties
AutoHideScrollers As Boolean
Whether the scrollbars are hidden when not scrolling. On OS X this is set by the system.
BackdropImage As Picture
An Image to be drawn behind other layers
BackgroundColor As Color
The color to fill where no content was drawn
BackgroundPattern As Picture
An image to be tiled beneath other layers aside from a BackdropImage.
BackingScale As Integer
The BackingScale of the window. On a Retina display returns 2
Bordered As Boolean
Set to true to draw a one-pixel border around the control
BuiltInScrollers As Boolean
Whether the control will render scrollers. (Also false when UseNativeScrollers=true)
DebugRects As Boolean
DisableHorizontalBounce As Boolean
DisableVerticalBounce As Boolean
FPS As Integer
Returns the theoretical number of frames that could be drawn based on most recent frame
Interpolation As Boolean
Whether scaled drawing should be interpolated or use the faster non-interpolated rendering.
LastFrameDuration As Double
Used to benchmark rendering speed
MaxZoom As Double = -1
The maximum allowed zoom value
MinZoom As Double = -1
The minimum allowed zoom value
NSScrollerSlots As Boolean = true
Whether Scroller slots are visible when using NSScrollers
NSScrollerStyle As Integer
The style of the NSScrollers when UseNativeScrollers is true
OverlayImage As Picture
An Image to be rendered above all other layers.
PageScroll As Boolean
Whether a click above or below the scroller will scroll by visible pages
PreventMomentumScrollx As Boolean = false
PreventMomentumScrolly As Boolean = false
renderMode As Integer
Sets the Rendering Mode for the canvas. See Constants for available modes.
ScrollbarBorderColor As Color
The color used to draw outlines on the scrollers.
ScrollbarBorderSize As Integer
The original thickness of the scroller borders. Scrollers are drawn at double resolution and scaled down for a smoother appearance.
ScrollbarColor As Color
The fill color for the scrollbars.
ScrollBarsHaveBorder As Boolean
Whether or not to render outlines for scrollbars.
ScrollBarSize As Integer
Width, in pixels of scrollbars.
Attributes( Hidden = 1 ) scrollBounds As piDogGeometry.DoubleRect
ScrollingImage As Picture
An image to be drawn below the scrolling layer and above the backdrop image. This layer scrolls with the scrolling layer.
ScrollingLayerSize As REALbasic.Size
The actual size, in pixels, of the scrollable area.
ScrollOnEdgeDrag As Boolean = true
Whether the control will adjust scrolling layer and/or scrolling image when the user drags out of the control.
ScrollPast As Boolean = true
Whether the canvas has a "snap-back" behavior. Also determines in the ScrollPastX and ScrollPastY events will be fired.
ScrollPositionX As Double
The Horizontal position of the ScrollingImage and/or ScrollingLayer
ScrollPositionY As Double
The Vertical position of the ScrollingImage and/or ScrollingLayer
ScrollToDuration As Double
The time to scroll to an area outside of the visible view area
ScrollwheelDuration As Double = .5
The time to scroll to the area made visible by scrolling with a scrollwheel or trackpad
UseDragLayer As Boolean
Whether drawing should be performed for a drag layer. Set to false if the drag layer will not be used to save cpu cycles.
UseNativeScrollers As Boolean
Whether the control will use native NSScrollers to manage scrolling on MacOSX. The side effect of this setting is the loss of inertial scrolling when a mouse wheel is used.
UseOverlayLayer As Boolean
Whether the control will use a dynamic overlay layer
UseScrollingLayer As Boolean
Whether drawing should be performed for a scrolling layer. Set to false if the scrolling layer is not used to save cpu cycles. Does not affect ScrollingImage rendering.
Zoom As Double
Rendering magnification. Double value where 1=100% .5=50% etc
ZoomPoint As REALbasic.Point
The point (scrolling layer based coordinates) where zooming in or out will attempt to focus the view.
Shared Methods
Shared Function Register(Name As string, ExpirationDate As string, SerialNumber as string, optional CopyNumber As Integer = 1) As Boolean
Used to enter piDog Bundle / piDogScrollingCanvas Registration Key. If not registered, a warning will be shown in built apps.
Shared Properties
Attributes( Hidden ) Protected Shared cocoaRefs As Dictionary