Generic control for scrolling a display object around within its parent.

This doesn't (seem to) work quite right because of the way Flash does
handles component dimensions. It's designed to be overridden.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4450 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2006-11-13 22:42:38 +00:00
parent ff951383c3
commit cfddf38a67
@@ -0,0 +1,147 @@
package com.threerings.mx.controls {
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import mx.containers.Canvas;
/**
* A control for scrolling some component separately.
*/
public class ScrollBox extends Canvas
{
public function ScrollBox (
target :DisplayObject, maxWidth :int, maxHeight :int)
{
_target = target;
_maxWidth = maxWidth;
_maxHeight = maxHeight;
opaqueBackground = 0xFFFFFF;
_box = new Sprite();
rawChildren.addChild(_box);
recheckBounds();
// TODO: only when something changes
addEventListener(Event.ENTER_FRAME, enterFrame);
_box.addEventListener(MouseEvent.MOUSE_DOWN, spritePressed);
}
override public function setActualSize (w :Number, h :Number) :void
{
super.setActualSize(w, h);
recheckBounds();
graphics.clear();
graphics.lineStyle(1, 0);
graphics.drawRect(0, 0, width, height);
}
protected function enterFrame (vent :Event) :void
{
if (!_dragging) {
recheckBounds();
}
}
/**
* Get the bounds of the scrollable area. Broken-out for easy overridding.
*/
protected function getScrollBounds () :Rectangle
{
var bounds :Rectangle = _target.transform.pixelBounds;
// var m :Matrix = _target.transform.concatenatedMatrix;
// bounds.topLeft = m.transformPoint(bounds.topLeft);
// bounds.bottomRight = m.transformPoint(bounds.bottomRight);
return bounds;
}
protected function recheckBounds () :void
{
var bounds :Rectangle = getScrollBounds();
// see what's visible, what's not..
var scroller :Rectangle = _target.scrollRect;
if (scroller == null) {
scroller = bounds.clone();
}
if ((_bounds != null) && _bounds.equals(bounds) &&
(_scroller != null) && _scroller.equals(scroller)) {
return;
}
_bounds = bounds.clone();
_scroller = scroller;
_scale = Math.min(1,
Math.min(_maxWidth / _bounds.width, _maxHeight / _bounds.height));
width = _scale * _bounds.width;
height = _scale * _bounds.height;
drawBox(_box, _scroller.width * _scale, _scroller.height * _scale);
_box.x = (_scroller.x - _bounds.x) * _scale;
_box.y = (_scroller.y - _bounds.y) * _scale;
}
protected function drawBox (box :Sprite, ww :Number, hh :Number) :void
{
var g :Graphics = _box.graphics;
g.clear();
g.beginFill(0x0000FF);
g.drawRect(0, 0, ww, hh);
g.endFill();
}
protected function spritePressed (evt :MouseEvent) :void
{
_box.addEventListener(Event.ENTER_FRAME, boxUpdate);
_box.startDrag(true,
new Rectangle(0, 0, width - _box.width, height - _box.height));
stage.addEventListener(MouseEvent.MOUSE_UP, spriteReleased);
_dragging = true;
}
protected function spriteReleased (evt :MouseEvent) :void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, spriteReleased);
_box.stopDrag();
_box.removeEventListener(Event.ENTER_FRAME, boxUpdate);
_dragging = false;
}
protected function boxUpdate (evt :Event) :void
{
var r :Rectangle = _target.scrollRect;
r.x = (_box.x / _scale) + _bounds.x;
r.y = (_box.y / _scale) + _bounds.y;
_target.scrollRect = r;
}
protected var _dragging :Boolean;
protected var _target :DisplayObject;
protected var _maxWidth :int;
protected var _maxHeight :int;
protected var _box :Sprite;
protected var _scale :Number;
protected var _bounds :Rectangle;
protected var _scroller :Rectangle;
}
}