topical media & game development
actionscript-events-ScrollBar.ax
actionscript-events-ScrollBar.ax
[swf]
flex
package {
import flash.display.*;
import flash.text.*;
import flash.events.*;
import flash.utils.*;
import flash.geom.*;
// A simple draggable scrollbar that automatically updates its size
// in response to changes in the size of a specified text field.
// Usage:
// var theTextField:TextField = new TextField();
// someContainer.addChild(theTextField);
// var scrollbar:@ax-actionscript-events-ScrollBar = new @ax-actionscript-events-ScrollBar(theTextField);
// someContainer.addChild(scrollbar);
public class @ax-actionscript-events-ScrollBar extends Sprite {
// The text field to which this scrollbar is applied
private var t:TextField;
// The current height of the text field. If the text field's height
// changes, we update the height of this scrollbar.
private var tHeight:Number;
// The background graphic for the scrollbar
private var scrollTrack:Sprite;
// The scrollbar's draggable "scroll thumb"
private var scrollThumb:Sprite;
// The scrollbar's width
private var scrollbarWidth:int = 15;
// The minimum height of the scrollbar's scroll thumb
private var minimumThumbHeight:int = 10;
// A flag indicating whether the user is currently dragging the
// scroll thumb
private var dragging:Boolean = false;
// A flag indicating whether the scrollbar should be redrawn at the next
// scheduled screen update
private var changed:Boolean = false;
// Constructor.
//
parameter: textfield The TextField object to which to apply
// this scrollbar.
public function @ax-actionscript-events-ScrollBar (textfield:TextField) {
// Store a reference to the TextField to which this
// scrollbar is applied
t = textfield;
// Remember the text field's height so that we can track it for
// changes that require a scrollbar redraw.
tHeight = t.height;
// Create the scrollbar background
scrollTrack = new Sprite();
scrollTrack.graphics.lineStyle();
scrollTrack.graphics.beginFill(0x333333);
scrollTrack.graphics.drawRect(0, 0, 1, 1);
addChild(scrollTrack);
// Create the draggable scroll thumb on the scrollbar
scrollThumb = new Sprite();
scrollThumb.graphics.lineStyle();
scrollThumb.graphics.beginFill(0xAAAAAA);
scrollThumb.graphics.drawRect(0, 0, 1, 1);
addChild(scrollThumb);
// Register an Event.SCROLL listener that will update the scrollbar
// to match the current scroll position of the text field
t.addEventListener(Event.SCROLL, scrollListener);
// Register with scrollThumb for mouse down events, which will trigger
// the dragging of the scroll thumb
scrollThumb.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownListener);
// Register to be notified when this object is added to or removed
// from the display list (requires the custom helper class,
// StageDetector). When this object is added to the display list,
// register for stage-level mouse move and mouse up events that
// will control the scroll thumb's dragging operation.
var stageDetector:actionscript_util_StageDetector = new actionscript_util_StageDetector(this);
stageDetector.addEventListener(actionscript_util_StageDetector.ADDED_TO_STAGE,
addedToStageListener);
stageDetector.addEventListener(actionscript_util_StageDetector.REMOVED_FROM_STAGE,
removedFromStageListener);
// Register to be notified each time the screen is about to be
// updated. Before each screen update, we check to see whether the
// scrollbar needs to be redrawn. For information on the
// Event.ENTER_FRAME event, see Chapter ##, Programmatic Animation.
addEventListener(Event.ENTER_FRAME, enterFrameListener);
// Force an initial scrollbar draw.
changed = true;
}
// Executed whenever this object is added to the display list
private function addedToStageListener (e:Event):void {
// Register for "global" mouse move and mouse up events
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);
}
// Executed whenever this object is removed from the display list
private function removedFromStageListener (e:Event):void {
// Unregister for "global" mouse move and mouse up events
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpListener);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener);
}
// Executed once for each screen update. This method checks
// whether any changes in the text field's scroll position, content,
// or size have occurred since the last time the scrollbar was drawn.
// If so, we redraw the scrollbar. By performing this "draw or not"
// check once per screen-update only, we eliminate redundant calls to
// updateScrollbar(), and we also avoid some Flash Player timing issues
// with TextField.maxScrollV.
private function enterFrameListener (e:Event):void {
// If the text field has changed height, request a redraw of the
// scrollbar
if (t.height != tHeight) {
changed = true;
tHeight = t.height;
// The height has changed, so stop any dragging operation in
// progress. The user will have to click again to start dragging
// the scroll thumb once the scroll bar has been redrawn.
if (dragging) {
scrollThumb.stopDrag();
dragging = false;
}
}
// If the scrollbar needs redrawing...
if (changed) {
// ...call the scrollbar drawing routine
updateScrollbar();
changed = false;
}
}
// Handles Event.SCROLL events
private function scrollListener (e:Event):void {
// In certain cases, when lines are removed from a text field,
// Flash Player dispatches two events: one for the reduction in
// maxScrollV (dispatched immediately) and one for the reduction in
// scrollV (dispatched several screen updates later). In such cases,
// the scrollV property temporarily contains an erroneous value that
// is greater than maxScrollV. As a workaround, we ignore the event
// dispatch for the change in maxScrollV, and wait for the event
// dispatch for the change in scrollV (otherwise, the rendered
// scrollbar would temporarily not match the text field's actual
// content).
if (t.scrollV > t.maxScrollV) {
return;
}
// If the user is not currently dragging the scrollbar's scroll
// thumb, then note that this scrollbar should be redrawn at the next
// scheduled screen update. (If the user is dragging the scroll thumb,
// then the scroll change that caused this event was the result of
// dragging the scroll thumb to a new position, so there's no need to
// update the scrollbar because the scroll thumb is already in the
// correct position.)
if (!dragging) {
changed = true;
}
}
// Sets the size and position of the scrollbar's background and scroll
// thumb in accordance with the associated text field's size and
// content. For information on the TextField properties scrollV,
// maxScrollV, and bottomScrollV, see Adobe's ActionScript Language
// Reference.
public function updateScrollbar ():void {
// Set the size and position of the scrollbar background.
// This code always puts the scrollbar on the right of the text field.
scrollTrack.x = t.x + t.width;
scrollTrack.y = t.y;
scrollTrack.height = t.height;
scrollTrack.width = scrollbarWidth;
// Check the text field's number of visible lines
var numVisibleLines:int = t.bottomScrollV - (t.scrollV-1);
// If some of the lines in the text field are not currently visible...
if (numVisibleLines < t.numLines) {
// ... make the scroll thumb visible
scrollThumb.visible = true;
// Now set the scroll thumb's size
// The scroll thumb's height is the percentage of lines showing,
// times the text field's height
var thumbHeight:int = Math.floor(t.height *
(numVisibleLines/t.numLines));
// Don't set the scroll thumb height to anything less
// than minimumThumbHeight
scrollThumb.height = Math.max(minimumThumbHeight, thumbHeight);
scrollThumb.width = scrollbarWidth;
// Now set the scroll thumb's position
scrollThumb.x = t.x + t.width;
// The scroll thumb's vertical position is the number lines the
// text field is scrolled, as a percentage, times the height of
// the "gutter space" in the scrollbar (the gutter space is the
// height of the scroll bar minus the height of the scroll thumb).
scrollThumb.y = t.y + (scrollTrack.height-scrollThumb.height)
* ((t.scrollV-1)/(t.maxScrollV-1));
} else {
// If all lines in the text field are currently visible, hide the
// scrollbar's scroll thumb
scrollThumb.visible = false;
}
}
// Sets the text field's vertical scroll position to match the relative
// position of the scroll thumb
public function synchTextToScrollThumb ():void {
var scrollThumbMaxY:Number = t.height-scrollThumb.height;
var scrollThumbY:Number = scrollThumb.y-t.y;
t.scrollV = Math.round(t.maxScrollV
* (scrollThumbY/scrollThumbMaxY));
}
// Executed when the primary mouse button is depressed over the scroll
// thumb
private function mouseDownListener (e:MouseEvent):void {
// Start dragging the scroll thumb. (The startDrag() method is
// inherited from the Sprite class.)
var bounds:Rectangle = new Rectangle(t.x + t.width,
t.y,
0,
t.height-scrollThumb.height);
scrollThumb.startDrag(false, bounds);
dragging = true;
}
// Executes when the primary mouse button is released (anywhere over, or
// even outside of, Flash Player's display area)
private function mouseUpListener (e:MouseEvent):void {
// If the scroll thumb is being dragged, update the text field's
// vertical scroll position, then stop dragging the scroll thumb
if (dragging) {
synchTextToScrollThumb();
scrollThumb.stopDrag();
dragging = false;
}
}
// Executes when the mouse pointer is moved (anywhere over Flash
// Player's display area)
private function mouseMoveListener (e:MouseEvent):void {
// If the scroll thumb is being dragged, set the text field's vertical
// scroll position to match the relative position of the scroll thumb
if (dragging) {
synchTextToScrollThumb();
}
}
}
}
(C) Æliens
27/08/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.