<<>> <> <> <> <<>> <> <<>> DIRECTORY DeviceClassTypes, DeviceTypes, WacomDevice, Rope; WacomDeviceImpl: CEDAR PROGRAM IMPORTS EXPORTS WacomDevice, DeviceTypes = BEGIN Device: TYPE = DeviceTypes.Device; DeviceObj: TYPE = DeviceTypes.DeviceObj; DeviceClass: PUBLIC TYPE = DeviceClassTypes.DeviceClass; DeviceClassObj: PUBLIC TYPE = DeviceClassTypes.DeviceClassObj; DeviceState: TYPE = DeviceTypes.DeviceState; DeviceStateObj: TYPE = DeviceTypes.DeviceStateObj; DeviceStateChange: TYPE = DeviceTypes.DeviceStateChange; DeviceStateChangeObj: TYPE = DeviceTypes.DeviceStateChangeObj; ROPE: TYPE = Rope.ROPE; WacomData: TYPE = REF WacomDataObj; WacomDataObj: TYPE = RECORD [ name: ROPE ]; WacomState: TYPE = REF WacomStateObj; WacomStateObj: TYPE = RECORD [ x, y: INTEGER, -- pen coordinates xValid, yValid: BOOL ¬ FALSE, p: INTEGER -- pressure IN approximately [-32 .. 32] ]; wacomClass: DeviceClass ¬ NEW[DeviceClassObj ¬ [$Wacom, GetWacomState]]; <> <<>> GetWacomState: DeviceClassTypes.GetDeviceStateProc = { <> state ¬ AllocateState[device]; }; CreateWacom: PUBLIC PROC [name: Rope.ROPE] RETURNS [device: Device] = { <> data: WacomData ¬ NEW[WacomDataObj ¬ [name: name]]; device ¬ NEW[DeviceObj]; device.class ¬ wacomClass; device.data ¬ data; device.name ¬ name; }; AllocateState: PUBLIC PROC [device: Device] RETURNS [deviceState: DeviceState] = { <> state: WacomState ¬ NEW[WacomStateObj ¬ [p: minPressure, x: 0, xValid: FALSE, y: 0, yValid: FALSE]]; deviceState ¬ NEW[DeviceStateObj]; deviceState.class ¬ device.class; deviceState.state ¬ state; }; <<>> CopyState: PROC [deviceState: DeviceState] RETURNS [copy: DeviceState] = { old: WacomState ¬ NARROW[deviceState.state]; state: WacomState ¬ NEW[WacomStateObj ¬ [p: old.p, x: old.x, xValid: old.xValid, y: old.y, yValid: old.yValid]]; copy ¬ NEW[DeviceStateObj]; copy.class ¬ deviceState.class; copy.state ¬ state; }; <> <<>> PenXChange: PUBLIC PROC [x: INTEGER] RETURNS [change: DeviceStateChange] = { change ¬ PenXChangeCreate[x]; }; PenYChange: PUBLIC PROC [y: INTEGER] RETURNS [change: DeviceStateChange] = { change ¬ PenYChangeCreate[y]; }; PressureChange: PUBLIC PROC [p: INTEGER] RETURNS [change: DeviceStateChange] = { change ¬ IF p <= minPressure THEN minPChange ELSE IF p >= maxPressure THEN maxPChange ELSE PressureChangeCreate[p]; }; PenXChangeCreate: PROC [x: INTEGER] RETURNS [dsChange: DeviceStateChange] ~ { change: WacomChange ¬ NEW[WacomChangeObj]; change.type ¬ penX; change.x ¬ x; dsChange ¬ NEW[DeviceStateChangeObj]; dsChange.class ¬ wacomClass; dsChange.change ¬ change; }; PenYChangeCreate: PROC [y: INTEGER] RETURNS [dsChange: DeviceStateChange] ~ { change: WacomChange ¬ NEW[WacomChangeObj]; change.type ¬ penY; change.y ¬ y; dsChange ¬ NEW[DeviceStateChangeObj]; dsChange.class ¬ wacomClass; dsChange.change ¬ change; }; PressureChangeCreate: PROC [p: INTEGER] RETURNS [dsChange: DeviceStateChange] ~ { change: WacomChange ¬ NEW[WacomChangeObj]; change.type ¬ pressure; change.p ¬ p; dsChange ¬ NEW[DeviceStateChangeObj]; dsChange.class ¬ wacomClass; dsChange.change ¬ change; }; WacomChange: TYPE = REF WacomChangeObj; WacomChangeObj: TYPE = RECORD [ type: ChangeType, x, y: INTEGER ¬ 0, p: INTEGER ¬ minPressure ]; ChangeType: TYPE = {penX, penY, pressure}; StateAfterChange: PUBLIC PROC [deviceState: DeviceState, change: DeviceStateChange] RETURNS [newDeviceState: DeviceState] = { ftChange: WacomChange ¬ NARROW[change.change]; SELECT ftChange.type FROM penX => newDeviceState ¬ PenXMotion[deviceState, ftChange.x]; penY => newDeviceState ¬ PenYMotion[deviceState, ftChange.y]; pressure => newDeviceState ¬ PressureMotion[deviceState, ftChange.p]; ENDCASE => ERROR; }; ExpandedChange: TYPE = WacomDevice.ExpandedChange; UnpackChange: PUBLIC PROC [change: DeviceStateChange] RETURNS [expanded: ExpandedChange] = { ftChange: WacomChange ¬ NARROW[change.change]; SELECT ftChange.type FROM penX => expanded ¬ [penX[ftChange.x]]; penY => expanded ¬ [penY[ftChange.y]]; pressure => expanded ¬ [pressure[ftChange.p]]; ENDCASE => ERROR; }; <> PenXMotion: PROC [deviceState: DeviceState, x: INTEGER] RETURNS [newDeviceState: DeviceState] = { newState: WacomState; newDeviceState ¬ CopyState[deviceState]; newState ¬ NARROW[newDeviceState.state]; newState.x ¬ x; newState.xValid ¬ TRUE; }; PenYMotion: PROC [deviceState: DeviceState, y: INTEGER] RETURNS [newDeviceState: DeviceState] = { newState: WacomState; newDeviceState ¬ CopyState[deviceState]; newState ¬ NARROW[newDeviceState.state]; newState.y ¬ y; newState.yValid ¬ TRUE; }; PressureMotion: PROC [deviceState: DeviceState, p: INTEGER] RETURNS [newDeviceState: DeviceState] = { newState: WacomState; newDeviceState ¬ CopyState[deviceState]; newState ¬ NARROW[newDeviceState.state]; newState.p ¬ p; }; <> <<>> IsComplete: PUBLIC PROC [deviceState: DeviceState] RETURNS [BOOL] = { state: WacomState ¬ NARROW[deviceState.state]; RETURN[state.xValid AND state.yValid]; }; GetPen: PUBLIC PROC [deviceState: DeviceState] RETURNS [x, y, p: INTEGER] = { state: WacomState ¬ NARROW[deviceState.state]; x ¬ state.x; y ¬ state.y; p ¬ state.p; }; <> minPressure: INT = -30; -- or less means no pressure maxPressure: INT = 30; -- or greater means maximum pressure minPChange: DeviceStateChange = PressureChangeCreate[minPressure]; maxPChange: DeviceStateChange = PressureChangeCreate[maxPressure]; END.