/** Simple scroll bar implemented in plain AS 3.0 so SWF size can be kept small (no component frameworks need to be included). (C) 2008, 2009 Jan Holst Jensen, jan@biochemfusion.com. All rights reserved. Thanks to "Essential ActionScript 3.0 by Colin Moock. Copyright 2007 O'Reilly Media, Inc., 0-596-52694-6" and numerous examples on the web for providing inspiration and code snippets for various scroll bar implementations. This Flash action script code file (BCFScrollBar.as) is released under a BSD-style license: * Copyright (C) 2008, 2009 Biochemfusion (http://www.biochemfusion.com) * All rights reserved. * * Redistribution and use for any purpose in source and binary forms, with or * without modification, are permitted, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * THIS SOFTWARE IS PROVIDED BY Biochemfusion ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Biochemfusion BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/ package { import flash.display.DisplayObjectContainer; import flash.display.Sprite; import flash.geom.Rectangle; import flash.events.Event; import flash.events.MouseEvent; public class BCFScrollBar extends Sprite { private static const SCROLL_BAR_WIDTH:int = 10; private static const SCROLL_THUMB_HEIGHT:int = 30; private static const SCROLL_TRACK_COLOR:int = 0xFF6400; private static const SCROLL_THUMB_COLOR:int = 0x888888; private static const SCROLL_CHEVRON_COLOR:int = 0x000000; private var scrollTrack:Sprite; private var scrollThumb:Sprite; private var isDragging:Boolean = false; private var scrolledContainer:DisplayObjectContainer; public function getWidth():int { return SCROLL_BAR_WIDTH; } private function mouseDownListener(e: Event):void { var bounds:Rectangle = new Rectangle( scrollTrack.x, scrollTrack.y, 0, scrollTrack.y + scrollTrack.height - scrollThumb.height ); scrollThumb.startDrag(false, bounds); isDragging = true; } private function mouseUpListener(e: Event):void { if (isDragging) { scrollThumb.stopDrag(); isDragging = false; } } private function mouseMoveListener(e: Event):void { if (!visible) return; var scrollMax:int = scrollTrack.height - scrollThumb.height; if ((scrollMax > 0) && (scrolledContainer.stage.stageHeight > 0)) { var relativeThumbPos:Number = scrollThumb.y / scrollMax; var extraContainerY:int = scrolledContainer.height - scrolledContainer.stage.stageHeight; scrolledContainer.y = - int(extraContainerY * relativeThumbPos); } else scrolledContainer.y = 0; } public function syncToContainer():void { if (!visible) { scrollThumb.y = 0; return; } scrollTrack.height = scrolledContainer.stage.stageHeight; var scrollMax:int = scrollTrack.height - scrollThumb.height; if ((scrollMax > 0) && (scrolledContainer.y != 0)) { var extraContainerY:int = scrolledContainer.height - scrolledContainer.stage.stageHeight; var relativeThumbPos:Number = - scrolledContainer.y / extraContainerY; scrollThumb.y = relativeThumbPos * scrollMax; if (scrollThumb.y > scrollMax) scrollThumb.y = scrollMax; } else scrollThumb.y = 0; } public function BCFScrollBar(container:DisplayObjectContainer) { scrolledContainer = container; scrollTrack = new Sprite(); scrollTrack.graphics.lineStyle(); scrollTrack.graphics.beginFill(SCROLL_TRACK_COLOR); scrollTrack.graphics.drawRect(0, 0, 1, 1); addChild(scrollTrack); scrollTrack.x = 0; scrollTrack.y = 0; scrollTrack.width = SCROLL_BAR_WIDTH; scrollTrack.height = 200; scrollThumb = new Sprite(); scrollThumb.graphics.lineStyle(); scrollThumb.graphics.beginFill(SCROLL_THUMB_COLOR); scrollThumb.graphics.drawRect(0, 0, SCROLL_BAR_WIDTH - 1, SCROLL_THUMB_HEIGHT - 1); scrollThumb.graphics.endFill(); // Add chevron marks to scroll thumb. scrollThumb.graphics.lineStyle(1, SCROLL_CHEVRON_COLOR); scrollThumb.graphics.moveTo(2, 5); scrollThumb.graphics.lineTo(SCROLL_BAR_WIDTH / 2 - 1, 2); scrollThumb.graphics.lineTo(SCROLL_BAR_WIDTH - 4, 5); scrollThumb.graphics.moveTo(2, SCROLL_THUMB_HEIGHT - 7); scrollThumb.graphics.lineTo(SCROLL_BAR_WIDTH / 2 - 1, SCROLL_THUMB_HEIGHT - 4); scrollThumb.graphics.lineTo(SCROLL_BAR_WIDTH - 4, SCROLL_THUMB_HEIGHT - 7); addChild(scrollThumb); scrollThumb.x = 0; scrollThumb.y = 100; scrollThumb.width = SCROLL_BAR_WIDTH; scrollThumb.height = 30; scrollThumb.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownListener); // MOUSE_UP and MOUSE_MOVE are "global" listeners. OK to attach them here, since the current usage // pattern is just a single scrollbar per stage. scrolledContainer.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpListener); scrolledContainer.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveListener); } } }