vona.ui

Class RXSInteractor

Up to five motion types can be enabled which transform arrow keypresses, mouse drags, and mouse wheel rolls to calls to the above APIs. When an event arrives the particular motion is selected from the subset of currently enabled motions according to the state of the keyboard modifier keys CTRL, ALT, and SHIFT, as well as the state of the mouse buttons if more than one is available. The five motion types, in order, are:
  1. rotateXY - up to two incremental Euler rotations about the X and Y axes, in that order
  2. translateXY - a 2D translation in the XY plane
  3. scale - a multiplicative change in local-to-world scale
  4. rotateZ - an incremental rotation about the Z axis
  5. translateZ - an incremental translation along the Z axis.

Arrow Key Events

For arrow key events the last two types are combined into one thus reducing the total number of different motion types to four. If both Z motions are enabled, the left/right keys effect rotateZ and the up/down keys effect translateZ, otherwise all four arrow keys effect whichever Z motion is enabled. For arrow key events

When a key is held down for less than KEY_REPEAT_THRESHOLD_MS it is considered a block event and the motion is effected as an interpolated block move, e.g. rotateXYBlocks(double, double). Longer hold times are converted internally into a series of one-pixel motions at the rate KEY_TIMER_PERIOD_MS and effected as pixel events, e.g. rotateXYPixels(double, double). The typematic events of the underlying platform, if any, are detected by timing and ignored, see Sun bug ID 4153069 (open) "keyReleased behavior incorrect".

Mouse Drag Events

For mouse drag events

Mouse drags are always effected as pixel motions, never as block motions.

Mouse Wheel Events

Mouse wheel events can effect scale, rotateZ, and translateZ motions only, in that order, thus reducing the total number of motion types to three.

Mouse wheel events are always effected as block motions. Wheel rolls towards the user are converted to positive (i.e. downwards) vertical pixel blocks, and rolls away from the user are converted to negative (i.e. upwards) pixel blocks.

Acceleration/Deceleration

Block motions are always internally converted to multi-pixel motions before they are effected, and the number of pixels in any motion, whether originally a block or pixel motion, is always then multiplied by the current accelFactor. Fractional pixel motions are handled. When a block motion converts to more than interpolationThresholdPixels it is executed as an interpolation over interpolationTime, otherwise it is executed immediately as a jump.

Setting accelFactor <= 0.0 has special meaning: block motions are converted to one pixel per block, and pixel motions are not accelerated (as if accelFactor were 1.0). This enables pixel-at-a-time fine manipulation.

If accelSliderEnabled, then presses of the numeral keys change accelFactor with the 1 key giving 0 accel (the above special case), the 2 key giving 1/8 accel, the 5 key giving 1.0 accel, the 0 key giving 4.0 accel, and the other numeral keys (in keyboard order 1234567890) interpolating those values.

Unit Conversions

Rotate, Translate, and Scale block motions are converted to multi-pixel motions according to currently set factors and the currently set canvas dimensions. See setBlockRotateFactor(double), setBlockTranslateFactor(double), and setBlockScaleFactor(double) for details.

Translations are converted from pixels to world frame units (even when controlInLocalFrame or controlInManipulationFrame is set) according to the current world-to-canvas transform, which is defined by canvasSize and worldToCanvasScale. For example, these may be set according to the current world-to-canvas projection transform of a display component. The translation is then applied relative to the orientation of the world frame unless controlInLocalFrame is set, in which case the translation is relative to the current orientation of the local frame, or controlInManipulationFrame is set, in which case the translation is relative to the current orientation of the manipulation frame.

Rotations are converted from pixels to radians by taking the quotient with the corresponding dimension of the canvas: a rotation of p horizontal pixels effects a rotation of 2*PI*p/w radians in the Y axis where w is the component width; similarly for vertical pixels and rotations about the X and Z axes. Rotate motions are always through the local frame point set by setRotationCenter(double, double, double) (defaults to local frame origin) and are about world frame axes unless controlInLocalFrame is set, in which case they are about the local frame axes, or controlInManipulationFrame is set, in which case they are about the manipulation frame axes.

Scale motions are converted from pixels according to the current canvas height h: a scale motion of p (signed) pixels effects a multiplicative change of scaleBase^(p/h) in local-to-world scale. Thus when p=h, i.e. a downwards drag across the full canvas height, the local-to-world scale is multiplied by scaleBase, and when p=-h, i.e. an upwards drag across the full canvas height, the local-to-world scale is divided by scaleBase. Scale motions triggered by mouse drag or wheel events are are centered at the projection of the mouse location on the world z-plane through the current rotation center in world frame at the beginning of the motion. Scale motions triggered by key events are centered on the current rotation center in world frame.

Synchronization Policies

This class is designed to be thread-safe with internal synchronization.

The lock acquisition order for deadlock avoidance is

  1. this
  2. rxsInterpolator

Copyright (C) 2007 Marsette A. Vona, III

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

Author:
Marsette (Marty) A. Vona, III