001/* [{ 002Copyright 2007, 2008, 2009 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.ArrayList; 022import java.util.BitSet; 023import java.util.Collections; 024import java.util.List; 025import java.util.logging.Level; 026import java.util.logging.Logger; 027import jpen.PButton; 028import jpen.PKind; 029 030public final class PLevelEmulator{ 031 static final Logger L=Logger.getLogger(PLevelEmulator.class.getName()); 032 //static { L.setLevel(Level.ALL); } 033 034 public static class ButtonTriggerPolicy{ 035 public final int levelType; 036 public final float onPressValue; 037 public final float onReleaseValue; 038 039 public ButtonTriggerPolicy(PLevel.Type levelType, float onPressValue, float onReleaseValue){ 040 this(levelType.ordinal(), onPressValue, onReleaseValue); 041 } 042 043 public ButtonTriggerPolicy(int levelType, float onPressValue, float onReleaseValue){ 044 this.levelType=levelType; 045 this.onPressValue=onPressValue; 046 this.onReleaseValue=onReleaseValue; 047 } 048 049 @Override 050 public String toString(){ 051 return "( levelType="+levelType+", onPressValue="+onPressValue+", onReleaseValue="+onReleaseValue+" )"; 052 } 053 } 054 055 final Pen pen; 056 057 PLevelEmulator(Pen pen){ 058 this.pen=pen; 059 } 060 061 private final List<List<ButtonTriggerPolicy>> kindTypeToButtonTypeToButtonTriggerPolicy=new ArrayList<List<ButtonTriggerPolicy>>(); 062 private final List<ButtonTriggerPolicy> activeButtonTriggerPolicies=new ArrayList<ButtonTriggerPolicy>(); 063 private final BitSet activeLevelTypes=new BitSet(); 064 private final List<ButtonTriggerPolicy> kindTypeToAlwaysActiveButtonTriggerPolicy=new ArrayList<ButtonTriggerPolicy>(); 065 066 public void setPressureTriggerForLeftCursorButton(float pressure){ 067 setTriggerForLeftCursorButton(new ButtonTriggerPolicy(PLevel.Type.PRESSURE.ordinal(),pressure,0f)); 068 } 069 070 public void setTriggerForLeftCursorButton(ButtonTriggerPolicy triggerPolicy){ 071 setTrigger(PKind.Type.CURSOR.ordinal(), PButton.Type.LEFT.ordinal(), triggerPolicy, true); 072 } 073 074 public void setTrigger(PKind.Type kindType, PButton.Type buttonType, ButtonTriggerPolicy triggerPolicy){ 075 setTrigger(kindType.ordinal(), buttonType.ordinal(), triggerPolicy); 076 } 077 078 public synchronized void setTrigger(int kindType, int buttonType, ButtonTriggerPolicy triggerPolicy){ 079 setTrigger(kindType, buttonType, triggerPolicy, false); 080 } 081 082 public synchronized void setTrigger(int kindType, int buttonType, ButtonTriggerPolicy triggerPolicy, boolean alwaysActiveOnKind){ 083 List<ButtonTriggerPolicy> buttonTypeToButtonTriggerPolicy=getButtonTypeToButtonTriggerPolicy(kindType); 084 ensureListSize(buttonTypeToButtonTriggerPolicy, buttonType); 085 ButtonTriggerPolicy oldPolicy=buttonTypeToButtonTriggerPolicy.set(buttonType, triggerPolicy); 086 087 ensureListSize(kindTypeToAlwaysActiveButtonTriggerPolicy, kindType); 088 if(oldPolicy!=null){ 089 if(kindTypeToAlwaysActiveButtonTriggerPolicy.get(kindType)==oldPolicy) 090 kindTypeToAlwaysActiveButtonTriggerPolicy.set(kindType, null); 091 } 092 if(triggerPolicy!=null && alwaysActiveOnKind){ 093 kindTypeToAlwaysActiveButtonTriggerPolicy.set(kindType, triggerPolicy); 094 } 095 } 096 097 public ButtonTriggerPolicy getButtonTriggerPolicy(PKind.Type kindType, PButton.Type buttonType){ 098 return getButtonTriggerPolicy(kindType, buttonType); 099 } 100 101 public synchronized ButtonTriggerPolicy getButtonTriggerPolicy(int kindType, int buttonType){ 102 List<ButtonTriggerPolicy> buttonTypeToButtonTriggerPolicy=getButtonTypeToButtonTriggerPolicy(kindType); 103 ensureListSize(buttonTypeToButtonTriggerPolicy, buttonType); 104 return buttonTypeToButtonTriggerPolicy.get(buttonType); 105 } 106 107 private List<ButtonTriggerPolicy> getButtonTypeToButtonTriggerPolicy(int kindType){ 108 ensureListSize(kindTypeToButtonTypeToButtonTriggerPolicy, kindType); 109 List<ButtonTriggerPolicy> buttonTypeToButtonTriggerPolicy=kindTypeToButtonTypeToButtonTriggerPolicy.get(kindType); 110 if(buttonTypeToButtonTriggerPolicy==null){ 111 kindTypeToButtonTypeToButtonTriggerPolicy.set(kindType, buttonTypeToButtonTriggerPolicy=new ArrayList<ButtonTriggerPolicy>()); 112 } 113 return buttonTypeToButtonTriggerPolicy; 114 } 115 116 private static void ensureListSize(List<?> list, int index){ 117 while(list.size()<=index) 118 list.add(null); 119 } 120 121 void scheduleEmulatedEvent(PButtonEvent buttonEvent){ 122 PLevel emulatedLevel=null; 123 if(buttonEvent.button.value) 124 emulatedLevel=emulateOnPress(buttonEvent.button.typeNumber); 125 else 126 emulatedLevel=emulateOnRelease(buttonEvent.button.typeNumber); 127 if(emulatedLevel!=null){ 128 pen.penManager.scheduleLevelEvent(pen.penManager.emulationDevice, buttonEvent.time, Collections.singleton(emulatedLevel)); 129 } 130 } 131 132 private PLevel emulateOnPress(int buttonType){ 133 PenState lastScheduledState=pen.lastScheduledState; 134 ButtonTriggerPolicy triggerPolicy=getButtonTriggerPolicy( 135 lastScheduledState.getKind().typeNumber, 136 buttonType); 137 if(L.isLoggable(Level.FINE)) L.fine("triggerPolicy: "+triggerPolicy+", buttonType: "+buttonType); 138 if(triggerPolicy!=null){ 139 setActiveButtonTriggerPolicy(buttonType, triggerPolicy); 140 if(lastScheduledState.getLevelValue(triggerPolicy.levelType)== 141 triggerPolicy.onPressValue) 142 return null; 143 return new PLevel(triggerPolicy.levelType, triggerPolicy.onPressValue); 144 } 145 return null; 146 } 147 148 private void setActiveButtonTriggerPolicy(int buttonType, ButtonTriggerPolicy policy){ 149 ensureListSize(activeButtonTriggerPolicies, buttonType); 150 ButtonTriggerPolicy oldPolicy=activeButtonTriggerPolicies.set(buttonType, policy); 151 if(oldPolicy!=null){ 152 activeLevelTypes.set(oldPolicy.levelType, false); 153 } 154 if(policy!=null){ 155 activeLevelTypes.set(policy.levelType, true); 156 } 157 } 158 159 private PLevel emulateOnRelease(int buttonType){ 160 ensureListSize(activeButtonTriggerPolicies, buttonType); 161 ButtonTriggerPolicy triggerPolicy=getActiveButtonTriggerPolicy(buttonType); 162 if(L.isLoggable(Level.FINE)) L.fine("triggerPolicy: "+triggerPolicy+", buttonType: "+buttonType); 163 if(triggerPolicy!=null){ 164 setActiveButtonTriggerPolicy(buttonType, null); 165 PLevel pLevel=new PLevel(triggerPolicy.levelType, triggerPolicy.onReleaseValue); 166 return pLevel; 167 } 168 return null; 169 } 170 171 private ButtonTriggerPolicy getActiveButtonTriggerPolicy(int buttonType){ 172 ensureListSize(activeButtonTriggerPolicies, buttonType); 173 ButtonTriggerPolicy buttonTriggerPolicy=activeButtonTriggerPolicies.get(buttonType); 174 return buttonTriggerPolicy; 175 } 176 177 boolean onActivePolicy(int kindType, int levelType){ 178 return onAlwaysActivePolicy(kindType, levelType) || activeLevelTypes.get(levelType); 179 } 180 181 private boolean onAlwaysActivePolicy(int kindType, int levelType){ 182 ensureListSize(kindTypeToAlwaysActiveButtonTriggerPolicy, kindType); 183 ButtonTriggerPolicy alwaysActivePolicy=kindTypeToAlwaysActiveButtonTriggerPolicy.get(kindType); 184 return alwaysActivePolicy==null ? false : 185 alwaysActivePolicy.levelType==levelType; 186 } 187}