需求:
我之前做的电子表格和高级数据表格中 有这样的要求,用户可能在电子表格中任意的设置单元格样式(背景色,边框……)。如果每个单元格对象都持有自己的CellStyle,那么100*100的单元格矩阵就会创建10000个CellStyle对象,很可怕。 所以我希望样式是在样式池中,被各个单元格引用的方式。并且对于不用的样式要回收掉。
功能:
1,对表格不使用的样式 及时删除掉
2,维护一个样式池, 保证池中样式都是不同的,并且是被引用着的,否则从池中移除
做法:
首先 需要了解下flex的Dictionary类,这个类可以在key上使用弱引用(Dictionary(weakKeys:Boolean = false))
api描述是:weakKeys指示 Dictionary 对象在对象键上使用“弱”引用。如果对某个对象的唯一引用位于指定的 Dictionary 对象中,则键符合垃圾回收的条件,并且在回收对象时会被从表中删除。 使用Dictionary 的key作为样式的池 就可以完成功能1的需要。
代码如下:
自定义样式类
public class CellStyle {
private static var styleManager:GStyleManager = GStyleManager.initialize();
public static const DEFAULT_STYLE:CellStyle = new CellStyle();
public var stylename:String;
private static function getCellStyle(value:CellStyle):CellStyle{
var style:CellStyle = styleManager.getCellStyle(value);
if(style != null){
return style;
}
value.stylename = UIDUtil.createUID();
styleManager.addStyle(value);
return value;
}
/**
* 字体加粗
* @see FontStyleEnum
*/
public var fontWeight:String = FontStyleEnum.NORMAL;
/**
* 斜体
*/
public var fontStyle:String = FontStyleEnum.NORMAL;
/**
* 下划线
* @default
*/
public var textDecoration:String = FontStyleEnum.NONE;
/**
* 字体类型
* @default
*/
public var fontFamily:String = "simsun";
/**
* 字体颜色
*/
public var fontColor:String = "#000000";
/**
* 字体大小
*/
public var fontSize:Number = 12;
//文字样式结束///
/**
* 上边框类型
* @default
*/
public var borderTypeTop:String = CellOp.SOLID;
/**
* 左边框类型
* @default
*/
public var borderTypeLeft:String = CellOp.SOLID;
/**
* 右边框类型
* @default
*/
public var borderTypeRight:String = CellOp.SOLID;
/**
* 下边框类型
* @default
*/
public var borderTypeBottom:String = CellOp.SOLID;
/**
* 边框类型
* @default
*/
public function set borderType(value:String):void{
borderTypeTop = value;
borderTypeLeft = value;
borderTypeRight = value;
borderTypeBottom = value;
}
//边框类型结束///
/**
* 上边框粗细
*/
public var borderThicknessTop:int = 0;
/**
* 左边框粗细
*/
public var borderThicknessLeft:int = 0;
/**
* 右边框粗细
*/
public var borderThicknessRight:int = 0;
/**
* 下边框粗细
*/
public var borderThicknessBottom:int = 0;
public function set borderThickness(value:Number):void{
this.borderThicknessBottom = value;
this.borderThicknessLeft = value;
this.borderThicknessRight = value;
this.borderThicknessTop = value;
}
//边框粗细结束///
// /**
// * 上边框透明度
// * @default
// */
// public var borderAlphaTop:Number = 0;
// /**
// * 下边框透明度
// * @default
// */
// public var borderAlphaBottom:Number = 0;
// /**
// * 左边框透明度
// * @default
// */
// public var borderAlphaLeft:Number = 0;
// /**
// * 有边框透明度
// * @default
// */
// public var borderAlphaRight:Number = 0;
///边框透明度 结束/
/**
* 格式化 方式
* @default
*/
public var formatString:String = "";
/**
* 上边框颜色
*/
public var borderColorTop:String = "#000000";
/**
* 右边框颜色
* @default
*/
public var borderColorRight:String = "#000000";
/**
* 左边框颜色
* @default
*/
public var borderColorLeft:String = "#000000";
/**
* 下边框颜色
* @default
*/
public var borderColorBottom:String = "#000000";
/**
* 边框颜色
* @param param1
*/
public function set borderColor(param1:String) : void
{
borderColorTop = param1;
borderColorBottom = param1;
borderColorRight = param1;
borderColorLeft = param1;
return;
}
///边框颜色 结束/
/** 横向排列 */
public var horizontalAlign:Number = 0;
/**
* 纵向排列
*/
public var verticalAlign:Number = 0.5;
///对齐方式 结束/
/**
* 背景起始色
* @default
*/
public var backColor:String = "";
/**
* 透明度
*/
public var backAlpha:Number = 0;
///背景色 结束/
/**
* 右内边距
*/
public var padding_right:int = 1;
/**
* 上内边距
*/
public var padding_top:int = 1;
/**
* 下内边距
*/
public var padding_bottom:int = 1;
/**
* 左内边距
*/
public var padding_left:int = 1;
/内边距 结束//
/**
* 是否换行
*/
public var textStyle:Boolean = false;
/**
*
* @param param1
*/
public function CellStyle(styleName:String = null)
{
styleName = UIDUtil.createUID()
}
/**
* 复制样式
* @param param1
*/
public function clone(param1:CellStyle) : CellStyle
{
this.formatString = param1.formatString;
this.backColor = param1.backColor;
this.backAlpha = param1.backAlpha;
this.borderColorBottom = param1.borderColorBottom;
this.borderColorLeft = param1.borderColorLeft;
this.borderColorRight = param1.borderColorRight;
this.borderColorTop = param1.borderColorTop;
this.borderThicknessTop = param1.borderThicknessTop;
this.borderThicknessBottom = param1.borderThicknessBottom;
this.borderThicknessLeft = param1.borderThicknessLeft;
this.borderThicknessRight = param1.borderThicknessRight;
// this.borderAlphaBottom = param1.borderAlphaBottom;
// this.borderAlphaTop = param1.borderAlphaTop;
// this.borderAlphaLeft = param1.borderAlphaLeft;
// this.borderAlphaRight = param1.borderAlphaRight;
this.borderTypeTop = param1.borderTypeTop;
this.borderTypeBottom = param1.borderTypeBottom;
this.borderTypeRight = param1.borderTypeRight;
this.borderTypeLeft = param1.borderTypeLeft;
this.padding_bottom = param1.padding_bottom;
this.padding_left = param1.padding_left;
this.padding_right = param1.padding_right;
this.padding_top = param1.padding_top;
this.fontColor = param1.fontColor;
this.fontSize = param1.fontSize;
this.fontWeight = param1.fontWeight;
this.fontStyle = param1.fontStyle;
this.textDecoration = param1.textDecoration;
this.fontFamily = param1.fontFamily;
this.horizontalAlign = param1.horizontalAlign;
this.verticalAlign = param1.verticalAlign;
this.textStyle = param1.textStyle;
return this;
}
public function equals(style:CellStyle):Boolean{
if(fontWeight == style.fontWeight && fontStyle == style.fontStyle && textDecoration == style.textDecoration
&& fontFamily == style.fontFamily && fontColor == style.fontColor && fontSize == style.fontSize
&& borderTypeBottom == style.borderTypeBottom && borderTypeTop == style.borderTypeTop
&& borderTypeLeft == style.borderTypeLeft && borderTypeRight == style.borderTypeRight
&& borderThicknessBottom == style.borderThicknessBottom && borderThicknessLeft == style.borderThicknessLeft
&& borderThicknessRight == style.borderThicknessRight && borderThicknessTop == style.borderThicknessTop
&& formatString == style.formatString && borderColorBottom == style.borderColorBottom && borderColorLeft == style.borderColorLeft
&& borderColorRight == style.borderColorRight && borderColorTop == style.borderColorTop
&& horizontalAlign == style.horizontalAlign && verticalAlign == style.verticalAlign
&& backColor == style.backColor && backAlpha == style.backAlpha
&& padding_bottom == style.padding_bottom && padding_left == style.padding_left
&& padding_right == style.padding_right && padding_top == style.padding_top
&& textStyle == style.textStyle){
return true;
}
return false;
}
public function setProperty(name:String, value:*):CellStyle{
var cellStyle:CellStyle = new CellStyle();
cellStyle.clone(this);
cellStyle[name] = value;
return getCellStyle(cellStyle);
}
}
}
对样式的修改需要调用setProperty方法 而不是直接修改属性,setProperty方法会在修改表样式的时候判断池中是否存在这样的样式,存在就返回,不存在创建一个放在池中在返回。 这样就解决了功能2的需要
样式管理类
public class GStyleManager
{
private var gridCellStyle:Dictionary;
private static var gstyleManager:GStyleManager;
private const styleCach:Array = new Array();
/**
* 记录单元格需要填充的样式map
*/
private var fillMap:Dictionary = new Dictionary();
function GStyleManager()
{
//初始化表格的默认样式
gridCellStyle = new Dictionary(true);
}
/**
* 初始化GStyleManager对象
*/
public static function initialize():GStyleManager{
if(!gstyleManager){
gstyleManager = new GStyleManager();
}
return gstyleManager;
}
/**
* 通过样式名,取得对应的样式对象,
* 如果没有指定样式,可以指定返回默认样式。
* @param name:String 样式名称
* @param useDefault:Boolean 如果没有name对应的样式,是否返回默认样式
* @return 样式对象CellStyle
*/
public function getStyleByName(name:String, useDefault:Boolean = true) : CellStyle
{
for(var k:* in gridCellStyle){
var styleName:String = gridCellStyle[k] as String;
if(name == styleName){
return k as CellStyle;
}
}
if(useDefault){
return CellStyle.DEFAULT_STYLE;
}
return null;
}
/**
* 添加style
*/
public function addStyle(style:CellStyle):void{
if(style != null){
gridCellStyle[style] = style.stylename;
}
}
/**
* 是否存在该样式
*/
private function hasStyle(styleName:String):Boolean{
var cellStyle:CellStyle = gridCellStyle[styleName] as CellStyle;;
if(cellStyle != null){
return true;
}
return false;
}
public function getCellStyle(style:CellStyle):CellStyle{
var cellStyle:CellStyle = null;
for(var cs:* in gridCellStyle){
cellStyle = CellStyle(cs);
if(cellStyle.equals(style)){
return cellStyle;
}
}
return null;
}
public function addFillMap(styleName:String, cell:Cell):void{
var cells:Vector. = fillMap[styleName];
if(cells == null){
cells = new Vector.;
fillMap[styleName] = cells;
}
cells.push(cell);
}
}
| |
6个单元格设置了背景色 但又2个是相同的,因此池中维护4个而不是6个 :)