googleで
カスタム検索
プロフィール

けろ&ひな

Author:けろ&ひな
大阪在住。
親ばか。
最近、転職したよ。でも、やってることは一緒なんだけどね。;-P

最近の記事
カテゴリー
月別アーカイブ
最近のコメント
最近のトラックバック
スポンサード リンク

スポンサーサイト--------(--)

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Flex][as3]datagridのヘッダセルを疑似的に連結してみる2009-12-25(Fri)

datagrid
仕事でやる必要がでてきたので、DataGridとDataGridHeaderを拡張して作ってみた。
(Flex Builder3 (Flex SDK 3.3)です。)

最初はセルを結合できたらと思ったんですけど手段がわからず。。。

仕方ないので、ヘッダのセル間に表示される「|」をプロパティかスタイルで消せるなら
と思ったけど方法が見つけられず。。。orz

ということで、DataGridのソースを眺めてたらDataGridHeaderクラスでヘッダを作ってる
みたいだったので、そのDataGridHeaderを拡張して「|」を消すことにしました。
ただ、そのHeaderクラスの指定がmx_internalの名前空間になってるので将来は変更されるのかなぁと。

ほんとはヘッダのタイトルにあたるテキストを中央に表示していたんですけど
そうすると、ヘッダにクリックイベントを付けてるとフリーズというか
updateDisplayListが無限ループにハマってしまうので、横に寄せました。
(画像ではソート機能を殺してテキストを中央に持って行ってます。)

ヘッダのテキストとセルを囲っている枠線はheaderRnedererで書いてます。
で、ヘッダテキストを中央に表示しようとした場合、
このheaderRendererでヘッダセルを広げないとテキストがキチンと表示されない。
でも、rendererで広げてしまうと、そこからまたupdateDisplayListが実行されて
無限に。。。

ヘッダテキストの書き出しをcreateChildrenに持っていき
幅の変更をsetActualSize()で行うことでテキストを中央に持って行けました。(2009/12/29修正)

ちなみに、ヘッダの幅とかはdataGridColumnのプロパティから取得しています。
でも、ヘッダドラッグして位置を動かすとグチャグチャになっちゃいます。

test.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:datagrid="datagrid.*" viewSourceURL="srcview/index.html">

<mx:Style source="style.css" />
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;

[]
protected var gridData:ArrayCollection = new ArrayCollection(
[
{header11:"2009/12/20", header21:"あいうえお", header22:"アイウエオ", header31:"qwert", header32:"QWERT", header33:"こんにちわ", header41:"hello"},
{header11:"2009/12/21", header21:"かきくけこ", header22:"カキクケコ", header31:"asdfg", header32:"ASDFG", header33:"こんばんわ", header41:"hello"},
{header11:"2009/12/22", header21:"さしすせそ", header22:"サシスセソ", header31:"zxcvb", header32:"ZXCVB", header33:"おつかれさま", header41:"hello"},

]);

]]>
</mx:Script>

<datagrid:NoHeaderSeparatorDataGrid id="grid" top="110" left="5" right="5" height="400" width="967"
dataProvider="
{gridData}"
headerHeight="
140" styleName="gridType1" headerStyleName="gridHeader"
sortableColumns="
true" draggableColumns="false" resizableColumns="true"
horizontalScrollPolicy="
on" verticalScrollPolicy="on">
<datagrid:columns>
<mx:DataGridColumn width="200" dataField="header11" headerText="日付"
headerRenderer="
renderer.GridHeaderRenderer" />
<mx:DataGridColumn width="200" dataField="header21" headerText="ひらがな"
headerRenderer="
renderer.GridHeaderRenderer" />
<mx:DataGridColumn width="200" dataField="header22" headerText="カタカナ"
headerRenderer="
renderer.GridHeaderRenderer" />
<mx:DataGridColumn width="200" dataField="header31" headerText="アルファベット(小文字)"
headerRenderer="
renderer.GridHeaderRenderer" />
<mx:DataGridColumn width="200" dataField="header32" headerText="アルファベット(大文字)"
headerRenderer="
renderer.GridHeaderRenderer" />
<mx:DataGridColumn width="200" dataField="header33" headerText="日本語挨拶"
headerRenderer="
renderer.GridHeaderRenderer" />
<mx:DataGridColumn width="200" dataField="header41" headerText="とりあえずHello"
headerRenderer="
renderer.GridHeaderRenderer" />
</datagrid:columns>
</datagrid:NoHeaderSeparatorDataGrid>
</mx:Application>


style.css
global {
fontColor: #000000;
fontFamily: MSG;
fontSize: 24;
}

DataGrid.gridType1, DataGrid.gridType2, DataGrid.gridType3{
alternatingItemColors: #FFFFFF, #FFFFFF;
color: #000000;
headerColors: #FFFFDD, #E8E09D;
horizontalGridLineColor: #CCCCCC;
horizontalGridLines: true;
rollOverColor: #FFFFFF;
selectionColor: #FFCC33;
textSelectedColor: #000000;
useRollOver: false;
verticalAlign: middle;
verticalGridLines: true;
}

