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.