001/* [{
002Copyright 2007, 2008 Nicolas Carranza <nicarran at gmail.com>
003
004This file is part of jpen.
005
006jpen is free software: you can redistribute it and/or modify
007it under the terms of the GNU Lesser General Public License as published by
008the Free Software Foundation, either version 3 of the License,
009or (at your option) any later version.
010
011jpen is distributed in the hope that it will be useful,
012but WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014GNU Lesser General Public License for more details.
015
016You should have received a copy of the GNU Lesser General Public License
017along with jpen.  If not, see <http://www.gnu.org/licenses/>.
018}] */
019package jpen;
020
021import java.util.Arrays;
022import java.util.Collection;
023import java.util.HashMap;
024import java.util.Map;
025
026public class PenState
027        implements java.io.Serializable {
028        public static final long serialVersionUID=1l;
029
030        public static class Levels implements java.io.Serializable {
031                public static final long serialVersionUID=1l;
032                private final float[] values=new float[PLevel.Type.VALUES.size()]; // CUSTOM type does not store value but VALUES does not have the CUSTOM
033                private final Map<Integer, Float> extTypeNumberToValue=new HashMap<Integer, Float>(2, 1); 
034
035                public void setValues(PenState penState){
036                        setValues(penState.levels);
037                }
038
039                public void setValues(PenState.Levels levels){
040                        for(int i=levels.values.length; --i>=0;)
041                                values[i]=levels.values[i];
042                        extTypeNumberToValue.clear();
043                        extTypeNumberToValue.putAll(levels.extTypeNumberToValue);
044                        for(int i=levels.values.length; i<values.length; i++){ // If a new PLevel.Type is added then transform the ext to this newer type (library backwards compat.)
045                                Float value=extTypeNumberToValue.remove(i);
046                                if(value!=null)
047                                        values[i]=value;
048                        }
049                }
050
051                public void setValues(PLevelEvent ev){
052                        setValues(ev.levels);
053                }
054
055                public final void setValues(Collection<PLevel> levels){
056                        for(PLevel level: levels){
057                                setValue(level);
058                        }
059                }
060
061                public final void setValues(PLevel[] levels){
062                        for(int i=levels.length; --i>=0; )
063                                setValue(levels[i]);
064                }
065
066                public final void setValue(PLevel level){
067                        setValue(level.typeNumber, level.value);
068                }
069
070                public final void setValue(PLevel.Type levelType, float value){
071                        setValue(levelType.ordinal(), value);
072                }
073
074                public final void setValue(int levelTypeNumber, float value){
075                        if(levelTypeNumber<values.length)
076                                values[levelTypeNumber]=value;
077                        else
078                                setExtValue(levelTypeNumber, value);
079                }
080                
081                private final void setExtValue(int levelTypeNumber, float value){
082                        extTypeNumberToValue.put(levelTypeNumber, value);
083                }
084                
085                public float getValue(PLevel.Type levelType){
086                        return getValue(levelType.ordinal()); 
087                }
088
089                public float getValue(int levelTypeNumber) {
090                        return levelTypeNumber<values.length ?
091                                                 values[levelTypeNumber]: getExtValue(levelTypeNumber);
092                }
093                
094                private float getExtValue(int extLevelTypeNumber) {
095                        Float value=extTypeNumberToValue.get(extLevelTypeNumber);
096                        return value==null? 0f: value;
097                }
098                
099                /**
100                Set all values to their defaults: 0f.
101                */
102                public void clearValues(){
103                        Arrays.fill(values, 0); 
104                        extTypeNumberToValue.clear();
105                }
106
107                @Override
108                public String toString(){
109                        return "(values="+Arrays.toString(values)+", extTypeNumberToValue="+extTypeNumberToValue+")";
110                }
111        }
112
113        private PKind kind=PKind.valueOf(PKind.Type.CURSOR);
114        final Levels levels=new Levels();
115        private final int[] buttonValues=new int[PButton.Type.VALUES.size()]; // CUSTOM type does not store value.
116        final Map<Integer, Integer> extButtonTypeNumberToValue=new HashMap<Integer, Integer>();
117        private int pressedButtonsCount;
118
119
120        PenState(){}
121
122        public float getLevelValue(PLevel.Type levelType) {
123                return levels.getValue(levelType.ordinal());
124        }
125
126        public float getLevelValue(int levelTypeNumber) {
127                return levels.getValue(levelTypeNumber);
128        }
129
130        public PKind getKind(){
131                return kind;
132        }
133
134        void setKind(PKind kind) {
135                this.kind=kind;
136        }
137
138        public boolean getButtonValue(PButton.Type buttonType) {
139                return getButtonValue(buttonType.ordinal());
140        }
141
142        public boolean getButtonValue(int  buttonTypeNumber) {
143                return (buttonTypeNumber>=buttonValues.length? getExtButtonValue(buttonTypeNumber): buttonValues[buttonTypeNumber]) > 0;
144        }
145
146        public boolean hasPressedButtons(){
147                return pressedButtonsCount>0;
148        }
149
150        public int getPressedButtonsCount(){
151                return pressedButtonsCount;
152        }
153
154        private int getExtButtonValue(int buttonTypeNumber) {
155                Integer buttonValue=extButtonTypeNumberToValue.get(buttonTypeNumber);
156                return buttonValue==null? 0: buttonValue;
157        }
158
159        boolean setButtonValue(int buttonTypeNumber, boolean value) {
160                boolean oldValue=getButtonValue(buttonTypeNumber);
161                if(buttonTypeNumber>=buttonValues.length)
162                        setExtButtonValue(buttonTypeNumber, value);
163                else {
164                        if(value){
165                                if(buttonValues[buttonTypeNumber]==0)
166                                        pressedButtonsCount++;
167                                buttonValues[buttonTypeNumber]++;
168                        }
169                        else{
170                                if(buttonValues[buttonTypeNumber]>0)
171                                        pressedButtonsCount--;
172                                buttonValues[buttonTypeNumber]=0;
173                        }
174                }
175                return oldValue!=getButtonValue(buttonTypeNumber);
176        }
177
178        private void setExtButtonValue(int buttonTypeNumber, boolean value) {
179                int currentValue=getExtButtonValue(buttonTypeNumber);
180                if(value){
181                        if(currentValue==0)
182                                pressedButtonsCount++;
183                        extButtonTypeNumberToValue.put(buttonTypeNumber, getExtButtonValue(buttonTypeNumber)+1);
184                }
185                else{
186                        if(currentValue>0)
187                                pressedButtonsCount--;
188                        extButtonTypeNumberToValue.put(buttonTypeNumber, 0);
189                }
190        }
191
192        void setValues(PenState penState){
193                levels.setValues(penState.levels);
194
195                for(int i=buttonValues.length; --i>=0;)
196                        buttonValues[i]=penState.buttonValues[i];
197                extButtonTypeNumberToValue.clear();
198                extButtonTypeNumberToValue.putAll(penState.extButtonTypeNumberToValue);
199
200                kind=penState.kind;
201        }
202
203}