.gridHeader {
backgroundAlpha: 0.0;
backgroundColor: undefined;
borderStyle: none;
color: #000000;
fontSize: 20;
headerHeight: 30;
textAlign: center;
}



NoHeaderSeparatorDataGrid.as
package datagrid
{
import mx.controls.DataGrid;
import mx.core.mx_internal;
use namespace mx_internal;

public class NoHeaderSeparatorDataGrid extends DataGrid
{
public function NoHeaderSeparatorDataGrid()
{
super();

// Headerクラスを上書きする
mx_internal::headerClass = NoSeparatorDataGridHeader;
}

}
}



NoSeparatorDataGridHeader.as
package datagrid
{
import mx.controls.dataGridClasses.DataGridHeader;
import mx.core.IFlexDisplayObject;
import mx.core.mx_internal;

use namespace mx_internal;
public class NoSeparatorDataGridHeader extends DataGridHeader
{
public function NoSeparatorDataGridHeader()
{
super();
}

/**
* セパレータの描画処理をOverrideしてセパレータを表示しない
*/

override protected function drawSeparators():void
{
super.drawSeparators();

// セパレータをすべて非表示にする
var separators:Array = mx_internal::getSeparators();
if (!separators)
return;
for (var i:Number = 0; i<separators.length; i++)
{
separators[i].alpha = 0;
}
}
}
}


んで、HeaderRendererはこちら。

GridHeaderRenderer.as
package renderer
{
import flash.display.GradientType;
import flash.geom.Matrix;

import mx.containers.Canvas;
import mx.controls.DataGrid;
import mx.controls.TextArea;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.controls.listClasses.BaseListData;
import mx.controls.listClasses.IDropInListItemRenderer;

public class GridHeaderRenderer extends Canvas implements IDropInListItemRenderer
{
protected const HEAD_TOP:Number = -3;
protected const COL_TOP_1:Number = -3;
protected const COL_TOP_2:Number = 35;
protected const COL_TOP_3:Number = 70;
private var _listData:BaseListData;
public function get listData():BaseListData
{
return _listData;
}
public function set listData(value:BaseListData):void
{
_listData = value;
}


private var _data:Object;
override public function get data():Object
{
return _data;
}
override public function set data(value:Object):void
{
_data = value;
super.data = value;
}

protected var textTitle:TextArea;
protected var textDetail:TextArea;

// ヘッダの各項目ごとのWidth
protected var headersWidth:Object;

public function GridHeaderRenderer()
{
super();

headersWidth = null;

this.verticalScrollPolicy = "off";
this.horizontalScrollPolicy = "off";
invalidateDisplayList();

}

override protected function createChildren():void
{
super.createChildren();

textTitle = new TextArea();
textDetail = new TextArea();
initializeTextArea(textTitle);
initializeTextArea(textDetail);
this.addChild(textTitle);
this.addChild(textDetail);

}

protected function initializeTextArea(area:TextArea):void
{
area.wordWrap = true;
area.selectable = false;
area.editable = false;
}

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);

if (!_listData)
return;

var ownerGrid:Object = _listData.owner;

// ヘッダの書き換え
if (ownerGrid is DataGrid && _listData.hasOwnProperty("dataField")) {

//headersWidthにヘッダの幅をdataFieldをキーにしたマップを初回のみ作成
if (!headersWidth) {
headersWidth = new Object();
var grid:DataGrid = DataGrid(ownerGrid);
for (var i:Number = 0; i < grid.columnCount; i++) {
var col:DataGridColumn = DataGridColumn(grid.columns[i]);
headersWidth[col.dataField] = col.width;
}
}

var gridStyleName:String = (ownerGrid as DataGrid).styleName.toString();
var filedName:String = _listData["dataField"];

//ヘッダの描画
drawHeader(unscaledWidth, unscaledHeight, gridStyleName, filedName);
}
}

protected function drawHeader(wid:Number, hi:Number, type:String, fieldName:String):void
{
// フィールド名とスタイル名によってヘッダの形状を変化させる
var ownerGrid:DataGrid = (_listData.owner as DataGrid)
var colors:Array = ownerGrid.getStyle("headerColors") as Array;
var lineColor:Number = Number(ownerGrid.getStyle("verticalGridLineColor"));
var column:DataGridColumn = DataGridColumn(_data);
var headerStyleName:String = ownerGrid.getStyle("headerStyleName").toString();
var wid:Number;
switch (fieldName)
{
//ヘッダ外枠に表示するテキストと枠線のみをここで設定
case "header11":
createSquere(0, HEAD_TOP, column.width, ownerGrid.headerHeight, colors, [1, 1],lineColor);
setHeadTitle("", headerStyleName);
break;
case "header21":
wid = headersWidth["header21"]+headersWidth["header22"];
createSquere(0, HEAD_TOP, wid, ownerGrid.headerHeight, colors, [1, 1], lineColor);
setActualSize(wid, ownerGrid.headerHeight);
setHeadTitle("header21", headerStyleName, wid);
break;
case "header31":
wid = headersWidth["header31"]+headersWidth["header32"]+headersWidth["header33"];
createSquere(0, HEAD_TOP, wid, ownerGrid.headerHeight, colors, [1, 1], lineColor);
setActualSize(wid, ownerGrid.headerHeight);
setHeadTitle("header31", headerStyleName, wid);
break;
case "header32":
wid = headersWidth["header32"]+headersWidth["header33"];
createSquere(0, COL_TOP_2, wid, ownerGrid.headerHeight, colors, [1, 1], lineColor);
setActualSize(wid, ownerGrid.headerHeight);
setHeadTitle("header32", headerStyleName, wid, COL_TOP_2+5);
break;
case "header41":
createSquere(0, HEAD_TOP, column.width, ownerGrid.headerHeight, colors, [1, 1],lineColor);
default:
//ヘッダの内枠には外枠用のテキストを表示しない
setHeadTitle("", headerStyleName);
break;
}
setHeadDetail(column.headerText, headerStyleName, column.width);

}

