1
4
5 import org.aswing.Component;
6 import org.aswing.Container;
7 import org.aswing.DefaultListCellFactory;
8 import org.aswing.Event;
9 import org.aswing.events.ListDataEvent;
10 import org.aswing.events.ListDataListener;
11 import org.aswing.geom.Dimension;
12 import org.aswing.geom.Point;
13 import org.aswing.geom.Rectangle;
14 import org.aswing.LayoutManager;
15 import org.aswing.ListCell;
16 import org.aswing.ListCellFactory;
17 import org.aswing.ListModel;
18 import org.aswing.plaf.ListUI;
19 import org.aswing.UIManager;
20 import org.aswing.utils.Delegate;
21 import org.aswing.utils.HashMap;
22 import org.aswing.utils.Vector;
23 import org.aswing.VectorListModel;
24 import org.aswing.Viewportable;
25
26
113 class org.aswing.JList extends Container implements Viewportable, LayoutManager, ListDataListener{
114
115
120 public static var ON_STATE_CHANGED:String = "onStateChanged";
121
122
126 public static var ON_SELECTION_CHANGE:String = "onSelectionChange";
127
128
131 public static var ON_LIST_SCROLL:String = "onListScroll";
132
133
136 public static var ON_ITEM_PRESS:String = "onItemPress";
137
140 public static var ON_ITEM_RELEASE:String = "onItemRelease";
141
144 public static var ON_ITEM_RELEASEOUTSIDE:String = "onItemReleaseOutSide";
145
148 public static var ON_ITEM_ROLLOVER:String = "onItemRollOver";
149
152 public static var ON_ITEM_ROLLOUT:String = "onItemRollOut";
153
156 public static var ON_ITEM_CLICKED:String = "onItemClicked";
157
158
159
160
163 public static var SINGLE_SELECTION:Number = 0;
164
167 public static var MULTIPLE_SELECTION:Number = 1;
168
169
170 private var viewHeight:Number;
171 private var viewWidth:Number;
172 private var maxWidthCell:ListCell;
173 private var cellPrefferSizes:HashMap;
174 private var comToCellMap:HashMap;
175
176
177 private var preferredWidthWhenNoCount:Number;
178
179 private var verticalUnitIncrement:Number;
180 private var verticalBlockIncrement:Number;
181
182 private var viewPosition:Point;
183
184 private var cellFactory:ListCellFactory;
185 private var model:ListModel;
186 private var cells:Vector;
187
188 private var selectedIndices:Array;
189 private var singleSelectedIndex:Number;
190 private var selectionMode:Number;
191 private var firstVisibleIndex:Number;
192 private var lastVisibleIndex:Number;
193
194 private var itemHandler:Object;
195
196
205 public function JList(listData:Object, cellFactory:ListCellFactory) {
206 super();
207
208 setName("JList");
209 layout = this;
210
211 verticalUnitIncrement = 1;
212 verticalBlockIncrement = 10;
213 viewPosition = new Point(0, 0);
214 selectionMode = SINGLE_SELECTION;
215 singleSelectedIndex = -1;
216 selectedIndices = new Array();
217 firstVisibleIndex = 0;
218 lastVisibleIndex = 0;
219 preferredWidthWhenNoCount = 20;
220
221 viewWidth = 0;
222 viewHeight = 0;
223 maxWidthCell = null;
224 cellPrefferSizes = new HashMap();
225 comToCellMap = new HashMap();
226 cells = new Vector();
227 model = null;
228 initItemHandler();
229
230 if(cellFactory == undefined){
231 cellFactory = new DefaultListCellFactory(true);
232 }
233 this.cellFactory = cellFactory;
234
235 if(listData instanceof ListModel){
236 setModel(ListModel(listData));
237 }else{
238 var o = listData;
239 if(o instanceof Array){
240 setListData(o);
241 }else{
242 setListData(null);
243 }
244 }
245
246 updateUI();
247 }
248
249 public function updateUI():Void{
250 setUI(ListUI(UIManager.getUI(this)));
251 }
252
253 public function setUI(newUI:ListUI):Void{
254 super.setUI(newUI);
255 }
256
257 public function getUIClassID():String{
258 return "ListUI";
259 }
260
261
262
266 public function setLayout(layout:LayoutManager):Void{
267 trace("Can not set layout to JList, its layout is itself");
268 throw new Error("Can not set layout to JList, its layout is itself");
269 }
270
271
280 public function setListData(ld:Array):Void{
281 var m:ListModel = new VectorListModel(ld);
282 setModel(m);
283 }
284
285
289 public function setModel(m:ListModel):Void{
290 if(m == null) return;
291 if(m != model){
292 model.removeListDataListener(this);
293 model = m;
294 model.addListDataListener(this);
295 updateListView();
296 }
297 }
298
299
302 public function getModel():ListModel{
303 return model;
304 }
305
306
309 public function getCellFactory():ListCellFactory{
310 return cellFactory;
311 }
312
313
317 public function setCellFactory(newFactory:ListCellFactory):Void{
318 cellFactory = newFactory;
319 removeAllCells();
320 updateListView();
321 }
322
323
327 public function addSelectionListener(func:Function, obj:Object):Object{
328 return addEventListener(ON_SELECTION_CHANGE, func, obj);
329 }
330
331
335 public function getPreferredWidthWhenNoCount():Number {
336 return preferredWidthWhenNoCount;
337 }
338
339
345 public function setPreferredWidthWhenNoCount(preferredWidthWhenNoCount:Number):Void {
346 this.preferredWidthWhenNoCount = preferredWidthWhenNoCount;
347 }
348
349
354 public function updateListView() : Void {
355 createCells();
356 validateCells();
357 }
358
359
363 public function clearSelection():Void{
364 if(selectionMode == MULTIPLE_SELECTION){
365 selectedIndices = new Array();
366 }else{
367 singleSelectedIndex = -1;
368 }
369 revalidate();
370 }
371
372
378 public function setSelectionMode(sm:Number):Void{
379 if(sm != selectionMode){
380 selectionMode = sm;
381 clearSelection();
382 }
383 }
384
385
390 public function getSelectionMode():Number{
391 return selectionMode;
392 }
393
394
399 public function getSelectedIndex():Number{
400 if(selectionMode == MULTIPLE_SELECTION){
401 for(var i:Number=0; i<selectedIndices.length; i++){
402 if(selectedIndices[i] == true){
403 return i;
404 }
405 }
406 return -1;
407 }else{
408 return singleSelectedIndex;
409 }
410 }
411
412
416 public function isSelectionEmpty():Boolean{
417 return getSelectedIndex() < 0;
418 }
419
420
424 public function getSelectedIndices():Array{
425 var indices:Array = new Array();
426 if(selectionMode == MULTIPLE_SELECTION){
427 for(var i:Number=0; i<selectedIndices.length; i++){
428 if(selectedIndices[i] == true){
429 indices.push(i);
430 }
431 }
432 }else{
433 if(singleSelectedIndex >= 0)
434 indices.push(singleSelectedIndex);
435 }
436 return indices;
437 }
438
439
442 public function isSelectedIndex(index:Number):Boolean{
443 var indices:Array = new Array();
444 if(selectionMode == MULTIPLE_SELECTION){
445 return selectedIndices[index] == true;
446 }else{
447 return singleSelectedIndex == index;
448 }
449 }
450
451
455 public function getSelectedValue():Object{
456 var i:Number = getSelectedIndex();
457 if(i < 0){
458 return null;
459 }else{
460 return model.getElementAt(i);
461 }
462 }
463
464
469 public function getSelectedValues():Array{
470 var values:Array = new Array();
471 if(selectionMode == MULTIPLE_SELECTION){
472 for(var i:Number=0; i<selectedIndices.length; i++){
473 if(selectedIndices[i] == true){
474 values.push(model.getElementAt(i));
475 }
476 }
477 }else{
478 if(singleSelectedIndex >= 0){
479 values.push(model.getElementAt(singleSelectedIndex));
480 }
481 }
482 return values;
483 }
484
485
493 public function setSelectedIndex(index:Number):Void{
494 if(selectionMode == MULTIPLE_SELECTION && selectedIndices[index] == true){
495 var notChanged:Boolean = true;
496 var selectedIndeces:Array = getSelectedIndices();
497 if(selectedIndeces.length == index + 1){
498 for(var i:Number=0; i<index; i++){
499 if(selectedIndeces[i] == true){
500 notChanged = false;
501 break;
502 }
503 }
504 }else{
505 notChanged = true;
506 }
507 if(notChanged){
508 return;
509 }
510 }else{
511 if(singleSelectedIndex == index){
512 return;
513 }
514 }
515
516 clearSelection();
517 if(selectionMode == MULTIPLE_SELECTION){
518 selectedIndices[index] = true;
519 }else{
520 singleSelectedIndex = index;
521 }
522 dispatchEvent(ON_SELECTION_CHANGE, createEventObj(ON_SELECTION_CHANGE));
523 revalidate();
524 }
525
526
537 public function setSelectedIndices(indices:Array):Void{
538 clearSelection();
539 if(selectionMode == MULTIPLE_SELECTION){
540 for(var i:Number=0; i<indices.length; i++)
541 selectedIndices[indices[i]] = true;
542 }else{
543 if(indices.length > 0 )
544 singleSelectedIndex = indices[0];
545 }
546 dispatchEvent(ON_SELECTION_CHANGE, createEventObj(ON_SELECTION_CHANGE));
547 revalidate();
548 }
549
550
556 public function setSelectedValue(value:Object):Void{
557 var n:Number = model.getSize();
558 for(var i:Number=0; i<n; i++){
559 if(model.getElementAt(i) == value){
560 setSelectedIndex(i);
561 return;
562 }
563 }
564 }
565
566
570 public function ensureIndexIsVisible(index:Number):Void{
571 if(index<=getFirstVisibleIndex() || index>=getLastVisibleIndex()){
572 setFirstVisibleIndex(index);
573 }
574 }
575
576 public function getFirstVisibleIndex():Number{
577 return firstVisibleIndex;
578 }
579
580
587 public function setFirstVisibleIndex(index:Number):Void{
588 var factory:ListCellFactory = getCellFactory();
589 var m:ListModel = getModel();
590 var p:Point = getViewPosition();
591 if(factory.isAllCellHasSameHeight() || factory.isShareCells()){
592 p.y = index * factory.getCellHeight();
593 }else{
594 var num:Number = Math.min(cells.getSize()-1, index);
595 var y:Number = 0;
596 for(var i:Number=0; i<num; i++){
597 var cell:ListCell = ListCell(cells.get(i));
598 var s:Dimension = getCachedCellPreferSize(cell);
599 if(s == null){
600 s = cell.getListCellComponent().getPreferredSize();
601 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
602 }
603 y += s.height;
604 }
605 p.y = y;
606 }
607 p.y = Math.max(0, Math.min(getViewMaxPos().y, p.y));
608 setViewPosition(p);
609 }
610
611 public function getLastVisibleIndex():Number{
612 return lastVisibleIndex;
613 }
614
615
622 public function setLastVisibleIndex(index:Number):Void{
623 var factory:ListCellFactory = getCellFactory();
624 var m:ListModel = getModel();
625 var p:Point = getViewPosition();
626 if(factory.isAllCellHasSameHeight() || factory.isShareCells()){
627 p.y = (index + 1) * factory.getCellHeight() - getExtentSize().height;
628 }else{
629 var num:Number = Math.min(cells.getSize(), index+1);
630 var y:Number = 0;
631 for(var i:Number=0; i<num; i++){
632 var cell:ListCell = ListCell(cells.get(i));
633 var s:Dimension = getCachedCellPreferSize(cell);
634 if(s == null){
635 s = cell.getListCellComponent().getPreferredSize();
636 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
637 }
638 y += s.height;
639 }
640 p.y = y - getExtentSize().height;
641 }
642 p.y = Math.max(0, Math.min(getViewMaxPos().y, p.y));
643 setViewPosition(p);
644 }
645
646
649 public function getVisibleRowCount():Number{
650 return getLastVisibleIndex() - getFirstVisibleIndex() + 1;
651 }
652
653
658 public function scrollToBottomLeft():Void{
659 setViewPosition(new Point(0, Number.MAX_VALUE));
660 }
661
666 public function scrollToBottomRight():Void{
667 setViewPosition(new Point(Number.MAX_VALUE, Number.MAX_VALUE));
668 }
669
674 public function scrollToTopLeft():Void{
675 setViewPosition(new Point(0, 0));
676 }
677
682 public function scrollToTopRight():Void{
683 setViewPosition(new Point(Number.MAX_VALUE, 0));
684 }
685
686
689 public function setEnabled(b:Boolean):Void{
690 if(b != isEnabled()){
691 var n:Number = getComponentCount();
692 for(var i:Number=n-1; i>=0; i--){
693 var com:Component = getComponent(i);
694 com.setEnabled(b);
695 }
696 repaint();
697 }
698 super.setEnabled(b);
699 }
700
701 private function addCellToContainer(cell:ListCell):Void{
702 append(cell.getListCellComponent());
703 comToCellMap.put(cell.getListCellComponent().getID(), cell);
704 cell.getListCellComponent().addEventListener(itemHandler);
705 }
706
707 private function removeCellFromeContainer(cell:ListCell):Void{
708 remove(cell.getListCellComponent());
709 comToCellMap.remove(cell.getListCellComponent().getID());
710 cell.getListCellComponent().removeEventListener(itemHandler);
711 }
712
713 private function checkCreateCellsWhenShareCells():Void{
714 createCellsWhenShareCells();
715 }
716
717 private function createCellsWhenShareCells():Void{
718 var ih:Number = getCellFactory().getCellHeight();
719 var needNum:Number = Math.floor(getExtentSize().height/ih) + 2;
720
721 viewWidth = getPreferredWidthWhenNoCount();
722 viewHeight = getModel().getSize()*ih;
723
724 if(cells.getSize() == needNum){
725 return;
726 }
727
728 var iw:Number = getWidth();
729
730 if(cells.getSize() < needNum){
731 var addNum:Number = needNum - cells.getSize();
732 for(var i:Number=0; i<addNum; i++){
733 var cell:ListCell = getCellFactory().createNewCell();
734 addCellToContainer(cell);
735 cells.append(cell);
736 }
737 }else if(cells.getSize() > needNum){
738 var removeIndex:Number = needNum;
739 var removed:Array = cells.removeRange(removeIndex, cells.getSize()-1);
740 for(var i:Number=0; i<removed.length; i++){
741 var cell:ListCell = ListCell(removed[i]);
742 removeCellFromeContainer(cell);
743 }
744 }
745 }
746
747 private function createCellsWhenNotShareCells():Void{
748 var factory:ListCellFactory = getCellFactory();
749 var m:ListModel = getModel();
750
751 var w:Number = 0;
752 var h:Number = 0;
753 var sameHeight:Boolean = factory.isAllCellHasSameHeight();
754
755 var mSize:Number = m.getSize();
756 var cSize:Number = cells.getSize();
757
758 cellPrefferSizes.clear();
759
760 var n:Number = Math.min(mSize, cSize);
761
762 for(var i:Number=0; i<n; i++){
763 var cell:ListCell = ListCell(cells.get(i));
764 cell.setValue(m.getElementAt(i));
765 var s:Dimension = cell.getListCellComponent().getPreferredSize();
766 cellPrefferSizes.put(cell.getListCellComponent().getID(), s);
767 if(s.width > w){
768 w = s.width;
769 maxWidthCell = cell;
770 }
771 if(!sameHeight){
772 h += s.height;
773 }
774 }
775
776
777 if(mSize > cSize){
778 for(var i:Number = cSize; i<mSize; i++){
779 var cell:ListCell = factory.createNewCell();
780 cells.append(cell);
781 cell.setValue(m.getElementAt(i));
782 addCellToContainer(cell);
783 var s:Dimension = cell.getListCellComponent().getPreferredSize();
784 cellPrefferSizes.put(cell.getListCellComponent().getID(), s);
785 if(s.width > w){
786 w = s.width;
787 maxWidthCell = cell;
788 }
789 if(!sameHeight){
790 h += s.height;
791 }
792 }
793 }else if(mSize < cSize){
794 var removed:Array = cells.removeRange(mSize, cSize-1);
795 for(var i:Number=0; i<removed.length; i++){
796 var cell:ListCell = ListCell(removed[i]);
797 cell.getListCellComponent().removeFromContainer();
798 removeCellFromeContainer(cell);
799 cellPrefferSizes.remove(cell.getListCellComponent().getID());
800 }
801 }
802
803 if(sameHeight){
804 h = m.getSize()*factory.getCellHeight();
805 }
806
807 viewWidth = w;
808 viewHeight = h;
809 }
810
811 private function createCells():Void{
812 if(getCellFactory().isShareCells()){
813 createCellsWhenShareCells();
814 }else{
815 createCellsWhenNotShareCells();
816 }
817 }
818
819 private function removeAllCells() : Void {
820 for(var i:Number=0; i<cells.getSize(); i++){
821 var cell:ListCell = ListCell(cells.get(i));
822 cell.getListCellComponent().removeFromContainer();
823 }
824 cells.clear();
825 }
826
827 private function validateCells():Void{
828 revalidate();
829 }
830
831
832
833 public function getVerticalUnitIncrement() : Number {
834 if(getCellFactory().isAllCellHasSameHeight()){
835 return getCellFactory().getCellHeight();
836 }else{
837 return verticalUnitIncrement;
838 }
839 }
840
841 public function getVerticalBlockIncrement() : Number {
842 if(getCellFactory().isAllCellHasSameHeight()){
843 return getExtentSize().height - getCellFactory().getCellHeight();
844 }else{
845 return getExtentSize().height - verticalBlockIncrement;
846 }
847 }
848
849 public function getHorizontalUnitIncrement() : Number {
850 return 1;
851 }
852
853 public function getHorizontalBlockIncrement() : Number {
854 return getExtentSize().width - 1;
855 }
856
857 public function setViewportTestSize(s:Dimension):Void{
858 setSize(s);
859 }
860
861 public function getExtentSize() : Dimension {
862 return getInsets().inroundsSize(getSize());
863 }
864
865 public function getViewSize() : Dimension {
866 return new Dimension(viewWidth, viewHeight);
867 }
868
869 public function getViewPosition() : Point {
870 return new Point(viewPosition.x, viewPosition.y);
871 }
872
873 public function setViewPosition(p : Point) : Void {
874 restrictionViewPos(p);
875 if(!viewPosition.equals(p)){
876 viewPosition.setLocation(p);
877 fireStateChanged();
878 revalidate();
879 }
880 }
881
882 public function scrollRectToVisible(contentRect : Rectangle) : Void {
883 setViewPosition(new Point(contentRect.x, contentRect.y));
884 }
885
886 private function restrictionViewPos(p:Point):Point{
887 var maxPos:Point = getViewMaxPos();
888 p.x = Math.max(0, Math.min(maxPos.x, p.x));
889 p.y = Math.max(0, Math.min(maxPos.y, p.y));
890 return p;
891 }
892
893 private function getViewMaxPos():Point{
894 var showSize:Dimension = getExtentSize();
895 var viewSize:Dimension = getViewSize();
896 var p:Point = new Point(viewSize.width-showSize.width, viewSize.height-showSize.height);
897 if(p.x < 0) p.x = 0;
898 if(p.y < 0) p.y = 0;
899 return p;
900 }
901
902 public function addChangeListener(func : Function, obj : Object) : Object {
903 return addEventListener(ON_STATE_CHANGED, func, obj);
904 }
905
906 public function getViewportPane() : Component {
907 return this;
908 }
909
910
911
912
915 public function addLayoutComponent(comp:Component, constraints:Object):Void{
916 }
917
918
921 public function removeLayoutComponent(comp:Component):Void{
922 }
923
924 public function preferredLayoutSize(target:Container):Dimension{
925 return getViewSize();
926 }
927
928 public function minimumLayoutSize(target:Container):Dimension{
929 return getInsets().getRoundBounds().getSize();
930 }
931
932 public function maximumLayoutSize(target:Container):Dimension{
933 return new Dimension(Number.MAX_VALUE, Number.MAX_VALUE);
934 }
935
936
939 public function layoutContainer(target:Container):Void{
940 var factory:ListCellFactory = getCellFactory();
941 if(factory.isShareCells()){
942 layoutWhenShareCells();
943 }else{
944 if(factory.isAllCellHasSameHeight()){
945 layoutWhenNotShareCellsAndSameHeight();
946 }else{
947 layoutWhenNotShareCellsAndNotSameHeight();
948 }
949 }
950 }
951
952 private function layoutWhenShareCells():Void{
953 checkCreateCellsWhenShareCells();
954
955 var factory:ListCellFactory = getCellFactory();
956 var m:ListModel = getModel();
957 var ir:Rectangle = getInsets().getInsideBounds(getSize().getBounds());
958 var cellWidth:Number = ir.width;
959
960 restrictionViewPos(viewPosition);
961 var x:Number = viewPosition.x;
962 var y:Number = viewPosition.y;
963 var ih:Number = factory.getCellHeight();
964 var startIndex:Number = Math.floor(y/ih);
965 var startY:Number = startIndex*ih - y;
966 var listSize:Number = m.getSize();
967
968 var cx:Number = ir.x - x;
969 var cy:Number = ir.y + startY;
970 for(var i:Number = 0; i<cells.getSize(); i++){
971 var cell:ListCell = ListCell(cells.get(i));
972 var ldIndex:Number = startIndex + i;
973 var cellCom:Component = cell.getListCellComponent();
974 if(ldIndex < listSize){
975 cell.setValue(m.getElementAt(ldIndex));
976 cellCom.setVisible(true);
977 cellCom.setBounds(cx, cy, cellWidth, ih);
978 cy += ih;
979 if(selectionMode == MULTIPLE_SELECTION){
980 cell.setSelected((selectedIndices[ldIndex]==true));
981 }else{
982 cell.setSelected(ldIndex == singleSelectedIndex);
983 }
984 }else{
985 cellCom.setVisible(false);
986 }
987 }
988 firstVisibleIndex = startIndex;
989 lastVisibleIndex = Math.min(startIndex + cells.getSize() - 1, listSize - 1);
990 }
991
992 private function layoutWhenNotShareCellsAndSameHeight():Void{
993 var factory:ListCellFactory = getCellFactory();
994 var m:ListModel = getModel();
995 var ir:Rectangle = getInsets().getInsideBounds(getSize().getBounds());
996 var cellWidth:Number = Math.max(ir.width, viewWidth);
997
998 restrictionViewPos(viewPosition);
999 var x:Number = viewPosition.x;
1000 var y:Number = viewPosition.y;
1001 var ih:Number = factory.getCellHeight();
1002 var startIndex:Number = Math.floor(y/ih);
1003 var listSize:Number = m.getSize();
1004 var endIndex:Number = startIndex + Math.floor(ir.height / ih) + 2 - 1;
1005 if(endIndex >= listSize){
1006 endIndex = listSize - 1;
1007 }
1008 var startY:Number = startIndex*ih - y;
1009
1010 var cx:Number = ir.x - x;
1011 var cy:Number = ir.y + startY;
1012
1013 for(var i:Number=firstVisibleIndex; i<startIndex; i++){
1014 ListCell(cells.get(i)).getListCellComponent().setVisible(false);
1015 }
1016 for(var i:Number=endIndex+1; i<=lastVisibleIndex; i++){
1017 ListCell(cells.get(i)).getListCellComponent().setVisible(false);
1018 }
1019
1020
1021 for(var i:Number=startIndex; i<=endIndex; i++){
1022 var cell:ListCell = ListCell(cells.get(i));
1023 var cellCom:Component = cell.getListCellComponent();
1024 cellCom.setVisible(true);
1025 var s:Dimension = getCachedCellPreferSize(cell);
1026 if(s == null){
1027 s = cell.getListCellComponent().getPreferredSize();
1028 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
1029 }
1030 cellCom.setBounds(cx, cy, Math.max(cellWidth, s.width), ih);
1031 cy += ih;
1032 if(selectionMode == MULTIPLE_SELECTION){
1033 cell.setSelected((selectedIndices[i]==true));
1034 }else{
1035 cell.setSelected(i == singleSelectedIndex);
1036 }
1037 }
1038 firstVisibleIndex = startIndex;
1039 lastVisibleIndex = endIndex;
1040 }
1041
1042 private function getCachedCellPreferSize(cell:ListCell):Dimension{
1043 return Dimension(cellPrefferSizes.get(cell.getListCellComponent().getID()));
1044 }
1045
1046 private function layoutWhenNotShareCellsAndNotSameHeight():Void{
1047 var factory:ListCellFactory = getCellFactory();
1048 var m:ListModel = getModel();
1049 var ir:Rectangle = getInsets().getInsideBounds(getSize().getBounds());
1050 var cellWidth:Number = Math.max(ir.width, viewWidth);
1051
1052 restrictionViewPos(viewPosition);
1053 var x:Number = viewPosition.x;
1054 var y:Number = viewPosition.y;
1055
1056 var startIndex:Number = 0;
1057 var cellsCount:Number = cells.getSize();
1058
1059 var tryY:Number = 0;
1060 var startY:Number = 0;
1061 for(var i:Number=0; i<cellsCount; i++){
1062 var cell:ListCell = ListCell(cells.get(i));
1063 var s:Dimension = getCachedCellPreferSize(cell);
1064 if(s == null){
1065 s = cell.getListCellComponent().getPreferredSize();
1066 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
1067 }
1068 tryY += s.height;
1069 if(tryY >= y){
1070 startIndex = i;
1071 startY = -(s.height - (tryY - y));
1072 break;
1073 }
1074 }
1075
1076 var listSize:Number = m.getSize();
1077 var cx:Number = ir.x - x;
1078 var cy:Number = ir.y + startY;
1079 var maxY:Number = ir.y + ir.height;
1080
1081
1082 var endIndex:Number = startIndex;
1083 for(var i:Number=startIndex; i<cellsCount; i++){
1084 var cell:ListCell = ListCell(cells.get(i));
1085 var cellCom:Component = cell.getListCellComponent();
1086 var s:Dimension = getCachedCellPreferSize(cell);
1087 if(s == null){
1088 s = cell.getListCellComponent().getPreferredSize();
1089 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
1090 }
1091 if(selectionMode == MULTIPLE_SELECTION){
1092 cell.setSelected((selectedIndices[i]==true));
1093 }else{
1094 cell.setSelected(i == singleSelectedIndex);
1095 }
1096 cellCom.setVisible(true);
1097 cellCom.setBounds(cx, cy, Math.max(cellWidth, s.width), s.height);
1098 cy += s.height;
1099 endIndex = i;
1100 if(cy >= maxY){
1101 break;
1102 }
1103 }
1104
1105
1106 for(var i:Number=firstVisibleIndex; i<startIndex; i++){
1107 ListCell(cells.get(i)).getListCellComponent().setVisible(false);
1108 }
1109 for(var i:Number=endIndex+1; i<=lastVisibleIndex; i++){
1110 ListCell(cells.get(i)).getListCellComponent().setVisible(false);
1111 }
1112
1113 firstVisibleIndex = startIndex;
1114 lastVisibleIndex = endIndex;
1115 }
1116
1117
1120 public function getLayoutAlignmentX(target:Container):Number{
1121 return 0;
1122 }
1123
1124
1127 public function getLayoutAlignmentY(target:Container):Number{
1128 return 0;
1129 }
1130
1131 public function invalidateLayout(target:Container):Void{
1132 }
1133
1134
1135
1136
1139 public function intervalAdded(e:ListDataEvent):Void{
1140 clearSelection();
1141 var factory:ListCellFactory = getCellFactory();
1142 var m:ListModel = getModel();
1143
1144 var w:Number = viewWidth;
1145 var h:Number = viewHeight;
1146 var sameHeight:Boolean = factory.isAllCellHasSameHeight();
1147
1148 var i0:Number = e.getIndex0();
1149 var i1:Number = e.getIndex1();
1150
1151 if(factory.isShareCells()){
1152 w = getPreferredWidthWhenNoCount();
1153 h = m.getSize()*factory.getCellHeight();
1154 }else{
1155 for(var i:Number=i0; i<=i1; i++){
1156 var cell:ListCell = factory.createNewCell();
1157 cells.append(cell, i);
1158 cell.setValue(m.getElementAt(i));
1159 addCellToContainer(cell);
1160 var s:Dimension = cell.getListCellComponent().getPreferredSize();
1161 cellPrefferSizes.put(cell.getListCellComponent().getID(), s);
1162 if(s.width > w){
1163 w = s.width;
1164 maxWidthCell = cell;
1165 }
1166 w = Math.max(w, s.width);
1167 if(!sameHeight){
1168 h += s.height;
1169 }
1170 }
1171 if(sameHeight){
1172 h = m.getSize()*factory.getCellHeight();
1173 }
1174 }
1175
1176 viewWidth = w;
1177 viewHeight = h;
1178
1179 revalidate();
1180 }
1181
1182
1185 public function intervalRemoved(e:ListDataEvent):Void{
1186 clearSelection();
1187 var factory:ListCellFactory = getCellFactory();
1188 var m:ListModel = getModel();
1189
1190 var w:Number = viewWidth;
1191 var h:Number = viewHeight;
1192 var sameHeight:Boolean = factory.isAllCellHasSameHeight();
1193
1194 var i0:Number = e.getIndex0();
1195 var i1:Number = e.getIndex1();
1196
1197 if(factory.isShareCells()){
1198 w = getPreferredWidthWhenNoCount();
1199 h = m.getSize()*factory.getCellHeight();
1200 }else{
1201 var needRecountWidth:Boolean = false;
1202 for(var i:Number=i0; i<=i1; i++){
1203 var cell:ListCell = ListCell(cells.get(i));
1204 if(cell == maxWidthCell){
1205 needRecountWidth = true;
1206 }
1207 if(!sameHeight){
1208 var s:Dimension = getCachedCellPreferSize(cell);
1209 if(s == null){
1210 s = cell.getListCellComponent().getPreferredSize();
1211 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
1212 }
1213 h -= s.height;
1214 }
1215 removeCellFromeContainer(cell);
1216 cellPrefferSizes.remove(cell.getListCellComponent().getID());
1217 }
1218 cells.removeRange(i0, i1);
1219 if(sameHeight){
1220 h = m.getSize()*factory.getCellHeight();
1221 }
1222 if(needRecountWidth){
1223 w = 0;
1224 for(var i:Number=cells.getSize()-1; i>=0; i--){
1225 var cell:ListCell = ListCell(cells.get(i));
1226 var s:Dimension = getCachedCellPreferSize(cell);
1227 if(s == null){
1228 s = cell.getListCellComponent().getPreferredSize();
1229 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
1230 }
1231 if(s.width > w){
1232 w = s.width;
1233 maxWidthCell = cell;
1234 }
1235 }
1236 }
1237 }
1238
1239 viewWidth = w;
1240 viewHeight = h;
1241
1242 revalidate();
1243 }
1244
1245
1248 public function contentsChanged(e:ListDataEvent):Void{
1249 var factory:ListCellFactory = getCellFactory();
1250 var m:ListModel = getModel();
1251
1252 var w:Number = viewWidth;
1253 var h:Number = viewHeight;
1254 var sameHeight:Boolean = factory.isAllCellHasSameHeight();
1255
1256 var i0:Number = e.getIndex0();
1257 var i1:Number = e.getIndex1();
1258
1259 if(factory.isShareCells()){
1260 w = getPreferredWidthWhenNoCount();
1261 h = m.getSize()*factory.getCellHeight();
1262 }else{
1263 var needRecountWidth:Boolean = false;
1264 for(var i:Number=i0; i<=i1; i++){
1265 var newValue:Object = m.getElementAt(i);
1266 var cell:ListCell = ListCell(cells.get(i));
1267 var s:Dimension = getCachedCellPreferSize(cell);
1268 if(s == null){
1269 s = cell.getListCellComponent().getPreferredSize();
1270 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
1271 }
1272 if(cell == maxWidthCell){
1273 h -= s.height;
1274 cell.setValue(newValue);
1275 var ns:Dimension = cell.getListCellComponent().getPreferredSize();
1276 cellPrefferSizes.put(cell.getListCellComponent().getID(), ns);
1277 if(ns.width < s.width){
1278 needRecountWidth = true;
1279 }else{
1280 w = ns.width;
1281 }
1282 h += ns.height;
1283 }else{
1284 h -= s.height;
1285 cell.setValue(newValue);
1286 var ns:Dimension = cell.getListCellComponent().getPreferredSize();
1287 cellPrefferSizes.put(cell.getListCellComponent().getID(), ns);
1288 h += ns.height;
1289 if(!needRecountWidth){
1290 if(ns.width > w){
1291 maxWidthCell = cell;
1292 w = ns.width;
1293 }
1294 }
1295 }
1296 }
1297 if(sameHeight){
1298 h = m.getSize()*factory.getCellHeight();
1299 }
1300 if(needRecountWidth || maxWidthCell == null){
1301 w = 0;
1302 for(var i:Number=cells.getSize()-1; i>=0; i--){
1303 var cell:ListCell = ListCell(cells.get(i));
1304 var s:Dimension = getCachedCellPreferSize(cell);
1305 if(s == null){
1306 s = cell.getListCellComponent().getPreferredSize();
1307 trace("Warnning : cell size not cached index = " + i + ", value = " + cell.getValue());
1308 }
1309 if(s.width > w){
1310 w = s.width;
1311 maxWidthCell = cell;
1312 }
1313 }
1314 }
1315 }
1316
1317 viewWidth = w;
1318 viewHeight = h;
1319
1320 revalidate();
1321 }
1322
1323
1324
1325 private function initItemHandler():Void{
1326 itemHandler = new Object();
1327 itemHandler[Component.ON_PRESS] = Delegate.create(this, __onItemPress);
1328 itemHandler[Component.ON_RELEASE] = Delegate.create(this, __onItemRelease);
1329 itemHandler[Component.ON_RELEASEOUTSIDE] = Delegate.create(this, __onItemReleaseOutside);
1330 itemHandler[Component.ON_ROLLOVER] = Delegate.create(this, __onItemRollOver);
1331 itemHandler[Component.ON_ROLLOUT] = Delegate.create(this, __onItemRollOut);
1332 itemHandler[Component.ON_CLICKED] = Delegate.create(this, __onItemClicked);
1333 }
1334
1335 private function createItemEventObj(ie:Event, type:String):Event{
1336 var event:Event = createEventObj(type);
1337 var item:Component = Component(ie.getSource());
1338 var cell:ListCell = getCellByCellComponent(item);
1339 event.value = cell.getValue();
1340 event.cell = cell;
1341 return event;
1342 }
1343
1344 private function getItemIndexByCellComponent(item:Component):Number{
1345 var cell:Object = comToCellMap.get(item.getID());
1346 if(getCellFactory().isShareCells()){
1347 return firstVisibleIndex + cells.indexOf(cell);
1348 }else{
1349 return cells.indexOf(cell);
1350 }
1351 }
1352
1353 private function getCellByCellComponent(item:Component):ListCell{
1354 return ListCell(comToCellMap.get(item.getID()));
1355 }
1356
1357 private function getCellByIndex(index:Number):ListCell{
1358 if(getCellFactory().isShareCells()){
1359 return ListCell(cells.get(index - firstVisibleIndex));
1360 }else{
1361 return ListCell(cells.get(index));
1362 }
1363 }
1364
1365
1368 private function __onItemPress(event:Event):Void{
1369 dispatchEvent(ON_ITEM_PRESS, createItemEventObj(event, ON_ITEM_PRESS));
1370
1371 var source:Component = Component(event.getSource());
1372 var index:Number = getItemIndexByCellComponent(source);
1373 var cell:ListCell = getCellByCellComponent(source);
1374 if(selectionMode == MULTIPLE_SELECTION){
1375 selectedIndices[index] = !selectedIndices[index];
1376 cell.setSelected(selectedIndices[index]);
1377 cacheIsJustPressMakeSelectionChanged = true;
1378 }else{
1379 if(singleSelectedIndex != index){
1380 if(singleSelectedIndex >= 0){
1381 getCellByIndex(singleSelectedIndex).setSelected(false);
1382 }
1383 singleSelectedIndex = index;
1384 cell.setSelected(true);
1385 cacheIsJustPressMakeSelectionChanged = true;
1386 }else{
1387 cacheIsJustPressMakeSelectionChanged = false;
1388 }
1389 }
1390 }
1391 private var cacheIsJustPressMakeSelectionChanged:Boolean;
1392
1395 private function __onItemRelease(event:Event):Void{
1396 dispatchEvent(ON_ITEM_RELEASE, createItemEventObj(event, ON_ITEM_RELEASE));
1397 if(cacheIsJustPressMakeSelectionChanged){
1398 dispatchEvent(ON_SELECTION_CHANGE, createEventObj());
1399 }
1400 }
1401
1402
1405 private function __onItemReleaseOutside(event:Event):Void{
1406 dispatchEvent(ON_ITEM_RELEASEOUTSIDE, createItemEventObj(event, ON_ITEM_RELEASEOUTSIDE));
1407 if(cacheIsJustPressMakeSelectionChanged){
1408 dispatchEvent(ON_SELECTION_CHANGE, createEventObj());
1409 }
1410 }
1411
1412
1415 private function __onItemRollOver(event:Event):Void{
1416 dispatchEvent(ON_ITEM_ROLLOVER, createItemEventObj(event, ON_ITEM_ROLLOVER));
1417 }
1418
1419
1422 private function __onItemRollOut(event:Event):Void{
1423 dispatchEvent(ON_ITEM_ROLLOUT, createItemEventObj(event, ON_ITEM_ROLLOUT));
1424 }
1425
1426
1429 private function __onItemClicked(event:Event):Void{
1430 var ie:Event = createItemEventObj(event, ON_ITEM_CLICKED);
1431 ie.clickCount = event.clickCount;
1432 dispatchEvent(ON_ITEM_CLICKED, ie);
1433 }
1434 }
1435