PageRenderTime 59ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/org/mousebomb/ui/DatePicker.as

https://github.com/mousebomb/mousebomb_as3lib
ActionScript | 621 lines | 456 code | 68 blank | 97 comment | 66 complexity | 147eab4dc649c692fad52833c3a80f3f MD5 | raw file
  1. package org.mousebomb.ui
  2. {
  3. import flash.display.DisplayObject;
  4. import flash.display.GradientType;
  5. import flash.display.SpreadMethod;
  6. import flash.display.Sprite;
  7. import flash.events.Event;
  8. import flash.events.MouseEvent;
  9. import flash.filters.BitmapFilter;
  10. import flash.filters.BitmapFilterQuality;
  11. import flash.filters.DropShadowFilter;
  12. import flash.filters.GlowFilter;
  13. import flash.geom.Matrix;
  14. import flash.text.TextField;
  15. import flash.text.TextFieldAutoSize;
  16. import flash.text.TextFormat;
  17. import flash.text.TextFormatAlign;
  18. [Event(name="select", type="flash.events.Event")] [Event(name="scroll", type="flash.events.Event")]
  19. /**
  20. * @author Mousebomb ()
  21. * @date 2009-12-30
  22. */
  23. public class DatePicker extends Sprite
  24. {
  25. private var _dayNames : Array = ["日","一", "二", "三", "四", "五", "六"];
  26. private var _disabledDays : Array = [];
  27. private var _firstDayOfWeek : uint = 1;
  28. private var _monthNames : Array = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月","十一月", "十二月"];
  29. private var _showToday : Boolean; private var _selectableRangeStart : Date = new Date(1900, 0, 1);
  30. private var _selectableRangeEnd : Date = new Date(2999, 11, 31);
  31. private var _selectedDate : Date = new Date(); //选中的Date,默认是今天,可能和显示的月份不同
  32. private var _todayDate : Date = new Date(); //指示今天
  33. private var daysMonthArray : Array = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  34. private var mCount : Number;
  35. private var yCount : Number;
  36. //是否允许滚动
  37. private var _disallowPrev:Boolean; private var _disallowNext:Boolean;
  38. //是否已初始化
  39. private var _inited : Boolean;
  40. //display:
  41. private var board : Sprite;
  42. private var nextBtn : Sprite;
  43. private var dayRow : Sprite;
  44. private var prevBtn : Sprite;
  45. private var calendar : Sprite;
  46. private var monthTf : TextField;
  47. private var gridCont : Sprite;
  48. //样式
  49. protected var _tfmDayNameRow : TextFormat;
  50. protected var _tfmMonth : TextFormat ;
  51. protected var _tfmSelectedDay : TextFormat ;
  52. protected var _tfmGrid : TextFormat ; protected var _tfmDisabledDay : TextFormat ; protected var _tfmToday : TextFormat ;
  53. public var bgColorDayNameRow : uint = 0x000000; public var bgColorSelectedDay : uint = 0x651212; public var bgColorGrid : uint = 0x000000; public var bgColorDisabled : uint = 0x000000; public var bgColorToday : uint = 0x000000; public var arrowColor : uint = 0xcccccc;
  54. /**
  55. * @param autoInit 是否自动初始化,设置为true的话则被AddedToStage的时候初始化
  56. */
  57. public function DatePicker(autoInit : Boolean = true)
  58. {
  59. _tfmDayNameRow = defaultTxtFormat("dayNameRow");
  60. _tfmMonth = defaultTxtFormat("month"); _tfmSelectedDay = defaultTxtFormat("selectedDay"); _tfmGrid = defaultTxtFormat("dateGrid"); _tfmDisabledDay = defaultTxtFormat("tfmDisabledDay");
  61. _tfmToday = defaultTxtFormat("tfmToday");
  62. if(autoInit)
  63. {
  64. addEventListener(Event.ADDED_TO_STAGE, onAdd2StageInit);
  65. }
  66. }
  67. private function defaultTxtFormat(str : String) : TextFormat
  68. {
  69. var fmt : TextFormat = new TextFormat("Arial", 12, 0xffffff);
  70. if(str == "dateGrid")
  71. {
  72. fmt.align = TextFormatAlign.RIGHT;
  73. fmt.italic = true;
  74. }
  75. if(str == "dayNameRow")
  76. {
  77. fmt.bold = true;
  78. fmt.align = TextFormatAlign.RIGHT;
  79. }
  80. if(str == "selectedDay")
  81. {
  82. fmt.align = TextFormatAlign.RIGHT;
  83. fmt.bold = true;
  84. }
  85. if(str == "tfmDisabledDay")
  86. {
  87. fmt.align = TextFormatAlign.RIGHT;
  88. fmt.italic = true;
  89. fmt.color = 0x999999;
  90. }
  91. if(str == "tfmToday")
  92. {
  93. fmt.align = TextFormatAlign.RIGHT;
  94. //fmt.italic = true;
  95. fmt.underline = true;
  96. fmt.color = 0xffffff;
  97. }
  98. return fmt;
  99. }
  100. private function onAdd2StageInit(event : Event) : void
  101. {
  102. init();
  103. removeEventListener(Event.ADDED_TO_STAGE, onAdd2StageInit);
  104. }
  105. public function init() : void
  106. {
  107. if(_inited) return;
  108. //
  109. board = this.addChild(drawRadialBackground(240, 175)) as Sprite;
  110. nextBtn = this.addChild(drawArrow(this.width - 25, 12, 0)) as Sprite;
  111. nextBtn.buttonMode = true;
  112. nextBtn.addEventListener(MouseEvent.CLICK, onNextClick);
  113. nextBtn.addEventListener(MouseEvent.MOUSE_OVER, onOver);
  114. nextBtn.addEventListener(MouseEvent.MOUSE_OUT, onOut);
  115. prevBtn = this.addChild(drawArrow(25, 12, 180)) as Sprite;
  116. prevBtn.buttonMode = true;
  117. prevBtn.addEventListener(MouseEvent.CLICK, onPrevClick);
  118. prevBtn.addEventListener(MouseEvent.MOUSE_OVER, onOver);
  119. prevBtn.addEventListener(MouseEvent.MOUSE_OUT, onOut);
  120. dayRow = this.addChild(drawDayNameRow(5, 25)) as Sprite;
  121. //**初始化日历动态部分
  122. calendar = new Sprite();
  123. calendar.x = 5;
  124. this.addChild(calendar);
  125. //**年、月显示
  126. monthTf = new TextField();
  127. monthTf.autoSize = TextFieldAutoSize.CENTER;
  128. monthTf.y = 5;
  129. monthTf.x = (this.width / 2) - (monthTf.width / 2);
  130. monthTf.setTextFormat(_tfmMonth);
  131. calendar.addChild(monthTf);
  132. //日历动态容器
  133. gridCont = new Sprite();
  134. calendar.addChild(gridCont);
  135. //**日历动态部分绘制
  136. drawDateGrid(_selectedDate.getMonth(), _selectedDate.getFullYear());
  137. //
  138. _inited = true;
  139. }
  140. private function onNextClick(e : MouseEvent) : void
  141. {
  142. //**只有当上个月有可选内容时才能滚动
  143. if(_disallowNext)
  144. {
  145. return;
  146. }
  147. //**
  148. clearDateGrid(); // remove current DateGrid-Sprite
  149. if(mCount == 11)
  150. {
  151. // if month == 11 (December)
  152. mCount = 0; // set month to 0 (January)
  153. yCount++; // and increase the year counter by 1
  154. }
  155. else
  156. {
  157. mCount++; // else increase month counter by 1
  158. }
  159. drawDateGrid(mCount, yCount); // make DateGrid-Sprite for the next month
  160. dispatchEvent(new Event(Event.SCROLL));
  161. }
  162. private function onPrevClick(e : MouseEvent) : void
  163. {
  164. //**只有当上个月有可选内容时才能滚动
  165. if(_disallowPrev)
  166. {
  167. return;
  168. }
  169. //**
  170. clearDateGrid();
  171. if(mCount == 0)
  172. {
  173. // if month == 0 (January)
  174. mCount = 11; // set month to 11 (December)
  175. yCount--; // and decrease the year counter by 1
  176. }
  177. else
  178. {
  179. mCount--; // else decrease month counter by 1
  180. }
  181. drawDateGrid(mCount, yCount); // make DateGrid-Sprite for the previous month
  182. dispatchEvent(new Event(Event.SCROLL));
  183. }
  184. private function onOver(e : MouseEvent) : void
  185. {
  186. e.target["alpha"] = 0.6;
  187. }
  188. private function onOut(e : MouseEvent) : void
  189. {
  190. e.target["alpha"] = 1;
  191. }
  192. /**
  193. * 产生表头行
  194. * 显示周一到周日
  195. */
  196. private function drawDayNameRow(tx : Number,ty : Number) : Sprite
  197. {
  198. var cont : Sprite = new Sprite();
  199. cont.x = tx;
  200. cont.y = ty;
  201. cont.addChild(drawRoundRect(this.width - 15, 22, bgColorDayNameRow, .8));
  202. //一周的七天
  203. for( var i : int = 0;i < 7;i++)
  204. {
  205. var dayTf : TextField = new TextField();
  206. dayTf.text = dayNames[(i + firstDayOfWeek) % 7];
  207. dayTf.width = 30;
  208. dayTf.height = 20;
  209. dayTf.selectable = false;
  210. dayTf.y = 3;
  211. dayTf.x = i * 32;
  212. dayTf.setTextFormat(_tfmDayNameRow);
  213. cont.addChild(dayTf);
  214. }
  215. return cont;
  216. }
  217. /**
  218. * 画一个圆角矩形,返回Sprite
  219. */
  220. private function drawRoundRect(w : Number,h : Number,col : uint, alph : Number) : Sprite
  221. {
  222. // creates a simple rect with a color-fill
  223. var s : Sprite = new Sprite();
  224. s.graphics.beginFill(col, alph);
  225. s.graphics.drawRoundRect(0, 0, w, h, 10);
  226. s.graphics.endFill();
  227. return s;
  228. }
  229. private function drawDateGrid(mm : Number, yy : Number) : void
  230. {
  231. //**年、月显示
  232. monthTf.text = monthNames[mm] + " - " + yy;
  233. monthTf.setTextFormat(_tfmMonth);
  234. //**日期行
  235. //每四年二月闰年
  236. var daysNr : int = (yy % 4 == 0 && mm == 1) ? 29 : daysMonthArray[mm];
  237. var myDate : Date = new Date(yy, mm, 1);
  238. // dayNameNr 用来确定该月第一天在第几格
  239. var dayNameNr : int = (myDate.getDay() - firstDayOfWeek) ;
  240. // 今天是星期几 0:周日 1~6
  241. var curDay : int = myDate.getDay();
  242. while(dayNameNr < 0 )
  243. {
  244. dayNameNr += 7;
  245. }
  246. var row : int = 1;
  247. var disabled : Boolean;
  248. for(var i : int = 1;i <= daysNr;i++)
  249. {
  250. if(dayNameNr == 0 && i != 1) row++; // 换行
  251. //**为格式化做准备
  252. //判定当前日期是否属于范围(selectableRange)
  253. if(myDate.valueOf() >= _selectableRangeStart.valueOf() && myDate.valueOf() <= _selectableRangeEnd.valueOf())
  254. {
  255. //判定当前创建的日是否被禁用(disabledDays)
  256. disabled = _disabledDays.indexOf(curDay) != -1;
  257. }
  258. else
  259. {
  260. disabled = true;
  261. }
  262. //是否当前渲染的日期是今天
  263. var isCurToday : Boolean = (_showToday && _todayDate.getDate() == i && _todayDate.getMonth() == mm && _todayDate.fullYear == yy);
  264. //是否当前渲染的日期是选中状态
  265. var isCurSelected : Boolean = (_selectedDate.fullYear == yy && _selectedDate.getMonth() == mm && _selectedDate.getDate() == i);
  266. //** 每个日期数字
  267. var gridItem : Sprite = new Sprite();
  268. gridItem.name = i + "." + (mm) + "." + yy;
  269. gridItem.x = dayNameNr * 32;
  270. gridItem.y = row * 20 + 30;
  271. gridItem.mouseChildren = false;
  272. if(!disabled)
  273. {
  274. gridItem.buttonMode = true;
  275. gridItem.addEventListener(MouseEvent.CLICK, onDateClick);
  276. gridItem.addEventListener(MouseEvent.MOUSE_OVER, onOver);
  277. gridItem.addEventListener(MouseEvent.MOUSE_OUT, onOut);
  278. }
  279. //** 每个日期数字的背景
  280. var bgrColor : uint = bgColorGrid;
  281. var bgrAlpha : Number = .6;
  282. if(disabled)
  283. {
  284. //不可选 已禁用
  285. bgrColor = bgColorDisabled;
  286. }else if(isCurSelected)
  287. {
  288. //选中高亮
  289. bgrColor = bgColorSelectedDay;
  290. bgrAlpha = 1;
  291. } else if(isCurToday)
  292. {
  293. //今日高亮
  294. bgrColor = bgColorToday;
  295. bgrAlpha = .6;
  296. }
  297. else
  298. {
  299. //普通日期数字
  300. bgrAlpha = .6;
  301. }
  302. var gridItemBg : Sprite = drawRoundRect(27, 18, bgrColor, bgrAlpha);
  303. gridItemBg.x = 3;
  304. gridItem.addChild(gridItemBg);
  305. //** 每个日期数字的文本
  306. var gridItemTf : TextField = new TextField();
  307. gridItemTf.width = 28;
  308. gridItemTf.height = 20;
  309. gridItemTf.text = String(i);
  310. gridItemTf.selectable = false;
  311. //格式化字体
  312. if(disabled)
  313. {
  314. //禁用
  315. gridItemTf.setTextFormat(_tfmDisabledDay);
  316. }else if(isCurSelected)
  317. {
  318. //选中高亮
  319. gridItemTf.setTextFormat(_tfmSelectedDay) ;
  320. }else if(isCurToday)
  321. {
  322. //今日
  323. gridItemTf.setTextFormat(_tfmToday);
  324. }
  325. else
  326. {
  327. gridItemTf.setTextFormat(_tfmGrid);
  328. }
  329. gridCont.addChild(gridItem);
  330. gridItem.addChild(gridItemTf);
  331. //维护今天星期几
  332. dayNameNr == 6 ? dayNameNr = 0 : dayNameNr++;
  333. curDay == 6 ? curDay = 0 : curDay++;
  334. myDate.date++;
  335. }
  336. //**记下当前年月
  337. mCount = mm;
  338. yCount = yy;
  339. //**记下是否允许翻到下个月(根据选择范围)
  340. _disallowPrev = (selectableRangeStart.valueOf() >= new Date(yCount, mCount,1).valueOf());
  341. _disallowNext = (selectableRangeEnd.valueOf() <= myDate.valueOf()); //此时myDate是这个月月底
  342. }
  343. private function clearDateGrid() : void
  344. {
  345. var len : int = gridCont.numChildren;
  346. for(var i : int = len - 1 ;i >= 0;--i)
  347. {
  348. var gridItem : Sprite = gridCont.getChildAt(i) as Sprite;
  349. gridItem.removeEventListener(MouseEvent.CLICK, onDateClick);
  350. gridItem.removeEventListener(MouseEvent.MOUSE_OVER, onOver);
  351. gridItem.removeEventListener(MouseEvent.MOUSE_OUT, onOut);
  352. gridCont.removeChildAt(i);
  353. }
  354. }
  355. private function onDateClick(e : MouseEvent) : void
  356. {
  357. var dateEle : Array = (e.target as DisplayObject).name.split(".");
  358. selectDate = new Date(dateEle[2], dateEle[1], dateEle[0]);
  359. this.dispatchEvent(new Event(Event.SELECT));
  360. }
  361. public function show() : void
  362. {
  363. visible = true;
  364. }
  365. public function hide() : void
  366. {
  367. visible = false;
  368. }
  369. private function drawArrow(__x : Number,__y : Number,__rot : Number) : Sprite
  370. {
  371. // creates Arrows for prevBtn & nextBtn
  372. var spr : Sprite = new Sprite();
  373. spr.graphics.lineStyle(1, 0);
  374. spr.graphics.beginFill(arrowColor);
  375. spr.graphics.lineTo(0, -7.5);
  376. spr.graphics.lineTo(7.5, 0);
  377. spr.graphics.lineTo(0, 7.5);
  378. spr.graphics.endFill();
  379. spr.x = __x;
  380. spr.y = __y;
  381. spr.rotation = __rot;
  382. return spr;
  383. }
  384. private function drawRadialBackground(tw : Number, th : Number) : Sprite
  385. {
  386. // creates background with gradient-fill
  387. var bg : Sprite = new Sprite();
  388. var fillType : String = GradientType.LINEAR;
  389. var colors : Array = new Array();
  390. colors = [0x4B5767, 0x1F222E];
  391. var alphas : Array = [1, 1];
  392. var ratios : Array = [0x00, 0xFF];
  393. var matr : Matrix = new Matrix();
  394. matr.createGradientBox(tw, th, 90, 0, 0);
  395. var spreadMethod : String = SpreadMethod.PAD;
  396. bg.graphics.beginGradientFill(fillType, colors, alphas, ratios, matr, spreadMethod);
  397. bg.graphics.lineStyle(2, 0xD9D9D9);
  398. bg.graphics.drawRoundRect(0, 0, tw, th, 5);
  399. //=============== apply Filter ===============//
  400. var glowColor : uint;
  401. glowColor = 0x000000;
  402. //glowFilter(color, alpha, blurX, blurY, strength, quality, inner, knockout)
  403. var glowFilter : BitmapFilter = new GlowFilter(glowColor, 1, 50, 25, 1, BitmapFilterQuality.HIGH, true, false);
  404. //shadowFilter( distance, angle, color, alpha, blurX, blurY, strength, quality, inner, knockout)
  405. var shadowFilter : DropShadowFilter = new DropShadowFilter(5, 90, 0x000000, 1, 10, 10, 0.9, BitmapFilterQuality.LOW, false, false);
  406. var myFilter : Array = new Array(glowFilter, shadowFilter);
  407. bg.filters = myFilter;
  408. return bg;
  409. }
  410. public function get dayNames() : Array
  411. {
  412. return _dayNames;
  413. }
  414. /**
  415. * dayNames 设置一星期中各天的名称。该值是一个数组,其默认值为 ["日","一", "二", "三", "四", "五", "六"]。
  416. */
  417. public function set dayNames(dayNames : Array) : void
  418. {
  419. _dayNames = dayNames;
  420. }
  421. public function get disabledDays() : Array
  422. {
  423. return _disabledDays;
  424. }
  425. /**
  426. * 指示一星期中禁用的各天。该参数是一个数组,并且最多具有七个值。默认值为 [](空数组)。
  427. */
  428. public function set disabledDays(disabledDays : Array) : void
  429. {
  430. _disabledDays = disabledDays;
  431. }
  432. public function get firstDayOfWeek() : uint
  433. {
  434. return _firstDayOfWeek;
  435. }
  436. /**
  437. * 指示一星期中的哪一天(其值为 0-6,0 是 dayNames 数组的第一个元素)显示在日期选择器的第一列中。此属性更改"日"列的显示顺序。
  438. */
  439. public function set firstDayOfWeek(firstDayOfWeek : uint) : void
  440. {
  441. _firstDayOfWeek = firstDayOfWeek;
  442. }
  443. public function get monthNames() : Array
  444. {
  445. return _monthNames;
  446. }
  447. /**
  448. * 设置在日历的标题行中显示的月份名称。该值是一个数组,其默认值为 ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October","November", "December"]。
  449. */
  450. public function set monthNames(monthNames : Array) : void
  451. {
  452. _monthNames = monthNames;
  453. }
  454. public function get selectableRangeStart() : Date
  455. {
  456. return _selectableRangeStart;
  457. }
  458. /**
  459. * 设置一定范围的可选日期的开始点。用户不能滚动到可选择范围以外。
  460. */
  461. public function set selectableRangeStart(selectableRangeStart : Date) : void
  462. {
  463. _selectableRangeStart = selectableRangeStart;
  464. }
  465. public function get selectableRangeEnd() : Date
  466. {
  467. return _selectableRangeEnd;
  468. }
  469. /**
  470. * 设置一定范围可选日期的结束点。用户不能滚动到可选择范围以外。
  471. */
  472. public function set selectableRangeEnd(selectableRangeEnd : Date) : void
  473. {
  474. _selectableRangeEnd = selectableRangeEnd;
  475. }
  476. /**
  477. * 当前选中的日期
  478. */
  479. public function get selectDate() : Date
  480. {
  481. return _selectedDate;
  482. }
  483. /**
  484. * 设置当前选中的日期
  485. * 默认为今天
  486. */
  487. public function set selectDate(v : Date) : void
  488. {
  489. _selectedDate = v;
  490. //如果如果已初始化则要更新视图,若当前选中的日期在当前显示的这个grid内,则使被选中者高亮
  491. if(_inited && _selectedDate.getFullYear() == yCount && _selectedDate.getMonth() == mCount)
  492. {
  493. //已经确定selectedDate在当前显示的日期内
  494. clearDateGrid();
  495. drawDateGrid(mCount, yCount);
  496. }
  497. }
  498. public function get tfmMonth() : TextFormat
  499. {
  500. return _tfmMonth;
  501. }
  502. public function set tfmMonth(tfmMonth : TextFormat) : void
  503. {
  504. _tfmMonth = tfmMonth;
  505. }
  506. public function get tfmSelectedDay() : TextFormat
  507. {
  508. return _tfmSelectedDay;
  509. }
  510. public function set tfmSelectedDay(tfmSelectedDay : TextFormat) : void
  511. {
  512. _tfmSelectedDay = tfmSelectedDay;
  513. }
  514. public function get tfmGrid() : TextFormat
  515. {
  516. return _tfmGrid;
  517. }
  518. public function set tfmGrid(tfmGrid : TextFormat) : void
  519. {
  520. _tfmGrid = tfmGrid;
  521. }
  522. public function get showToday() : Boolean
  523. {
  524. return _showToday;
  525. }
  526. /**
  527. * 是否高亮显示出今天
  528. */
  529. public function set showToday(v : Boolean) : void
  530. {
  531. if(_showToday == v)return;
  532. _showToday = v;
  533. //如果已初始化则要更新视图,若今天在当前显示的这个grid内,则使今天高亮
  534. if(_inited && _todayDate.getFullYear() == yCount && _todayDate.getMonth() == mCount)
  535. {
  536. //已经确定selectedDate在当前显示的日期内
  537. clearDateGrid();
  538. drawDateGrid(mCount, yCount);
  539. }
  540. }
  541. public function get tfmToday() : TextFormat
  542. {
  543. return _tfmToday;
  544. }
  545. /**
  546. * 设置高亮显示今天日期的文本样式
  547. */
  548. public function set tfmToday(tfmToday : TextFormat) : void
  549. {
  550. _tfmToday = tfmToday;
  551. }
  552. }
  553. }