Add disclosure triangles
[potlatch2.git] / net / systemeD / potlatch2 / panels / DragAndDropPanel.mxml
1 <?xml version="1.0" encoding="utf-8"?>
2
3 <mx:VBox width="100%" height="100%" horizontalScrollPolicy="off" styleName="dndPanelVbox"
4     xmlns:fx="http://ns.adobe.com/mxml/2009"
5         xmlns:controls="net.systemeD.controls.*"
6         xmlns:mx="library://ns.adobe.com/flex/mx">
7
8         <mx:Text id="dndPanelText" text="{dndPrompt}" width="100%" styleName="helpInfo" />
9         <mx:Repeater id="dndRep" dataProvider="{MapFeatures.getInstance().getCategoriesForType('point')}" styleName="dndRepeater">
10                 <mx:HBox width="100%" styleName="dndPanelCategory">
11                         <mx:Label text="{dndRep.currentItem.name}:" styleName="dndPanelCategoryLabel"/>
12                         <mx:Spacer width="100%" />
13                         <mx:Label click="showHide(event)" text="" />
14                         <mx:Image click="showHide(event)" source="{closedIcon}" />
15                 </mx:HBox>
16
17                 <mx:TileList dataProvider="{dndRep.currentItem.getFeaturesForType('point', true)}" width="100%" height="1"
18                              id="tl" dragEnabled="true" mouseDown="mouseDownHandler(event)" verticalScrollPolicy="off" 
19                              rowHeight="32" columnWidth="100" updateComplete="sizePOIGrid(event)" styleName="dndPanelTileList">
20                         <mx:itemRenderer>
21                                 <fx:Component>
22                                         <mx:HBox toolTip="{data.name}" horizontalScrollPolicy="off" >
23                                                 <mx:Image id="foo" source="{data.dndimage}" height="24" width="24" toolTip="{data.name}" />
24                                                 <mx:Label text="{data.name}" />
25                                         </mx:HBox>
26                                 </fx:Component>
27                         </mx:itemRenderer>
28                 </mx:TileList>
29         </mx:Repeater>
30
31         <fx:Script><![CDATA[
32
33         import net.systemeD.potlatch2.mapfeatures.*;
34         import mx.core.DragSource;
35         import mx.managers.DragManager;
36         import mx.controls.Image;
37         import mx.controls.Button;
38         import mx.controls.TileList;
39         import mx.controls.scrollClasses.*;
40
41         [Bindable] [Embed(source="../../../../embedded/CollapsiblePanelAssets.swf", symbol="CollapseButtonDown")] private var openIcon:Class;
42         [Bindable] [Embed(source="../../../../embedded/CollapsiblePanelAssets.swf", symbol="CollapseButtonOver")] private var closedIcon:Class;
43
44         [Bindable] public var dndPrompt:String="Add new points by dragging them onto the map";
45
46         private var inited:Object={};
47         private static const MINIMISED_ROWS:uint=2;             // we could perhaps set this by category (e.g. two for shopping, one for tourism...)
48         private static const MINIMISED:uint=0;
49         private static const MAXIMISED:uint=1;
50         private static const TOO_SMALL:uint=2;
51
52         /** Start POI drag-and-drop. */
53         private function mouseDownHandler(event:MouseEvent):void {
54                 if (event.target is ScrollThumb || event.target is Button) return;
55
56                 var item:Feature=Feature(TileList(event.currentTarget).selectedItem);
57                 var dragInitiator:HBox = event.currentTarget.itemToItemRenderer(item);
58                 var dragSource:DragSource = new DragSource();
59                 dragSource.addData(item.tags, 'tags');
60                 dragSource.addData(event.currentTarget, 'container');
61
62                 var dragProxy:Image = new Image();
63                 dragProxy.source = item.dndimage;
64                 dragProxy.width = 24;   // must set width and height explicitly
65                 dragProxy.height = 24;  // for non-embedded images
66
67                 DragManager.doDrag(dragInitiator, dragSource, event, dragProxy);
68         }
69
70         /** Handle user's click on show/hide label. */
71         public function showHide(event:Event):void {
72                 // find out which tilelist was clicked
73                 var theHBox:HBox=event.currentTarget.parent;
74                 var pos:uint=theHBox.parent.getChildIndex(theHBox);
75                 var tilelist:TileList=TileList(theHBox.parent.getChildAt(pos+1));
76                 
77                 // now adjust the number of rows
78                 setHeight(tilelist,(isAtMaximumSize(tilelist)));
79         }
80
81         /** Set a POI grid to the correct size when it's created. Non-functional if called later. */
82         private function sizePOIGrid(event:Event):void {
83                 var tilelist:TileList=TileList(event.target);
84                 if (inited[tilelist]) { return; }
85                 inited[tilelist]=true;
86                 setHeight(tilelist,true);
87         }
88         
89         /** Set a POI grid to minimised or maximised state, and return the state it's been set to. */
90         private function setHeight(tilelist:TileList,minimise:Boolean):uint {
91                 // Set required state
92                 var rows:Number=rowsForAll(tilelist);
93                 var state:uint;
94                 if (rows<=MINIMISED_ROWS) { applyHeight(tilelist,rows); state=TOO_SMALL; }
95                 else if (minimise) { applyHeight(tilelist,MINIMISED_ROWS); state=MINIMISED; }
96                 else { applyHeight(tilelist,rows); state=MAXIMISED; }
97                 
98                 // Update the clickable label
99                 var pos:uint=tilelist.parent.getChildIndex(tilelist);
100                 var hbox:HBox=HBox(tilelist.parent.getChildAt(pos-1));
101                 var label:Label=Label(hbox.getChildAt(2));
102                 var button:Image=Image(hbox.getChildAt(3));
103                 switch (state) {
104                         case TOO_SMALL: label.text="";         button.visible=false; break;
105                         case MINIMISED: label.text="Show all"; button.source =closedIcon; break;
106                         case MAXIMISED: label.text="Collapse"; button.source =openIcon; break;
107                 }
108                 return state;
109         }
110         
111         /** Called by setHeight to actually apply the row height to the Flex TileList object. */
112         private function applyHeight(tilelist:TileList,rows:uint):void {
113                 tilelist.height=rows*(tilelist.rowHeight+1);
114         }
115         
116         /** Is the POI grid at its maximum size? */
117         private function isAtMaximumSize(tilelist:TileList):Boolean {
118                 var size:Number=tilelist.height/(tilelist.rowHeight+1);
119                 return (size==rowsForAll(tilelist));
120         }
121         
122         /** How many rows are required to show everything in this POI grid? */
123         private function rowsForAll(tilelist:TileList):Number {
124                 var rows:Number=tilelist.dataProvider.length/tilelist.columnCount;
125                 if (rows!=Math.floor(rows)) { rows=Math.floor(rows+1); }
126                 return rows;
127         }
128
129         ]]></fx:Script>
130
131 </mx:VBox>