TextField 用 行スクロールバー
TextField 用 行スクロールバー
@author taiga
package {
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.ColorTransform;
import flash.text.TextField;
import flash.text.TextFieldType;
[SWF (backgroundColor="0xcccccc")]
/**
* TextField 用 行スクロールバー
* @author taiga
*/
public class TextFieldScrollTest extends Sprite {
/** @private */
private var _sampleText :String;
/** @private */
private var _lineHeight :int;
/** @private */
private var _isScrollDown :Boolean;
/** @private */
private var _scrollClickPointY :int;
/** @private */
private var _enabledColor :uint;
/** @private */
private var _disabledColor :uint;
/** TextField インスタンスです。 */
protected var textField :TextField;
/** Sprite インスタンスです。 */
protected var textFieldScrollBar :Sprite;
/** Shape インスタンスです。 */
protected var textFieldScroolBarBackground :Shape;
/** ResetButton インスタンスです。 */
protected var resetButton :ResetButton;
/**
* コンストラクタ
*/
public function TextFieldScrollTest() {
super();
_sampleText = "TextField クラスは、テキストの表示と入力用の表示オブジェクトを作成するために使用されます。SWF ファイルのダイナミックテキストフィールドおよびテキスト入力フィールドは、すべて TextField クラスのインスタンスです。TextField クラスを使用すると、低レベルでのテキストレンダリングが可能になります。ただし、Flex では一般的に Label、Text、TextArea、TextInput コントロールを使用して、テキスト処理を行います。\n\n" +
"テキストフィールドを動的に作成する場合は、TextField() コンストラクタを使用します。\n\n" +
"TextField クラスのメソッドを使用すると、オーサリング時または実行時に作成したダイナミックテキストフィールドやテキスト入力フィールドにテキストを設定、選択、および操作できます。\n\n" +
"ActionScript には、テキストを実行時にフォーマットする方法がいくつか用意されています。TextFormat クラスでは、TextField オブジェクトの文字フォーマットと段落フォーマットを設定できます。TextField.styleSheet プロパティおよび StyleSheet クラスを使用して、テキストフィールドに CSS (Cascading Style Sheet) スタイルを適用できます。CSS を使用すると、ビルトイン HTML タグのスタイル設定、新しいフォーマットタグの定義、またはスタイルの適用を行うことができます。HTML 形式のテキスト(CSS スタイルを使用している場合も可)をテキストフィールドに直接割り当てることができます。テキストフィールドに割り当てる HTML テキストに埋め込みメディア(ムービークリップ、SWF ファイル、GIF ファイル、PNG ファイル、および JPEG ファイル)を含めることができます。この場合テキストは、Web ブラウザ上で HTML ドキュメントの埋め込みメディアの周りをテキストが囲むのと同じように、埋め込みメディアの周りを囲みます。\n\n" +
"Flash Player では、テキストのフォーマットに利用できる HTML タグのサブセットをサポートしています。htmlText プロパティの説明の、サポートされている HTML タグのリストを参照してください。 ";
_enabledColor = 0x333333;
_disabledColor = 0x999999;
createChildren();
}
/** 子表示オブジェクトを生成します。 */
protected function createChildren():void {
if(stage != null) {
stage.addEventListener(MouseEvent.MOUSE_MOVE, scrollMouseMoveHandler, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_UP, scrollMouseUpHandler, false, 0, true);
}
textField = addChildAt(new TextField(), 0) as TextField;
textField.multiline = true;
textField.wordWrap = true;
textField.background = true;
textField.border = true;
textField.type = TextFieldType.INPUT;
textField.addEventListener(Event.CHANGE, textFieldChangeHandler, false, 0, true);
textFieldScrollBar = addChildAt(new Sprite(), 0) as Sprite;
textFieldScroolBarBackground = addChildAt(new Shape(), 0) as Shape;
resetButton = addChildAt(new ResetButton(), 0) as ResetButton;
resetButton.addEventListener(MouseEvent.CLICK, resetButtonClickHandler, false, 0, true);
updateDisplayList();
}
/** 表示リスト上のオブジェクトを再描画します。 */
protected function updateDisplayList():void {
const TEXTFIELD_WIDTH :int = 435;
const TEXTFIELD_HEIGHT :int = 350;
if(textField != null) {
textField.text = "あj";
_lineHeight = textField.getLineMetrics(0).height;
textField.text = _sampleText;
textField.width = TEXTFIELD_WIDTH;
textField.height = TEXTFIELD_HEIGHT;
textField.x = 10;
textField.y = 10;
}
checkNumLines(textField);
if(textFieldScrollBar != null) {
textFieldScrollBar.x = textField.x + textField.width + 2;
textFieldScrollBar.y = textField.y;
drawScrollBar(textFieldScrollBar);
}
if(textFieldScroolBarBackground != null) {
textFieldScroolBarBackground.x = textFieldScrollBar.x + (textFieldScrollBar.width / 2);
textFieldScroolBarBackground.y = textField.y;
drawScrollBarBackground(textFieldScroolBarBackground);
}
if(resetButton != null) {
resetButton.x = textField.x + textField.width - resetButton.width;
resetButton.y = textField.x + textField.height + 5;
}
}
/** TextField インスタンスの CHANGE ハンドラです。 */
protected function textFieldChangeHandler(event:Event):void {
drawScrollBar(textFieldScrollBar);
checkNumLines(event.currentTarget as TextField);
}
/** TextField インスタンスの表示行数を取得します。 */
protected function getShowNumLines(target:TextField):int {
return int((target.height - 4) / _lineHeight);
}
/** スクロールバーとステージのマウスアップ処理です。 */
protected function scrollMouseUpHandler(event:MouseEvent):void {
textField.addEventListener(Event.SCROLL, textFieldKeyScrollHandler, true, int.MAX_VALUE, true);
_isScrollDown = false;
}
/** スクロールバーのマウスダウン処理です。 */
protected function scrollMouseDownHandler(event:MouseEvent):void {
textField.removeEventListener(Event.SCROLL, textFieldKeyScrollHandler, true);
_isScrollDown = true;
_scrollClickPointY = mouseY;
}
/** スクロールバーをマウスダウン中に動かすときの処理です。 */
protected function scrollMouseMoveHandler(event:MouseEvent):void {
var scrollRectHeight_ :int;
var scrollPaneHeight_ :int;
var invisibledNumLines_ :int;
var minY_ :int;
var maxY_ :int;
var dY_ :int;
var dScrollV_ :Number;
scrollRectHeight_ = textField.height;
scrollPaneHeight_ = textField.textHeight;
if(scrollRectHeight_ > scrollPaneHeight_ || !_isScrollDown) {
return;
}
invisibledNumLines_ = textField.numLines - getShowNumLines(textField);
minY_ = textField.y;
maxY_ = scrollRectHeight_ - textFieldScrollBar.height + textField.y;
dY_ = textFieldScrollBar.y + (mouseY - _scrollClickPointY);
if(dY_ <= minY_) {
textFieldScrollBar.y = minY_;
dScrollV_ = 0;
}
else if(dY_ >= maxY_) {
textFieldScrollBar.y = maxY_;
dScrollV_ = invisibledNumLines_;
}
else {
textFieldScrollBar.y = dY_;
dScrollV_ = Math.ceil(dY_ / (maxY_ / invisibledNumLines_));
}
textField.scrollV = dScrollV_ + 1;
_scrollClickPointY = mouseY;
event.updateAfterEvent();
}
/** TextField インスタンスのキースクロール処理です。 */
protected function textFieldKeyScrollHandler(event:Event):void {
if(_isScrollDown) {
return;
}
revisionPoint(event.currentTarget as TextField);
}
/** ResetButton インスタンスの CLICK ハンドラです。*/
protected function resetButtonClickHandler(event:MouseEvent):void {
textField.text = _sampleText;
drawScrollBar(textFieldScrollBar);
checkNumLines(textField);
}
/** スクロールバーの表示 / 非表示 を制御します。*/
protected function checkNumLines(target:TextField):void {
revisionPoint(textField);
if(target.height < target.textHeight + 4) {
textField.addEventListener(Event.SCROLL, textFieldKeyScrollHandler, false, 0, true);
textFieldScrollBar.useHandCursor = true;
textFieldScrollBar.buttonMode = true;
textFieldScrollBar.addEventListener(MouseEvent.MOUSE_UP, scrollMouseUpHandler, false, 0, true);
textFieldScrollBar.addEventListener(MouseEvent.MOUSE_DOWN, scrollMouseDownHandler, false, 0, true);
textFieldScrollBar.addEventListener(MouseEvent.MOUSE_MOVE, scrollMouseMoveHandler, false, 0, true);
hexToRGB(textFieldScrollBar, _enabledColor);
hexToRGB(textFieldScroolBarBackground, _enabledColor);
}
else {
textField.removeEventListener(Event.SCROLL, textFieldKeyScrollHandler, false);
textFieldScrollBar.useHandCursor = false;
textFieldScrollBar.buttonMode = false;
textFieldScrollBar.removeEventListener(MouseEvent.MOUSE_UP, scrollMouseUpHandler, false);
textFieldScrollBar.removeEventListener(MouseEvent.MOUSE_DOWN, scrollMouseDownHandler, false);
textFieldScrollBar.removeEventListener(MouseEvent.MOUSE_MOVE, scrollMouseMoveHandler, false);
hexToRGB(textFieldScrollBar, _disabledColor);
hexToRGB(textFieldScroolBarBackground, _disabledColor);
}
}
/** スクロールバーの座標を補正します。 */
protected function revisionPoint(target:TextField):void {
var dHeight_ :int = target.height - textFieldScrollBar.height;
var dScrollV_ :int = target.scrollV - 1;
var resultY_ :Number = dHeight_ / (target.numLines - getShowNumLines(target)) * dScrollV_;
var y_ :Number = resultY_ + target.y
if(y_ + textFieldScrollBar.height > target.y + target.height) {
y_ = target.y + target.height - textFieldScrollBar.height;
}
if(y_ < target.y || isNaN(y_)) {
y_ = target.y;
}
textFieldScrollBar.y = y_;
}
/** スクロールバーの外観を描画します。 */
protected function drawScrollBar(target:Sprite):void {
var g :Graphics = target.graphics;
var minHeight_:int = 20;
var height_ :Number = textField.height * (getShowNumLines(textField) / textField.numLines);
if(height_ > textField.height) {
height_ = textField.height;
}
else if(height_ < minHeight_) {
height_ = minHeight_;
}
g.clear();
g.beginFill(_enabledColor);
g.drawRoundRect(0, 0, 8, height_, 10, 10);
g.endFill();
}
/** スクロールバーの下地の外観を描画します。 */
protected function drawScrollBarBackground(target:Shape):void {
var g:Graphics = target.graphics;
g.clear();
g.beginFill(_enabledColor);
g.drawRect(0, 0, 0.5, textField.height);
g.endFill();
}
/** 指定ターゲットの色を指定カラーに変更します。 */
protected function hexToRGB(target:DisplayObject, v:uint):void {
var r:uint = (v >> 16) & 0xff;
var g:uint = (v >> 8) & 0xff;
var b:uint = v & 0xff;
target.transform.colorTransform = new ColorTransform(0, 0, 0, 1, r, g, b);
}
}
}
import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.SimpleButton;
import flash.geom.Matrix;
/**
* ResetButton クラスは SimpleButton のサブクラスです。
* サイズは固定です。外部からの編集はしません。
*/
class ResetButton extends SimpleButton {
/** upState の Shape です。 */
protected var upStateSkin :Shape;
/** overStateShape の Shape です。 */
protected var overStateSkin :Shape;
/** downState の Shape です。 */
protected var downStateSkin :Shape;
/** hitTestState の Shape です。 */
protected var hitTestStateSkin :Shape;
/**
* コンストラクタ
*/
public function ResetButton(upState:DisplayObject=null, overState:DisplayObject=null, downState:DisplayObject=null, hitTestState:DisplayObject=null) {
super(upState, overState, downState, hitTestState);
upStateSkin = new Shape();
overStateSkin = new Shape();
downStateSkin = new Shape();
hitTestStateSkin = new Shape();
super.upState = createShape(upStateSkin, [0x333333, 0x666666], [0xeeeeee, 0xcccccc], 0x000000);
super.overState = createShape(overStateSkin, [0x666666, 0x999999], [0xffffff, 0xdddddd], 0x666666);
super.downState = createShape(downStateSkin, [0x999999, 0x666666], [0xaaaaaa, 0x999999], 0x333333);
super.hitTestState = createHitTestShape(hitTestStateSkin);
super.hitTestState.x = 0;
super.hitTestState.y = 0;
super.useHandCursor = true;
}
/** コンポーネントの外観を作成します。 */
protected function createShape(target:Shape, backgroundColors:Array, fillColors:Array, arrowColor:uint):Shape {
const PI :Number = Math.PI;
var w :int = 60;
var h :int = 13;
var r :int = 10;
var g :Graphics = target.graphics;
var m :Matrix = new Matrix();
var rad :Number = PI / 180;
m.createGradientBox(w, h, PI / 2, 0, 0);
g.beginGradientFill(GradientType.LINEAR, backgroundColors, [100, 100], [0, 255], m);
g.drawRoundRect(0, 0, w, h, r, r);
g.endFill();
g.beginGradientFill(GradientType.LINEAR, fillColors, [100, 100], [0, 255], m);
g.drawRoundRect(1, 1, w - 2, h - 2, r - 1, r - 1);
g.endFill();
return target;
}
/** ボタン領域用表示オブジェクトを作成します。 */
protected function createHitTestShape(target:Shape):Shape {
var w :int = 60;
var h :int = 13;
var g :Graphics = target.graphics;
g.beginFill(0);
g.drawRect(0, 0, w, h);
g.endFill();
return target;
}
}