user-definable function keys for background imagery and stylesheets
authorRichard Fairhurst <richard@systemed.net>
Sun, 28 Nov 2010 17:38:13 +0000 (17:38 +0000)
committerRichard Fairhurst <richard@systemed.net>
Sun, 28 Nov 2010 17:38:13 +0000 (17:38 +0000)
TODO.txt
net/systemeD/potlatch2/BackgroundDialog.mxml
net/systemeD/potlatch2/EditController.as
net/systemeD/potlatch2/FunctionKeyManager.as [new file with mode: 0644]
potlatch2.mxml

index 7fd5a9a..20c6e5f 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -25,7 +25,7 @@ Potlatch 2: main outstanding issues
 * Adding a relation via the advanced panel doesn't update the simple panel
 * 'Select relation' panel doesn't indicate that the list is being filtered (e.g. simple -> add to a route)
 * Checkbox needs a clear button, or to be changed to a ✓✗? triplet
-
+* Relations should talk to FunctionKeyManager too, so you can assign a route to a particular key
 
 == UI ==
 
@@ -63,6 +63,11 @@ Potlatch 2: main outstanding issues
 * Reopen?
 * Handle errors when closing bugs (especially nickname-based errors)
 
+== Code tidying ==
+
+* The imagery and stylesheet collections should each be singletons, rather than clogging up the EditController and application
+
+
 Requested enhancements
 ----------------------
 
index 7522c66..cc81eb8 100644 (file)
@@ -7,8 +7,18 @@
 
   <mx:DataGrid editable="true" width="100%" height="100%" id="dataGrid">
     <mx:columns>
-        <mx:DataGridColumn editable="true" dataField="name" headerText="Name"/>
-        <mx:DataGridColumn editable="true" dataField="url" headerText="URL"/>
+        <mx:DataGridColumn editable="true"  dataField="name" headerText="Name"/>
+        <mx:DataGridColumn editable="true"  dataField="url" headerText="URL"/>
+        <mx:DataGridColumn editable="false" headerText="Key" width="70">
+                       <mx:itemRenderer>
+                               <mx:Component>
+                               <mx:ComboBox
+                                       selectedItem="{FunctionKeyManager.instance().getKeyFor(outerDocument.title,data.name)}"
+                                   dataProvider="{FunctionKeyManager.fkeysCollection}"
+                                       change="FunctionKeyManager.instance().setKeyFromFString(selectedItem as String,outerDocument.title,data.name)" />
+                               </mx:Component>
+                       </mx:itemRenderer>
+               </mx:DataGridColumn>
     </mx:columns>
   </mx:DataGrid>
 
