Contextual help for each ControllerState
authorRichard Fairhurst <richard@systemeD.net>
Sun, 14 Oct 2012 23:14:50 +0000 (16:14 -0700)
committerRichard Fairhurst <richard@systemeD.net>
Sun, 14 Oct 2012 23:14:50 +0000 (16:14 -0700)
net/systemeD/potlatch2/ContextualHelp.mxml [new file with mode: 0644]
net/systemeD/potlatch2/EditController.as
net/systemeD/potlatch2/controller/ControllerState.as
net/systemeD/potlatch2/dialogs/OptionsDialog.mxml
potlatch2.mxml
styles/Application.css

diff --git a/net/systemeD/potlatch2/ContextualHelp.mxml b/net/systemeD/potlatch2/ContextualHelp.mxml
new file mode 100644 (file)
index 0000000..0595e8b
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mx:ViewStack
+ xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ backgroundColor="#71A2FA">
+
+  <mx:Box id="contextNoSelection"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Click object</b> to select. <b>Click blank area</b> to start drawing way. 
+                       <b>Double-click blank area</b> to create point. <b>Drag blank area</b> to move map.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextSelectedWay"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Click node</b> to select it. <b>Shift-click node</b> to start branching way. 
+                       <b>Shift-click way</b> to insert new node. 
+                       <b>Shift-backspace/delete</b> to delete.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextDragSelection"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Drag item</b> - release when done.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextDragWayNode"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Drag node</b> - release when done.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextDrawQuadrilateral"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Stretch and rotate to fit</b> - release when done.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextDrawWay"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Click blank space</b> to add new point. <b>Click way</b> to make junction. 
+                       <b>Double-click</b> or press Enter to finish drawing. <b>Backspace</b> to cancel last.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextSelectArea"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Drag</b> to select area. <b>Release</b> when done.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextSelectedMultiple"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Control-click</b> to add/remove items from selection.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextSelectedParallelWay"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Move mouse</b> to adjust position. <b>Click</b> to create. <b>Escape</b> to cancel.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextSelectedPOINode"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Click, hold and drag</b> to move. <b>Backspace/delete</b> to delete.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextSelectedWayNode"><mx:TextArea styleName="contextualHelp" width="100%" condenseWhite="true">
+               <mx:htmlText><![CDATA[
+                       <b>Click, hold and drag</b> to move. <b>Backspace/delete</b> to delete.
+               ]]></mx:htmlText>
+       </mx:TextArea></mx:Box>
+
+  <mx:Box id="contextNotFound"><mx:TextArea styleName="contextualHelp" width="100%" htmlText="(No help available)"/></mx:Box>
+
+</mx:ViewStack>
index 91a8ce5..76af73e 100644 (file)
@@ -29,6 +29,7 @@ package net.systemeD.potlatch2 {
 
         /** The current ControllerState */
         public var state:ControllerState;
+        public static var CHANGED_STATE:String="changed_state";
         
                /** Hash of when a key was pressed. A user can keyDown within a TextInput, press Enter (leaving
                    the TextInput), and then keyup - resulting in the keypress being interpreted again. 
@@ -177,6 +178,7 @@ package net.systemeD.potlatch2 {
             newState.setController(this);
             state = newState;
             state.enterState();
+            dispatchEvent(new Event(CHANGED_STATE));
         }
 
                /** Given what is currently selected (or not), find the matching ControllerState. */
index 92615e5..e073545 100644 (file)
@@ -68,6 +68,12 @@ package net.systemeD.potlatch2.controller {
                public function toString():String {
                        return "(No state)";
                }
+
+               /** Return contextual help string for this state. */
+               public function contextualHelpId():String {
+                       return toString();
+               }
+
                /** Default behaviour for the current state that should be called if state-specific action has been taken care of or ruled out. */
                protected function sharedKeyboardEvents(event:KeyboardEvent):ControllerState {
                        var editableLayer:MapPaint=controller.map.editableLayer;                                                                // shorthand for this method
index c312f86..55e1aab 100644 (file)
@@ -21,6 +21,9 @@
     <s:CheckBox width="100%" label="Highlight unedited TIGER (US roads)" selected="false" id="tigercheck"
         change="tigerToggle()" />
 
+    <s:CheckBox width="100%" label="Show contextual help" selected="true" id="contextcheck"
+        change="contextToggle()" />
+
        <s:CheckBox width="100%" label="Show mouse latitude/longitude" selected="false" id="latlongcheck"
                change="FlexGlobals.topLevelApplication.coordsbox.visible=latlongcheck.selected" />
 
@@ -65,6 +68,7 @@
         cursorcheck.selected = FlexGlobals.topLevelApplication.theController.cursorsEnabled;
         tigercheck.selected = userState.data['tiger_highlighted'];
         latlongcheck.selected = FlexGlobals.topLevelApplication.coordsbox.visible;
+               contextcheck.selected = FlexGlobals.topLevelApplication.contextHelp.visible;
                simplifyslider.value = userState.data['simplify_tolerance'] ? userState.data['simplify_tolerance']/0.00001 : 5;
     }
     
         try { userState.flush(); } catch (e:Error) {}
     }
 
+       private function contextToggle():void {
+               FlexGlobals.topLevelApplication.contextHelp.visible = contextcheck.selected;
+               FlexGlobals.topLevelApplication.contextHelp.height  = contextcheck.selected ? 30 : 0;
+               userState.setProperty("hide_context_help",!contextcheck.selected);
+               try { userState.flush(); } catch (e:Error) {}
+       }
+
        private function simplifySet():void {
         userState.setProperty("simplify_tolerance",simplifyslider.value*0.00001);
         try { userState.flush(); } catch (e:Error) {}
index af7976e..ddd91d4 100644 (file)
          <!-- Tag viewer -->
          <potlatch2:TagViewer width="25%" height="100%" id="tagViewer"/>
 
-      <mx:Canvas width="75%" height="100%">
-        <mx:Canvas id="map_area" resize="onResizeMap()"
-            top="0" left="0" width="100%" height="100%" dragEnter="dragEnterHandler(event);" dragDrop="dragDropHandler(event);">
+      <mx:VBox width="75%" height="100%" verticalGap="0" id="rhContent" >
+          <mx:Canvas width="100%" height="100%">
+            <mx:Canvas id="map_area" resize="onResizeMap()"
+                top="0" left="0" width="100%" height="100%" dragEnter="dragEnterHandler(event);" dragDrop="dragDropHandler(event);">
+            </mx:Canvas>
+            <mx:Image source="@Embed('embedded/zoomIn.svg')" left="5" top="5" click="theMap.zoomIn();"
+                rollOverEffect="glowImage" rollOutEffect="unglowImage" toolTip="{'Zoom in - currently z'+getScale()}" />
+            <mx:Image source="@Embed('embedded/zoomOut.svg')" left="5" top="22" click="theMap.zoomOut();"
+                rollOverEffect="glowImage" rollOutEffect="unglowImage" toolTip="{'Zoom out - currently z'+getScale()}" />
+            <mx:Image source="@Embed('embedded/search.svg')" left="5" top="42" click="new FindDialog().init();"
+                rollOverEffect="glowImage" rollOutEffect="unglowImage" toolTip="Find place" />
+            <mx:TextArea id="dataWorking" text="" right="5" top="5" disabledColor="black" backgroundDisabledColor="0xFFFFEA" height="18"
+                enabled="false" borderThickness="0"
+                showEffect="{wipeIn}" hideEffect="{wipeOut}"/>
+            <mx:TextArea id="coordsbox" left="25" top="5" disabledColor="black" backgroundDisabledColor="0xFFFFEA" height="33"
+                width="57" enabled="false" borderThickness="0" visible="false"/>
+
         </mx:Canvas>
-        <mx:Image source="@Embed('embedded/zoomIn.svg')" left="5" top="5" click="theMap.zoomIn();"
-            rollOverEffect="glowImage" rollOutEffect="unglowImage" toolTip="{'Zoom in - currently z'+getScale()}" />
-        <mx:Image source="@Embed('embedded/zoomOut.svg')" left="5" top="22" click="theMap.zoomOut();"
-            rollOverEffect="glowImage" rollOutEffect="unglowImage" toolTip="{'Zoom out - currently z'+getScale()}" />
-        <mx:Image source="@Embed('embedded/search.svg')" left="5" top="42" click="new FindDialog().init();"
-            rollOverEffect="glowImage" rollOutEffect="unglowImage" toolTip="Find place" />
-        <mx:TextArea id="dataWorking" text="" right="5" top="5" disabledColor="black" backgroundDisabledColor="0xFFFFEA" height="18"
-            enabled="false" borderThickness="0"
-            showEffect="{wipeIn}" hideEffect="{wipeOut}"/>
-        <mx:TextArea id="coordsbox" left="25" top="5" disabledColor="black" backgroundDisabledColor="0xFFFFEA" height="33"
-            width="57" enabled="false" borderThickness="0" visible="false"/>
-
-    </mx:Canvas>
+        <potlatch2:ContextualHelp width="100%" height="30" id="contextHelp" />
+    </mx:VBox>
 
     </mx:HDividedBox>
 
                        }
                        if (objChanged) { try { obj.flush(); } catch (e:Error) {} }
 
+                       // hide contextual help if user preference
+                       if (obj.data.hasOwnProperty('hide_context_help') && obj.data['hide_context_help']) {
+                               contextHelp.visible = false;
+                               contextHelp.height  = 0;
+                       }
+
                        // map backdrop object
             var w:uint = map_area.width;
             var h:uint = map_area.height;
                        // position toolbox
                        toolbox=Toolbox(PopUpManager.createPopUp(this,Toolbox,false));
                        toolbox.init(theController);
-                       toolbox.x=stage.stageWidth-toolbox.width-5;
-                       toolbox.y=stage.stageHeight-toolbox.height-5;
-
-                       // add debug field
-                       var t:TextField=new TextField();
-                       t.width=500; t.height=150; t.border=true;
-                       t.multiline=true;
-                       _root.addChild(t);
-                       Globals.vars.debug=t;
-            t.visible = loaderInfo.parameters["show_debug"] == 'true';
-                       Globals.vars.root=theMap;       // just for the addDebug function
+                       toolbox.x=suggestToolboxX();
+                       toolbox.y=suggestToolboxY();
+                       Globals.vars.root=theMap;
 
                        // create controller
             theController = new EditController(theMap, tagViewer, toolbox);
             theController.setActive();
                        theController.addEventListener(AttentionEvent.ATTENTION, onAttention);
                        theController.addEventListener(AttentionEvent.ALERT, onAlert);
+                       theController.addEventListener(EditController.CHANGED_STATE, onStateChanged);
             
             // set the access token from saved cookie
             var tokenObject:SharedObject = SharedObject.getLocal("access_token","/");
                        stage.addChild(alert);
                }
 
