001package jmri.jmrit.throttle;
002
003import java.awt.event.KeyEvent;
004
005import javax.swing.KeyStroke;
006
007import org.jdom2.Element;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011/**
012 * A class to store JMRI throttles keyboard shortcuts
013 * 
014 * @author Lionel Jeanson - 2021
015 * 
016 */
017public class ThrottlesPreferencesWindowKeyboardControls implements Cloneable {
018    
019    // speed multiplier
020    private float moreSpeedMultiplier = 5f;
021    
022    //
023    // shortcuts stored as arrays of pairs [modifier][key]
024    //
025    // all bellow defaults are extracted from previous existing code
026    //
027    // moving through throttle windows
028    private int[][] nextThrottleWindowKeys = { 
029        {0,KeyEvent.VK_INSERT}
030    };
031    private int[][] prevThrottleWindowKeys = { 
032        {0,KeyEvent.VK_DELETE}
033    };
034    // moving through 1 throttle window frames
035    private int[][] nextThrottleFrameKeys = { 
036        {0,KeyEvent.VK_END}
037    };
038    private int[][] prevThrottleFrameKeys = { 
039        {0,KeyEvent.VK_HOME}
040    };
041    // moving through running throttle frames
042    private int[][] nextRunThrottleFrameKeys = {
043        {KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_END}
044    };
045    private int[][] prevRunThrottleFrameKeys = {
046        {KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_HOME}
047    };      
048    
049    // moving through internal windows
050    private int[][] nextThrottleInternalWindowKeys = { 
051        {0,KeyEvent.VK_K},
052        {0,KeyEvent.VK_TAB}
053    };
054    private int[][] prevThrottleInternalWindowKeys = { 
055        {0,KeyEvent.VK_L},
056        {KeyEvent.SHIFT_DOWN_MASK, KeyEvent.VK_TAB}          
057    };
058    
059    // select internal window
060    private int[][] moveToControlPanelKeys = { 
061        {0,KeyEvent.VK_C}
062    };
063    private int[][] moveToFunctionPanelKeys = { 
064        {0,KeyEvent.VK_F}
065    };
066    private int[][] moveToAddressPanelKeys=  { 
067        {0,KeyEvent.VK_A}
068    };
069    
070    
071    // Speed
072    private int[][] reverseKeys = { 
073        {0,KeyEvent.VK_DOWN} // Down arrow
074    }; 
075    private int[][] forwardKeys = { 
076        {0,KeyEvent.VK_UP} // Up arrow
077    };
078    private int[][] switchDirectionKeys = { 
079    };         
080    
081    private int[][] idleKeys = {
082        {0,KeyEvent.VK_MULTIPLY},  // numpad *
083        {0,KeyEvent.VK_SPACE}
084    };
085    private int[][] stopKeys=  {
086        {0,KeyEvent.VK_DIVIDE}, // numpad /
087        {0,KeyEvent.VK_ESCAPE}
088    };
089    
090    private int[][] accelerateKeys = {
091        {0,KeyEvent.VK_ADD},  // numpad +
092        {0,KeyEvent.VK_LEFT}
093    };
094    private int[][] decelerateKeys = {
095        {0,KeyEvent.VK_SUBTRACT}, // numpad -;
096        {0,KeyEvent.VK_RIGHT}
097    };
098    private int[][] accelerateMoreKeys = {
099        {0,KeyEvent.VK_PAGE_UP},
100        {KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_LEFT}
101    };
102    private int[][] decelerateMoreKeys = {
103        {0,KeyEvent.VK_PAGE_DOWN},
104        {KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_RIGHT}
105    };    
106    
107    // function buttons
108    private int[][][] functionsKeys = { 
109        {{0,KeyEvent.VK_NUMPAD0}}, // F0
110        {{0,KeyEvent.VK_F1},{0,KeyEvent.VK_NUMPAD1}}, // F1
111        {{0,KeyEvent.VK_F2},{0,KeyEvent.VK_NUMPAD2}}, // F2
112        {{0,KeyEvent.VK_F3},{0,KeyEvent.VK_NUMPAD3}}, // F3
113        {{0,KeyEvent.VK_F4},{0,KeyEvent.VK_NUMPAD4}}, // F4
114        {{0,KeyEvent.VK_F5},{0,KeyEvent.VK_NUMPAD5}}, // F5
115        {{0,KeyEvent.VK_F6},{0,KeyEvent.VK_NUMPAD6}}, // F6
116        {{0,KeyEvent.VK_F7},{0,KeyEvent.VK_NUMPAD7}}, // F7
117        {{0,KeyEvent.VK_F8},{0,KeyEvent.VK_NUMPAD8}}, // F8
118        {{0,KeyEvent.VK_F9},{0,KeyEvent.VK_NUMPAD9}}, // F9
119        {{0,KeyEvent.VK_F10},{0,KeyEvent.VK_DECIMAL},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD0}}, // F10
120        {{0,KeyEvent.VK_F11},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F1},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD1}}, // F11
121        {{0,KeyEvent.VK_F12},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F2},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD2}}, // F12
122        {{0,KeyEvent.VK_F13},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F3},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD3}}, // F13
123        {{0,KeyEvent.VK_F14},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F4},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD4}}, // F14
124        {{0,KeyEvent.VK_F15},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F5},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD5}}, // F15
125        {{0,KeyEvent.VK_F16},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F6},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD6}}, // F16
126        {{0,KeyEvent.VK_F17},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F7},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD7}}, // F17
127        {{0,KeyEvent.VK_F18},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F8},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD8}}, // F18
128        {{0,KeyEvent.VK_F19},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_F9},{KeyEvent.SHIFT_DOWN_MASK,KeyEvent.VK_NUMPAD9}}, // F19
129        {{0,KeyEvent.VK_F20},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F10},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD0}}, // F20
130        {{0,KeyEvent.VK_F21},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F1},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD1}}, // F21
131        {{0,KeyEvent.VK_F22},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F2},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD2}}, // F22
132        {{0,KeyEvent.VK_F23},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F3},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD3}}, // F23
133        {{0,KeyEvent.VK_F24},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F4},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD4}}, // F24
134        {{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F5},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD5}}, // F25
135        {{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F6},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD6}}, // F26
136        {{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F7},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD7}}, // F27
137        {{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F8},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD8}}  // F28 
138        // simply add more lines for more functions controls...
139        // {{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_F9},{KeyEvent.CTRL_DOWN_MASK,KeyEvent.VK_NUMPAD9}}, // F29
140    };
141        
142    /**
143     * @return the nextThrottleWindowKeys
144     */
145    public int[][] getNextThrottleWindowKeys() {
146        return nextThrottleWindowKeys;
147    }
148
149    /**
150     * @return the prevThrottleWindowKeys
151     */
152    public int[][] getPrevThrottleWindowKeys() {
153        return prevThrottleWindowKeys;
154    }
155
156    /**
157     * @return the nextThrottleFrameKeys
158     */
159    public int[][] getNextThrottleFrameKeys() {
160        return nextThrottleFrameKeys;
161    }
162
163    /**
164     * @return the prevThrottleFrameKeys
165     */
166    public int[][] getPrevThrottleFrameKeys() {
167        return prevThrottleFrameKeys;
168    }
169
170    /**
171     * @return the nextRunThrottleFrameKeys
172     */
173    public int[][] getNextRunThrottleFrameKeys() {
174        return nextRunThrottleFrameKeys;
175    }
176
177    /**
178     * @return the prevRunThrottleFrameKeys
179     */
180    public int[][] getPrevRunThrottleFrameKeys() {
181        return prevRunThrottleFrameKeys;
182    }
183
184    /**
185     * @return the nextThrottleInternalWindowKeys
186     */
187    public int[][] getNextThrottleInternalWindowKeys() {
188        return nextThrottleInternalWindowKeys;
189    }
190
191    /**
192     * @return the prevThrottleInternalWindowKeys
193     */
194    public int[][] getPrevThrottleInternalWindowKeys() {
195        return prevThrottleInternalWindowKeys;
196    }
197
198    /**
199     * @return the moveToControlPanelKeys
200     */
201    public int[][] getMoveToControlPanelKeys() {
202        return moveToControlPanelKeys;
203    }
204
205    /**
206     * @return the moveToFunctionPanelKeys
207     */
208    public int[][] getMoveToFunctionPanelKeys() {
209        return moveToFunctionPanelKeys;
210    }
211
212    /**
213     * @return the moveToAddressPanelKeys
214     */
215    public int[][] getMoveToAddressPanelKeys() {
216        return moveToAddressPanelKeys;
217    }
218
219    /**
220     * @return the reverseKeys
221     */
222    public int[][] getReverseKeys() {
223        return reverseKeys;
224    }
225
226    /**
227     * @return the forwardKeys
228     */
229    public int[][] getForwardKeys() {
230        return forwardKeys;
231    }
232
233    /**
234     * @return the switchDirectionKeys
235     */
236    public int[][] getSwitchDirectionKeys() {
237        return switchDirectionKeys;
238    }
239
240    /**
241     * @return the idleKeys
242     */
243    public int[][] getIdleKeys() {
244        return idleKeys;
245    }
246
247    /**
248     * @return the stopKeys
249     */
250    public int[][] getStopKeys() {
251        return stopKeys;
252    }
253
254    /**
255     * @return the accelerateKeys
256     */
257    public int[][] getAccelerateKeys() {
258        return accelerateKeys;
259    }
260
261    /**
262     * @return the decelerateKeys
263     */
264    public int[][] getDecelerateKeys() {
265        return decelerateKeys;
266    }
267
268    /**
269     * @return the accelerateMoreKeys
270     */
271    public int[][] getAccelerateMoreKeys() {
272        return accelerateMoreKeys;
273    }
274
275    /**
276     * @return the decelerateMoreKeys
277     */
278    public int[][] getDecelerateMoreKeys() {
279        return decelerateMoreKeys;
280    }
281
282    /**
283     * @param fn function number
284     * @return the functionsKeys
285     */
286    public int[][] getFunctionsKeys(int fn) {
287        return functionsKeys[fn];
288    }
289    
290    public KeyStroke[] getKeyStrokes(String evtString) {
291        int [][] keys = null;
292        boolean onKeyRelease = true;
293        switch (evtString) {
294            // Throttle commands
295            case "accelerate"      : keys = getAccelerateKeys(); onKeyRelease = false; break;
296            case "decelerate"      : keys = getDecelerateKeys(); onKeyRelease = false; break;
297            case "accelerateMore"  : keys = getAccelerateMoreKeys(); onKeyRelease = false; break;
298            case "decelerateMore"  : keys = getDecelerateMoreKeys(); onKeyRelease = false; break;
299            case "idle"            : keys = getIdleKeys(); break;
300            case "stop"            : keys = getStopKeys(); break;
301            case "forward"         : keys = getForwardKeys(); break;
302            case "reverse"         : keys = getReverseKeys(); break;
303            case "switchDirection" : keys = getSwitchDirectionKeys(); break;
304            // Throttle inner window cycling
305            case "nextJInternalFrame"     : keys = getNextThrottleInternalWindowKeys(); break;
306            case "previousJInternalFrame" : keys = getPrevThrottleInternalWindowKeys(); break;
307            case "showControlPanel"       : keys = getMoveToControlPanelKeys(); break;
308            case "showFunctionPanel"      : keys = getMoveToFunctionPanelKeys(); break;
309            case "showAddressPanel"       : keys = getMoveToAddressPanelKeys(); break;
310            // Throttle frames
311            case "nextThrottleFrame"            : keys = getNextThrottleFrameKeys(); break;
312            case "previousThrottleFrame"        : keys = getPrevThrottleFrameKeys(); break;
313            case "nextRunningThrottleFrame"     : keys = getNextRunThrottleFrameKeys(); break;
314            case "previousRunningThrottleFrame" : keys = getPrevRunThrottleFrameKeys(); break;       
315            // Throttle windows
316            case "nextThrottleWindow"     : keys = getNextThrottleWindowKeys(); break;
317            case "previousThrottleWindow" : keys = getPrevThrottleWindowKeys(); break;
318            default:
319        }
320        // function buttons
321        if (evtString.matches("fn_.*_.*")) {
322            String[]tokens = evtString.split("_");
323            keys = functionsKeys[Integer.parseInt(tokens[1])];
324            if("Pressed".equals(tokens[2])) {
325                onKeyRelease = false;
326            } 
327        }
328        if (keys == null) {       
329            return new KeyStroke[0];
330        }        
331        KeyStroke[] ks = new KeyStroke[keys.length];
332        for (int i = 0 ; i < ks.length; i++) {
333            ks[i] = KeyStroke.getKeyStroke(keys[i][1], keys[i][0], onKeyRelease);
334        }
335        return ks;
336    }    
337    
338    /**
339     * @return the number of functions shortcuts
340     */
341    public int getNbFunctionsKeys() {
342        return functionsKeys.length;
343    }
344
345    /**
346     * @param fn the function numbers
347     * @param aFunctionsKeys the functionsKeys to set
348     */
349    public void setFunctionsKeys(int fn, int[][] aFunctionsKeys) {
350        this.functionsKeys[fn] = aFunctionsKeys;
351    }
352    
353    /**
354     * @return the moreSpeedMultiplier
355     */
356    public float getMoreSpeedMultiplier() {
357        return moreSpeedMultiplier;
358    }
359
360    /**
361     * @param moreSpeedMultiplier the moreSpeedMultiplier to set
362     */
363    public void setMoreSpeedMultiplier(float moreSpeedMultiplier) {
364        this.moreSpeedMultiplier = moreSpeedMultiplier;
365    }
366
367    /**
368     * @param nextThrottleWindowKeys the nextThrottleWindowKeys to set
369     */
370    public void setNextThrottleWindowKeys(int[][] nextThrottleWindowKeys) {
371        this.nextThrottleWindowKeys = nextThrottleWindowKeys;
372    }
373
374    /**
375     * @param prevThrottleWindowKeys the prevThrottleWindowKeys to set
376     */
377    public void setPrevThrottleWindowKeys(int[][] prevThrottleWindowKeys) {
378        this.prevThrottleWindowKeys = prevThrottleWindowKeys;
379    }
380
381    /**
382     * @param nextTrottleFrameKeys the nextThrottleFrameKeys to set
383     */
384    public void setNextTrottleFrameKeys(int[][] nextTrottleFrameKeys) {
385        this.nextThrottleFrameKeys = nextTrottleFrameKeys;
386    }
387
388    /**
389     * @param prevThrottleFrameKeys the prevThrottleFrameKeys to set
390     */
391    public void setPrevThrottleFrameKeys(int[][] prevThrottleFrameKeys) {
392        this.prevThrottleFrameKeys = prevThrottleFrameKeys;
393    }
394
395    /**
396     * @param nextRunThrottleFrameKeys the nextRunThrottleFrameKeys to set
397     */
398    public void setNextRunThrottleFrameKeys(int[][] nextRunThrottleFrameKeys) {
399        this.nextRunThrottleFrameKeys = nextRunThrottleFrameKeys;
400    }
401
402    /**
403     * @param prevRunThrottleFrameKeys the prevRunThrottleFrameKeys to set
404     */
405    public void setPrevRunThrottleFrameKeys(int[][] prevRunThrottleFrameKeys) {
406        this.prevRunThrottleFrameKeys = prevRunThrottleFrameKeys;
407    }
408
409    /**
410     * @param nextThrottleInternalWindowKeys the nextThrottleInternalWindowKeys to set
411     */
412    public void setNextThrottleInternalWindowKeys(int[][] nextThrottleInternalWindowKeys) {
413        this.nextThrottleInternalWindowKeys = nextThrottleInternalWindowKeys;
414    }
415
416    /**
417     * @param prevThrottleInternalWindowKeys the prevThrottleInternalWindowKeys to set
418     */
419    public void setPrevThrottleInternalWindowKeys(int[][] prevThrottleInternalWindowKeys) {
420        this.prevThrottleInternalWindowKeys = prevThrottleInternalWindowKeys;
421    }
422
423    /**
424     * @param moveToControlPanelKeys the moveToControlPanelKeys to set
425     */
426    public void setMoveToControlPanelKeys(int[][] moveToControlPanelKeys) {
427        this.moveToControlPanelKeys = moveToControlPanelKeys;
428    }
429
430    /**
431     * @param moveToFunctionPanelKeys the moveToFunctionPanelKeys to set
432     */
433    public void setMoveToFunctionPanelKeys(int[][] moveToFunctionPanelKeys) {
434        this.moveToFunctionPanelKeys = moveToFunctionPanelKeys;
435    }
436
437    /**
438     * @param moveToAddressPanelKeys the moveToAddressPanelKeys to set
439     */
440    public void setMoveToAddressPanelKeys(int[][] moveToAddressPanelKeys) {
441        this.moveToAddressPanelKeys = moveToAddressPanelKeys;
442    }
443
444    /**
445     * @param reverseKeys the reverseKeys to set
446     */
447    public void setReverseKeys(int[][] reverseKeys) {
448        this.reverseKeys = reverseKeys;
449    }
450
451    /**
452     * @param forwardKeys the forwardKeys to set
453     */
454    public void setForwardKeys(int[][] forwardKeys) {
455        this.forwardKeys = forwardKeys;
456    }
457
458    /**
459     * @param switchDirectionKeys the switchDirectionKeys to set
460     */
461    public void setSwitchDirectionKeys(int[][] switchDirectionKeys) {
462        this.switchDirectionKeys = switchDirectionKeys;
463    }
464
465    /**
466     * @param idleKeys the idleKeys to set
467     */
468    public void setIdleKeys(int[][] idleKeys) {
469        this.idleKeys = idleKeys;
470    }
471
472    /**
473     * @param stopKeys the stopKeys to set
474     */
475    public void setStopKeys(int[][] stopKeys) {
476        this.stopKeys = stopKeys;
477    }
478
479    /**
480     * @param accelerateKeys the accelerateKeys to set
481     */
482    public void setAccelerateKeys(int[][] accelerateKeys) {
483        this.accelerateKeys = accelerateKeys;
484    }
485
486    /**
487     * @param decelerateKeys the decelerateKeys to set
488     */
489    public void setDecelerateKeys(int[][] decelerateKeys) {
490        this.decelerateKeys = decelerateKeys;
491    }
492
493    /**
494     * @param accelerateMoreKeys the accelerateMoreKeys to set
495     */
496    public void setAccelerateMoreKeys(int[][] accelerateMoreKeys) {
497        this.accelerateMoreKeys = accelerateMoreKeys;
498    }
499
500    /**
501     * @param decelerateMoreKeys the decelerateMoreKeys to set
502     */
503    public void setDecelerateMoreKeys(int[][] decelerateMoreKeys) {
504        this.decelerateMoreKeys = decelerateMoreKeys;
505    }
506    
507    @Override
508    public ThrottlesPreferencesWindowKeyboardControls clone() throws CloneNotSupportedException {
509        ThrottlesPreferencesWindowKeyboardControls ret = (ThrottlesPreferencesWindowKeyboardControls) super.clone();    
510        
511        ret.moreSpeedMultiplier = this.moreSpeedMultiplier;        
512        ret.nextThrottleWindowKeys = clone(this.nextThrottleWindowKeys);
513        ret.prevThrottleWindowKeys = clone(this.prevThrottleWindowKeys);        
514        ret.nextThrottleFrameKeys = clone(this.nextThrottleFrameKeys);    
515        ret.prevThrottleFrameKeys = clone(this.prevThrottleFrameKeys);    
516        ret.nextRunThrottleFrameKeys = clone(this.nextRunThrottleFrameKeys);    
517        ret.prevRunThrottleFrameKeys = clone(this.prevRunThrottleFrameKeys);
518        ret.nextThrottleInternalWindowKeys  = clone(this.nextThrottleInternalWindowKeys);
519        ret.prevThrottleInternalWindowKeys = clone(this.prevThrottleInternalWindowKeys);
520        ret.moveToControlPanelKeys = clone(this.moveToControlPanelKeys);
521        ret.moveToFunctionPanelKeys = clone(this.moveToFunctionPanelKeys);
522        ret.moveToAddressPanelKeys = clone(this.moveToAddressPanelKeys);
523        ret.reverseKeys = clone(this.reverseKeys);
524        ret.forwardKeys = clone(this.forwardKeys);
525        ret.switchDirectionKeys = clone(this.switchDirectionKeys);
526        ret.idleKeys = clone(this.idleKeys);
527        ret.stopKeys = clone(this.stopKeys);
528        ret.accelerateKeys = clone(this.accelerateKeys);
529        ret.decelerateKeys = clone(this.decelerateKeys);
530        ret.accelerateMoreKeys = clone(this.accelerateMoreKeys);
531        ret.decelerateMoreKeys = clone(this.decelerateMoreKeys);
532        ret.functionsKeys = new int[this.functionsKeys.length][0][0];
533        for (int i=0; i<this.functionsKeys.length; i++) {
534            ret.functionsKeys[i] = clone(this.functionsKeys[i]);
535        }
536        return ret;
537    }
538
539    private int[][] clone(int[][] from) {
540        int[][] to = new int[from.length][2];
541        for (int i=0;i<from.length;i++) {            
542            to[i][0] = from[i][0];
543            to[i][1] = from[i][1];
544        }
545        return to;
546    }
547    
548    private Element getControlXml(String eltname, int[][] controls) {        
549        java.util.ArrayList<Element> children = new java.util.ArrayList<>(controls.length);
550        for (int i=0;i<controls.length;i++) {
551            org.jdom2.Element e = new org.jdom2.Element("ksc-"+i);
552            e.setAttribute("m",""+controls[i][0]);
553            e.setAttribute("k",""+controls[i][1]);
554            children.add(e);
555        }
556        org.jdom2.Element e = new org.jdom2.Element(eltname);
557        e.setContent(children);
558        return e;
559    }
560    
561    Element store() {
562        java.util.ArrayList<Element> children = new java.util.ArrayList<>(10);
563        children.add( getControlXml("nextThrottleWindowKeys", nextThrottleWindowKeys));
564        children.add( getControlXml("prevThrottleWindowKeys", prevThrottleWindowKeys));
565        children.add( getControlXml("nextThrottleFrameKeys", nextThrottleFrameKeys));
566        children.add( getControlXml("prevThrottleFrameKeys", prevThrottleFrameKeys));
567        children.add( getControlXml("nextRunThrottleFrameKeys", nextRunThrottleFrameKeys));
568        children.add( getControlXml("prevRunThrottleFrameKeys", prevRunThrottleFrameKeys));
569        children.add( getControlXml("nextThrottleInternalWindowKeys", nextThrottleInternalWindowKeys));
570        children.add( getControlXml("prevThrottleInternalWindowKeys", prevThrottleInternalWindowKeys));
571        children.add( getControlXml("moveToControlPanelKeys", moveToControlPanelKeys));
572        children.add( getControlXml("moveToFunctionPanelKeys", moveToFunctionPanelKeys));
573        children.add( getControlXml("moveToAddressPanelKeys", moveToAddressPanelKeys));
574        children.add( getControlXml("reverseKeys", reverseKeys));
575        children.add( getControlXml("forwardKeys", forwardKeys));
576        children.add( getControlXml("switchDirectionKeys", switchDirectionKeys));
577        children.add( getControlXml("idleKeys", idleKeys));
578        children.add( getControlXml("stopKeys", stopKeys));
579        children.add( getControlXml("accelerateKeys", accelerateKeys));
580        children.add( getControlXml("decelerateKeys", decelerateKeys));
581        children.add( getControlXml("accelerateMoreKeys", accelerateMoreKeys));
582        children.add( getControlXml("decelerateMoreKeys", decelerateMoreKeys));
583        for (int i=0;i<functionsKeys.length;i++) {
584            children.add( getControlXml("functionsKeys-"+i, functionsKeys[i]));
585        }
586        org.jdom2.Element e = new org.jdom2.Element("throttlesControls");
587        e.setAttribute("moreSpeedMultiplier",""+moreSpeedMultiplier);
588        e.setContent(children);
589        return e;        
590    }
591    
592    private int[][] createControlFromXml(Element child) {
593        int[][] ret = new int[child.getChildren().size()][2];
594        int i=0;
595        for (Element e : child.getChildren()) {
596            ret[i][0] = Integer.parseInt(e.getAttributeValue("m"));
597            ret[i][1] = Integer.parseInt(e.getAttributeValue("k"));
598            i++;
599        }
600        
601        return ret;
602    }
603
604    public void load(org.jdom2.Element e) {
605        if ((e == null) || (e.getChildren().isEmpty())) {
606            return;
607        }
608        try {
609            nextThrottleWindowKeys = createControlFromXml(e.getChild("nextThrottleWindowKeys"));
610            prevThrottleWindowKeys = createControlFromXml(e.getChild("prevThrottleWindowKeys"));
611            nextThrottleFrameKeys = createControlFromXml(e.getChild("nextThrottleFrameKeys"));
612            prevThrottleFrameKeys = createControlFromXml(e.getChild("prevThrottleFrameKeys"));
613            nextRunThrottleFrameKeys = createControlFromXml(e.getChild("nextRunThrottleFrameKeys"));
614            prevRunThrottleFrameKeys = createControlFromXml(e.getChild("prevRunThrottleFrameKeys"));
615            nextThrottleInternalWindowKeys = createControlFromXml(e.getChild("nextThrottleInternalWindowKeys"));
616            prevThrottleInternalWindowKeys = createControlFromXml(e.getChild("prevThrottleInternalWindowKeys"));
617            moveToControlPanelKeys = createControlFromXml(e.getChild("moveToControlPanelKeys"));
618            moveToFunctionPanelKeys = createControlFromXml(e.getChild("moveToFunctionPanelKeys"));
619            moveToAddressPanelKeys = createControlFromXml(e.getChild("moveToAddressPanelKeys"));
620            reverseKeys = createControlFromXml(e.getChild("reverseKeys"));
621            forwardKeys = createControlFromXml(e.getChild("forwardKeys"));
622            switchDirectionKeys = createControlFromXml(e.getChild("switchDirectionKeys"));
623            idleKeys = createControlFromXml(e.getChild("idleKeys"));
624            stopKeys = createControlFromXml(e.getChild("stopKeys"));
625            accelerateKeys = createControlFromXml(e.getChild("accelerateKeys"));
626            decelerateKeys = createControlFromXml(e.getChild("decelerateKeys"));
627            accelerateMoreKeys = createControlFromXml(e.getChild("accelerateMoreKeys"));
628            decelerateMoreKeys = createControlFromXml(e.getChild("decelerateMoreKeys"));
629            for (int i=0;i<functionsKeys.length;i++) {
630                functionsKeys[i] = createControlFromXml(e.getChild("functionsKeys-"+i));
631            }
632            moreSpeedMultiplier = Float.parseFloat(e.getAttributeValue("moreSpeedMultiplier"));
633        } catch (NumberFormatException exc) {
634            log.error("Error while restoring thottle controls from xml : {}", exc.getMessage());
635        }
636        
637    }
638    
639    private final static Logger log = LoggerFactory.getLogger(ThrottlesPreferencesWindowKeyboardControls.class);
640}