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.io.IOException; 022import java.io.ObjectInputStream; 023import java.util.Arrays; 024import jpen.event.PenListener; 025import jpen.internal.AccessibleField; 026 027public abstract class PenEvent 028 implements java.io.Serializable { 029 public static final long serialVersionUID=2l; 030 031 protected long time=-1; 032 transient volatile PenEvent next; 033 public final transient Pen pen; 034 private final byte deviceId; 035 private final long deviceTime; 036 private transient Object penOwnerTag; 037 038 PenEvent(PenDevice device, long deviceTime) { 039 this(device.getProvider().getConstructor().getPenManager().pen, 040 device.getId(), 041 deviceTime); 042 } 043 044 private PenEvent(Pen pen, byte deviceId, long deviceTime){ 045 this.pen=pen; 046 this.deviceId=deviceId; 047 this.deviceTime=deviceTime; 048 } 049 050 static final class Dummy 051 extends PenEvent{ 052 Dummy(){ 053 super(null, (byte)0, 0); 054 } 055 @Override 056 void copyTo(PenState penState){} 057 @Override 058 void dispatch(){} 059 } 060 061 /** 062 Returns the time in milliseconds of when this event was scheduled by the {@link Pen}. 063 */ 064 public long getTime() { 065 return time; 066 } 067 068 abstract void copyTo(PenState penState); 069 070 abstract void dispatch(); 071 072 /** 073 Returns the id of the {@link PenDevice} which generated this event. 074 075 @see #getDevice() 076 @see PenManager#getDevice(byte) 077 */ 078 public byte getDeviceId(){ 079 return deviceId; 080 } 081 082 /** 083 @throws IllegalStateException if the {@link #pen} is null. {@code pen} is null after deserialization. 084 */ 085 public PenDevice getDevice(){ 086 if(pen==null) 087 throw new IllegalStateException(); 088 return pen.penManager.getDevice(deviceId); 089 } 090 091 /** 092 Returns the timestamp in milliseconds of when this event ocurred in the {@link PenDevice}. The value returned was measured since some fixed but arbitrary time imposed by the {@link PenDevice}. 093 094 @see #getDeviceId() 095 @see #getTime() 096 */ 097 public long getDeviceTime(){ 098 return deviceTime; 099 } 100 101 /** 102 @see PenOwner#evalPenEventTag(PenEvent) 103 */ 104 void setPenOwnerTag(Object penOwnerTag){ 105 this.penOwnerTag=penOwnerTag; 106 } 107 108 Object getPenOwnerTag(){ 109 return penOwnerTag; 110 } 111 112 @Override 113 public String toString(){ 114 return "[PenEvent: deviceId="+deviceId+", deviceTime="+deviceTime+", time="+time+"]"; 115 } 116 117 private void readObject(ObjectInputStream in) 118 throws IOException, ClassNotFoundException { 119 try{ 120 ObjectInputStream.GetField fields = in.readFields(); 121 time=fields.get("time", 0l); 122 //v Backwards compatibility: 123 //vv deviceId and deviceTime are new, provide better defaults: 124 //if(fields.defaulted("deviceId")) 125 //deviceIdField.getField().set(this, fields.get("deviceId", (byte)0)); 126 if(fields.defaulted("deviceTime")) 127 deviceTimeField.getField().set(this, fields.get("deviceTime", time)); 128 //^^ 129 //^ 130 }catch(IllegalAccessException ex){ 131 throw new AssertionError(ex); 132 } 133 } 134 135 static final AccessibleField deviceIdField=new AccessibleField(PenEvent.class, "deviceId"); 136 static final AccessibleField deviceTimeField=new AccessibleField(PenEvent.class, "deviceTime"); 137}