+               /** ControllerState has changed, so update contextual help */
+               
+               public function onStateChanged(event:Event):void {
+                       var helpId:String = theController.state.contextualHelpId();
+                       contextHelp.selectedChild = contextHelp.hasOwnProperty("context"+helpId) ? contextHelp["context"+helpId] : contextHelp["contextNotFound"];
+               }
+
         public function onResizeMap():void {
             if ( theMap != null )
                 theMap.updateSize(map_area.width, map_area.height);
 
                        if (toolbox) {
-                               toolbox.x=Math.min(toolbox.x,stage.stageWidth-toolbox.width-5);
-                               toolbox.y=Math.min(toolbox.y,stage.stageHeight-toolbox.height-5);
+                               toolbox.x=Math.min(toolbox.x,suggestToolboxX());
+                               toolbox.y=Math.min(toolbox.y,suggestToolboxY());
                        }
         }
                private function bumpHandler(e:MapEvent):void {
-                       if (toolbox) {
-                               toolbox.y=Math.min(toolbox.y,stage.stageHeight-toolbox.height-10-e.params.y);
+                       if (toolbox) { 
+                               toolbox.y=Math.min(toolbox.y,suggestToolboxY(e.params.y+5));
                        }
                }
+               private function suggestToolboxX():int {
+                       return theMap.localToGlobal(new Point(theMap.width,theMap.height)).x - toolbox.width - 5;
+               }
+               private function suggestToolboxY(yOffset:int=0):int {
+                       return theMap.localToGlobal(new Point(theMap.width,theMap.height)).y - toolbox.height - 5 - yOffset;
+               }
 
                private function disableMapMouse():void {
                        map_area.mouseChildren=false;
index 70d3875..9e3c3d0 100644 (file)
@@ -319,6 +319,13 @@ s|FormItem {
        tabOffset: 10px;
 }
 
+.contextualHelp {
+       backgroundColor: #71A2FA;
+       color: white;
+       borderThickness: 0;
+       fontSize: 12pt;
+       textAlign: center;
+}
 
 /* Don't appear to be used */