/**
* ヘッダセルの外枠
*
* @param txt 外枠ヘッダのテキスト
* @param stylename 外枠ヘッダテキストのスタイル名
* @param textWidth 外枠ヘッダテキストの幅
* @param ty 外枠ヘッダテキストのy位置
* */

protected function setHeadTitle(txt:String, stylename:String, textWidth:Number = 0, ty:Number = 10):void
{
setHeaderTextArea(textTitle, txt, stylename, textWidth, ty);
}

/**
* ヘッダセルの内枠
*
* @param txt ヘッダのテキスト
* @param stylename ヘッダテキストのスタイル名
* @param textWidth ヘッダテキストの幅
* */

protected function setHeadDetail(txt:String, stylename:String, textWidth:Number = 0):void
{
// テキストをヘッダの下付けにする
setHeaderTextArea(textDetail, txt, stylename, textWidth);
textDetail.validateDisplayList();
textDetail.y = this.height - textDetail.textHeight - 5;
}

/**
* ヘッダセルテキストの設定
*
* @param textArea ヘッダのテキストエリア
* @param txt ヘッダのテキスト
* @param stylename ヘッダテキストエリアのスタイル名
* @param textWidth ヘッダテキストエリアの幅
* @param ty ヘッダテキストエリアのy位置
* */

protected function setHeaderTextArea(textArea:TextArea, txt:String, stylename:String, textWidth:Number = 0, ty:Number = 10):void
{
textArea.text = txt;
// textArea.width = textWidth;
// //カッコ記号などの場合にfontによってtextWidthとwidthとで差がでて、改行が描画後に起こるので若干を追加
// textArea.height = textArea.textHeight + 5;
textArea.x = 1;
textArea.y = ty;
if (stylename)
textArea.styleName = stylename;
textArea.setActualSize(textWidth, this.height - ty);
}


/**
* ヘッダに四角の枠を作って背景色にグラデーションをかける
*
* @param x0 x開始点
* @param y0 y開始点
* @param x1 x終了点
* @param y1 y終了点
* @param colors グラデーションの色配列
* @param alphas グラデーションのアルファ配列
* @param lineColor 枠線の色
* @param topLine 枠の上線を描画 (default:true)
* @param rightLine 枠の右線を描画 (default:true)
* @param bottomLine 枠の下線を描画 (default:true)
* @param leftLine 枠の左線を描画 (default:true)
*
* */

protected function createSquere(x0:Number, y0:Number, x1:Number, y1:Number, colors:Array, alphas:Array, lineColor:Number,
topLine:Boolean = true, rightLine:Boolean = true, bottomLine:Boolean = true, leftLine:Boolean = true):void
{
y1 = y1 + HEAD_TOP;
var matrix:Matrix = new Matrix();
matrix.createGradientBox(x1, y1, Math.PI / 2, 0, 0);
graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, [0, 255], matrix);
graphics.moveTo(x0, y0);
setLineStyle(topLine, lineColor);
graphics.lineTo(x1, y0);
setLineStyle(rightLine, lineColor);
graphics.lineTo(x1, y1);
setLineStyle(bottomLine, lineColor);
graphics.lineTo(x0, y1);
setLineStyle(leftLine, lineColor);
graphics.lineTo(x0, y0);
graphics.endFill();
}

/**
* 線のスタイル設定
*
* @param isDraw 線を表示するか
* @param lineColor 線の色
* */

protected function setLineStyle(isDraw:Boolean, lineColor:Number):void
{
if (isDraw)
graphics.lineStyle(1, lineColor);
else
graphics.lineStyle(1, 0, 0);
}


}
}


もっと簡単にできないかなぁ。。。
2009/12/28 追記:
NoSeparaotrDataGridHeader.as の

separators[i].visible=false;


separators[i].alpha=0;
に変更してセルのリサイズにも対応できた。
関連記事

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

管理者にだけ表示を許可する

コメント

工事中
RSSフィード
リンク

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。