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:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user