<mx:ViewStack id="sidebar" width="100%" height="100%" creationPolicy="all">
- <!-- Drag & drop icon panel -->
-
- <mx:VBox id="dndPanel" width="100%" height="100%" horizontalScrollPolicy="off" styleName="dndPanelVbox">
- <mx:Text id="dndPanelText" text="{dndPrompt}" width="100%" styleName="helpInfo" />
- <mx:Repeater id="dndRep" dataProvider="{MapFeatures.getInstance().getCategoriesForType('point')}" styleName="dndRepeater">
- <mx:HBox width="100%" styleName="dndPanelCategory">
- <mx:Label text="{dndRep.currentItem.name}:" styleName="dndPanelCategoryLabel"/>
- </mx:HBox>
-
- <mx:TileList dataProvider="{dndRep.currentItem.getFeaturesForType('point', true)}" width="100%" height="1"
- rowHeight="32" columnWidth="32" updateComplete="resizePOIGrid(event)" styleName="dndPanelTileList">
- <mx:itemRenderer>
- <fx:Component>
- <mx:VBox toolTip="{data.name}">
- <fx:Script><![CDATA[
- import mx.events.DragEvent;
- import mx.managers.DragManager;
- import mx.core.DragSource;
-
- private function dragPOI(event:MouseEvent, tags:Array):void {
- if (outerDocument.controller.map.dragstate==outerDocument.controller.map.DRAGGING) return;
-
- // Get the drag initiator component from the event object.
- var dragInitiator:Image = event.currentTarget as Image;
- var dragSource:DragSource = new DragSource();
- dragSource.addData(tags, 'tags');
- dragSource.addData(event.target.parent.parent.parent.parent, 'container');
-
- var dragProxy:Image = new Image();
- dragProxy.source = dragInitiator.source;
- dragProxy.width = dragInitiator.width; // must set width and height explicitly
- dragProxy.height = dragInitiator.height; // for non-embedded images
- DragManager.doDrag(dragInitiator, dragSource, event, dragProxy);
- }
- ]]></fx:Script>
- <mx:Image id="foo" source="{data.dndimage}" height="24" width="24" mouseMove="dragPOI(event, data.tags)" toolTip="{data.name}" />
- </mx:VBox>
- </fx:Component>
- </mx:itemRenderer>
- </mx:TileList>
- </mx:Repeater>
- </mx:VBox>
+ <sidepanel:DragAndDropPanel id="dndPanel" />
<!-- Standard tagging panel -->
private var tabIcons:Object= { Basic:tabIconBasic, Details:tabIconDetails, Address:tabIconAddress, Walk:tabIconWalk, Cycle:tabIconCycle,
Transport:tabIconTransport, Restrictions:tabIconRestrictions};
- [Bindable]
- public var dndPrompt:String="Add new points by dragging them onto the map";
-
private var editorStackTabNavigator:TabNavigator;
private var editorStackAccordion:Accordion;
[Bindable] private var editorStack:Container;
private var connection:Connection;
private var currentCategorySelector:CategorySelector;
private var categorySelectors:Object = {}; // hash of categorySelectors for each limitType
+ private var categorySelectorEntity:Entity; // entity used to draw the categorySelector
private var feature:Feature = null;
private var rowData:Object; // relation membership reference, needed so it's accessible from relation actions menu
if (entities.length==0) {
// Nothing selected, so show drag-and-drop panel
sidebar.selectedChild = dndPanel;
+ selectedEntity=null;
} else if (entities.length==1) {
// Single entity selected, so show tag panel
+ if (firstSelected!=null && selectedEntity!=firstSelected) {
+ firstSelected.addEventListener(Connection.TAG_CHANGED, tagChanged, false, 0, true);
+ }
selectedEntity=firstSelected;
connection=firstSelected.connection;
- if (selectedEntity!=null) { selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged); }
if (advancedID!=null) { setupAdvanced(firstSelected); }
if (firstSelected is Relation) { stack.addChild(membersVBox); }
if (selectedEntity is Marker && connection is BugConnection) {
&& xor(!controller.map.getLayerForEntity(entities[0]).isBackground, !controller.map.getLayerForEntity(entities[1]).isBackground) ) {
backgroundMergePanelContents.init(entities);
sidebar.selectedChild = backgroundMergePanel;
+ // ** FIXME: do we need to set selectedEntity here?
} else if(isMultipleEditable(entities)) {
selectedEntity = new EntityCollection(entities);
- selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged);
+ selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged, false, 0, true);
sidebar.selectedChild = multiplePanel;
setupMultiAdvanced(selectedEntity);
connection=entities[0].connection;
} else {
//The selection contains elements which can't be edited all together.
sidebar.selectedChild = multipleInvalidPanel;
+ selectedEntity=null;
}
UIComponent.resumeBackgroundProcessing();
}
private function refreshFeatureIcon():void {
var oldFeature:Feature = feature;
+ var oldEntity:Entity = categorySelectorEntity;
+
feature = selectedEntity == null ? null : mapFeatures.findMatchingFeature(selectedEntity);
- if ( feature != oldFeature ) {
- if ( oldFeature != null )
- oldFeature.removeEventListener("imageChanged", featureImageChanged);
- if ( feature != null )
- feature.addEventListener("imageChanged", featureImageChanged);
+ if (oldFeature==feature && categorySelectorEntity==selectedEntity) {
+ updateCategoryImageAndText(selectedEntity,feature);
+ return;
}
- setCategorySelector(selectedEntity, feature);
+
+ categorySelectorEntity=selectedEntity;
+ if ( oldFeature != null ) { oldFeature.removeEventListener("imageChanged", featureImageChanged); }
+ if ( feature != null ) { feature.addEventListener("imageChanged", featureImageChanged); }
+ setCategorySelector(selectedEntity, feature);
}
private function featureImageChanged(event:Event):void {
setCategorySelector(selectedEntity, feature);
}
+
/** Set the icon, categorySelector and help text for the current entity. */
private function setCategorySelector(entity:Entity, feature:Feature):void {
// Remove the "user has selected something" event listener from previous categorySelector,
currentCategorySelector=categorySelectors[lt];
currentCategorySelector.addEventListener("selectedType", changeFeatureType, false, 0, true);
- // Update surrounding icon/text display
+ updateCategoryImageAndText(entity,feature);
+ currentCategorySelector.setSelectedFeature(feature);
+
+ // Set it as the popup, and make sure it's visible
+ popupChange.popUp=currentCategorySelector;
+ currentCategorySelector.visible=true;
+ }
+
+ private function updateCategoryImageAndText(entity:Entity, feature:Feature):void {
if (feature) {
iconImage.source = feature.image;
iconText.htmlText = feature.htmlDetails(entity);
popupChange.label = feature.name;
helpLabel.visible = feature.hasHelpURL();
- currentCategorySelector.setSelectedFeature(feature);
} else {
iconImage.source = null;
popupChange.label = "unknown";
} else {
iconText.htmlText = "<b>No tags set</b><br/><font size='10pt'>Please use the menu below to define what this "+entity.getType()+" is</font>";
}
- currentCategorySelector.setSelectedFeature(null);
}
-
- // Set it as the popup, and make sure it's visible
- popupChange.popUp=currentCategorySelector;
- currentCategorySelector.visible=true;
- }
+ }
private function isMultipleEditable(entities:Array):Boolean {
for each(var entity:Entity in entities) {
UIComponent.resumeBackgroundProcessing();
}
- private function resizePOIGrid(event:Event):void {
- var rows:Number=event.target.dataProvider.length/event.target.columnCount;
- if (rows!=Math.floor(rows)) { rows=Math.floor(rows+1); }
- event.target.height=rows*(event.target.rowHeight+1);
- }
-
]]></fx:Script>
</mx:VBox>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<mx:VBox width="100%" height="100%" horizontalScrollPolicy="off" styleName="dndPanelVbox"
+ xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:controls="net.systemeD.controls.*"
+ xmlns:mx="library://ns.adobe.com/flex/mx">
+
+ <mx:Text id="dndPanelText" text="{dndPrompt}" width="100%" styleName="helpInfo" />
+ <mx:Repeater id="dndRep" dataProvider="{MapFeatures.getInstance().getCategoriesForType('point')}" styleName="dndRepeater">
+ <mx:HBox width="100%" styleName="dndPanelCategory">
+ <mx:Label text="{dndRep.currentItem.name}:" styleName="dndPanelCategoryLabel"/>
+ <mx:Spacer width="100%" />
+ <mx:Label click="showHide(event)" text="" />
+ <mx:Image click="showHide(event)" source="{closedIcon}" />
+ </mx:HBox>
+
+ <mx:TileList dataProvider="{dndRep.currentItem.getFeaturesForType('point', true)}" width="100%" height="1"
+ id="tl" dragEnabled="true" mouseDown="mouseDownHandler(event)" verticalScrollPolicy="off"
+ rowHeight="32" columnWidth="100" updateComplete="sizePOIGrid(event)" styleName="dndPanelTileList">
+ <mx:itemRenderer>
+ <fx:Component>
+ <mx:HBox toolTip="{data.name}" horizontalScrollPolicy="off" >
+ <mx:Image id="foo" source="{data.dndimage}" height="24" width="24" toolTip="{data.name}" />
+ <mx:Label text="{data.name}" />
+ </mx:HBox>
+ </fx:Component>
+ </mx:itemRenderer>
+ </mx:TileList>
+ </mx:Repeater>
+
+ <fx:Script><![CDATA[
+
+ import net.systemeD.potlatch2.mapfeatures.*;
+ import mx.core.DragSource;
+ import mx.managers.DragManager;
+ import mx.controls.Image;
+ import mx.controls.Button;
+ import mx.controls.TileList;
+ import mx.controls.scrollClasses.*;
+
+ [Bindable] [Embed(source="../../../../embedded/CollapsiblePanelAssets.swf", symbol="CollapseButtonDown")] private var openIcon:Class;
+ [Bindable] [Embed(source="../../../../embedded/CollapsiblePanelAssets.swf", symbol="CollapseButtonOver")] private var closedIcon:Class;
+
+ [Bindable] public var dndPrompt:String="Add new points by dragging them onto the map";
+
+ private var inited:Object={};
+ private static const MINIMISED_ROWS:uint=2; // we could perhaps set this by category (e.g. two for shopping, one for tourism...)
+ private static const MINIMISED:uint=0;
+ private static const MAXIMISED:uint=1;
+ private static const TOO_SMALL:uint=2;
+ private static const ICON_WIDTH:uint=24;
+ private static const ICON_HEIGHT:uint=24;
+
+ /** Start POI drag-and-drop. */
+ private function mouseDownHandler(event:MouseEvent):void {
+ if (event.target is ScrollThumb || event.target is Button) return;
+
+ var item:Feature=Feature(TileList(event.currentTarget).selectedItem);
+ var dragInitiator:HBox = event.currentTarget.itemToItemRenderer(item);
+ var dragSource:DragSource = new DragSource();
+ dragSource.addData(item.tags, 'tags');
+ dragSource.addData(event.currentTarget, 'container');
+
+ var dragProxy:Image = new Image();
+ dragProxy.source = item.dndimage;
+ dragProxy.width = ICON_WIDTH; // must set width and height explicitly
+ dragProxy.height = ICON_HEIGHT; // for non-embedded images
+
+ DragManager.doDrag(dragInitiator, dragSource, event, dragProxy);
+ TileList(event.currentTarget).selectedItem=null;
+ }
+
+ /** Handle user's click on show/hide label. */
+ public function showHide(event:Event):void {
+ // find out which tilelist was clicked
+ var theHBox:HBox=event.currentTarget.parent;
+ var pos:uint=theHBox.parent.getChildIndex(theHBox);
+ var tilelist:TileList=TileList(theHBox.parent.getChildAt(pos+1));
+
+ // now adjust the number of rows
+ setHeight(tilelist,(isAtMaximumSize(tilelist)));
+ }
+
+ /** Set a POI grid to the correct size when it's created. Non-functional if called later. */
+ private function sizePOIGrid(event:Event):void {
+ var tilelist:TileList=TileList(event.target);
+ if (inited[tilelist]) { return; }
+ inited[tilelist]=true;
+ setHeight(tilelist,true);
+ }
+
+ /** Set a POI grid to minimised or maximised state, and return the state it's been set to. */
+ private function setHeight(tilelist:TileList,minimise:Boolean):uint {
+ // Set required state
+ var rows:Number=rowsForAll(tilelist);
+ var state:uint;
+ if (rows<=MINIMISED_ROWS) { applyHeight(tilelist,rows); state=TOO_SMALL; }
+ else if (minimise) { applyHeight(tilelist,MINIMISED_ROWS); state=MINIMISED; }
+ else { applyHeight(tilelist,rows); state=MAXIMISED; }
+
+ // Update the clickable label
+ var pos:uint=tilelist.parent.getChildIndex(tilelist);
+ var hbox:HBox=HBox(tilelist.parent.getChildAt(pos-1));
+ var label:Label=Label(hbox.getChildAt(2));
+ var button:Image=Image(hbox.getChildAt(3));
+ switch (state) {
+ case TOO_SMALL: label.text=""; button.visible=false; break;
+ case MINIMISED: label.text="Show all"; button.source =closedIcon; break;
+ case MAXIMISED: label.text="Collapse"; button.source =openIcon; break;
+ }
+ return state;
+ }
+
+ /** Called by setHeight to actually apply the row height to the Flex TileList object. */
+ private function applyHeight(tilelist:TileList,rows:uint):void {
+ tilelist.height=rows*(tilelist.rowHeight+1);
+ }
+
+ /** Is the POI grid at its maximum size? */
+ private function isAtMaximumSize(tilelist:TileList):Boolean {
+ var size:Number=tilelist.height/(tilelist.rowHeight+1);
+ return (size==rowsForAll(tilelist));
+ }
+
+ /** How many rows are required to show everything in this POI grid? */
+ private function rowsForAll(tilelist:TileList):Number {
+ var rows:Number=tilelist.dataProvider.length/tilelist.columnCount;
+ if (rows!=Math.floor(rows)) { rows=Math.floor(rows+1); }
+ return rows;
+ }
+
+ ]]></fx:Script>
+
+</mx:VBox>