@@ -21,7 +31,6 @@
 
        /*
                Still to do:
-               - editable hotkeys for each layer
                - editable source tag for each layer
                - editable bbox for each layer
                - ability to use this dialogue to select as well as edit
@@ -34,6 +43,7 @@
     import mx.core.Application;
        import mx.collections.ArrayCollection;
        import mx.controls.List;
+       import net.systemeD.potlatch2.FunctionKeyManager;
 
        public var dataCollection:ArrayCollection;
        private var menu:List;
index 2f7028f..769b7c7 100644 (file)
@@ -4,6 +4,7 @@ package net.systemeD.potlatch2 {
     import net.systemeD.halcyon.connection.*;
     import net.systemeD.halcyon.VectorLayer;
     import net.systemeD.potlatch2.controller.*;
+    import net.systemeD.potlatch2.FunctionKeyManager;
        import mx.managers.CursorManager;
        import flash.events.*;
        import flash.geom.*;
@@ -78,6 +79,7 @@ package net.systemeD.potlatch2 {
         private function keyUpHandler(event:KeyboardEvent):void {
             trace("key code "+event.keyCode);
                        if (keys[event.keyCode]) { delete keys[event.keyCode]; }
+                       if (FunctionKeyManager.instance().handleKeypress(event.keyCode)) { return; }
             var newState:ControllerState = state.processKeyboardEvent(event);
             setState(newState);            
                }
diff --git a/net/systemeD/potlatch2/FunctionKeyManager.as b/net/systemeD/potlatch2/FunctionKeyManager.as
new file mode 100644 (file)
index 0000000..3020866
--- /dev/null
@@ -0,0 +1,85 @@
+package net.systemeD.potlatch2 {
+
+       import mx.collections.ArrayCollection;
+    import flash.net.SharedObject;
+       import flash.events.EventDispatcher;
+       import flash.events.Event;
+
+       /* Still to do:
+               - this is keyed by a 'name' value, e.g. 'background'/'Bing'. If the user renames the value (e.g. renames the 'Bing'
+                 layer to 'Microsoft'), the mapping will be lost
+               - the selectedItem call to getKeyFor generates one of those stupid "warning: unable to bind to property 
+                 'name' on class 'Object' (class is not an IEventDispatcher)" binding errors
+       */
+
+    public class FunctionKeyManager extends EventDispatcher {
+
+        private static const GLOBAL_INSTANCE:FunctionKeyManager = new FunctionKeyManager();
+        public static function instance():FunctionKeyManager { return GLOBAL_INSTANCE; }
+
+               public static var fkeys:Array=['','F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12','F13','F14','F15'];
+               [Bindable(event="bogus")]
+               public static var fkeysCollection:ArrayCollection=new ArrayCollection(fkeys);
+
+               private var keys:Array=[];
+               private var listeners:Object={};
+
+               public function FunctionKeyManager() {
+                       for (var i:uint=1; i<16; i++) {
+                               if (SharedObject.getLocal("user_state").data['F'+i]) {
+                                       keys[i]=SharedObject.getLocal("user_state").data['F'+i];
+                               }
+                       }
+               }
+
+               /* Register a function as the handler for all keypresses with that code (e.g. 'background') */
+
+               public function registerListener(code:String,f:Function):void {
+                       listeners[code]=f;
+               }
+               
+               /* Set the code (e.g. 'background') and value (e.g. 'Bing') associated with a key */
+
+               public function setKey(fkey:uint, code:String, value:String):void {
+                       keys[fkey]={ code:code, value:value };
+                       var obj:SharedObject=SharedObject.getLocal("user_state");
+                       obj.setProperty('F'+fkey,{ code:code, value:value });
+                       obj.flush();
+                       dispatchEvent(new Event("key_changed"));
+               }
+
+               public function setKeyFromFString(key:String, code:String, value:String):void {
+                       if (key=='') {
+                               var oldKey:String=getKeyFor(code,value);
+                               keys[Number(oldKey.substr(1))]=null;
+                               var obj:SharedObject=SharedObject.getLocal("user_state");
+                               obj.setProperty(oldKey,null);
+                               obj.flush();
+                       } else {
+                               setKey(Number(key.substr(1)),code,value);
+                       }
+               }
+
+               /* Find what key, if any, is currently assigned to a given code and value */
+
+               [Bindable(event="key_changed")]
+               public function getKeyFor(code:String, value:String):String {
+                       for (var i:uint=1; i<16; i++) {
+                               if (keys[i] && keys[i].code==code && keys[i].value==value) { return 'F'+i; }
+                       }
+                       return '';
+               }
+
+               /* Dispatch function triggered by this key */
+               
+               public function handleKeypress(keycode:uint):Boolean {
+                       if (keycode<112 || keycode>126) { return false; }
+                       var fkey:uint=keycode-111;
+                       if (!keys[fkey]) { return false; }
+                       if (keys[fkey].value=='') { return false; }
+                       listeners[keys[fkey].code](keys[fkey].value);
+                       return true;
+               }
+               
+       }
+}
index 32d5fe3..bb3e968 100644 (file)
             if (!backgroundSet && loaderInfo.parameters['yahoo_default'] == 'true') {
                 setBackground(theController.imagery[1]);
             }
+                       FunctionKeyManager.instance().registerListener('Background imagery',
+                               function(o:String):void { setBackground(findBackgroundWithName(o)); });
                }
                
                public function setBackground(bg:Object):void {
                        obj.setProperty('background_name',String(bg.name));
                        obj.flush();
                }
+               
+               private function findBackgroundWithName(name:String):Object {
+                       for each (var bg:Object in theController.imagery) {
+                               if (bg.name==name) { return bg; }
+                       }
+                       return { url:'' };
+               }
 
                public function getAvailableImagery():Array {
                        var available:Array=[];
                 setStylesheet('Potlatch','potlatch.css');
               }
             }
+                       FunctionKeyManager.instance().registerListener('Map style',
+                               function(o:String):void { setStylesheet(o,findStylesheetURLWithName(o)); });
                }
 
                public function setStylesheet(name:String,url:String):void {
                        obj.flush();
                }
 
+               private function findStylesheetURLWithName(name:String):String {
+                       for each (var ss:Object in theController.stylesheets) {
+                               if (ss.name==name) { return ss.url; }
+                       }
+                       return '';
+               }
+
                private function scaleHandler(event:MapEvent):void {
                        dispatchEvent(new Event("rescale"));
                }