// This may look like C code, but it is really -*- C++ -*-

//<copyright>
// 
// Copyright (c) 1993,94
// Institute for Information Processing and Computer Supported New Media (IICM),
// Graz University of Technology, Austria.
// 
//</copyright>

//<file>
//
// Name:        hgptrhand.h
//
// Purpose:     interface to pointer handler of 3D viewer
//
// Created:     17 Dec 92   Michael Pichler
//
// Changed:      2 Feb 95   Michael Pichler
//
//
// Description
// -----------
//
// Interface of class HG3dInputHandler.
// Responsible for handling pointer (mouse) events.
// 
//
// Style attributes (X-defaults):
//
// SpeedFactor,
// FlipFocal, WalkFocal, FlipZoom, FlipTurnHor, FlipTurnVert,
// WalkZoom, WalkTurnHor, WalkTurnVert, WalkZoom3, WalkTurnHor3, WalkTurnVert3,
// VelocityZoom,  VelocityPan,  VelocityTurnHor,  VelocityTurnVert,
// VelocityZoom3, VelocityPan3, VelocityTurnHor3, VelocityTurnVert3,
// FlyDeadX, FlyDeadY, FlySpeedInc, FlyTurnHor, FlyTurnVert,
// FlyToTran, FlyToRot
//
//
//</file>



#ifndef hg_viewer_hg3d_hgptrhand_h
#define hg_viewer_hg3d_hgptrhand_h


#include <InterViews/input.h>
#include <InterViews/window.h>
class Event;
class Glyph;
class Style;

#include <ge3d/vectors.h>

class SceneWindow;
class Camera;
class GEContext;


//<class>
//
// Name: HG3dInputHandler
//
// Purpose: Handling Pointer Events
//
// Public Interface:
//
// - HG3dInputHandler (
//     Glyph*,                          the glyph on which the input handler listens
//     Style*,                          the style of the session
//     SceneWindow*                     the scene displayed
//   )
//   Constructor.
//
// - context (GEContext*)
//   Sets the GE-Context which can be redrawn. Due to the hierarchy of window glyphs
//   the gecontext cannot be passed in the constructor.
//
// - loadXdefaults (Style*)
//   Constants for navigation speed can be changed via X attributes.
// 
// - drawui ()
//   Draws user interface parts (heads up display) depending on the current navigation
//   mode atop the window.
//      
// - reset ()
//   This function should be called whenever the movement mode is changed or another
//   scene is read. It resets internal states like the displayed cursor or marked
//   points for POI.
//   return value: non-zero iff the canvas must be redrawn.
//
// - tofract_x (Window*, Coord x)
//   Converts window coordinate x into [0..1], relative to window width.
//
// - tofract_y (Window*, Coord y)
//   Converts window coordinate y into [0..1], relative to window height.
//
//
// Overriden functions of Baseclass InputHandler:
//
// - allocate (...)
//   see InterViews 3.1. Used to get a pointer to the window.
//
// - press (const Event&)
// - double_click (const Event&)
// - drag (const Event&)
// - release (const Event&)
// - move (const Event&)
//   handle the pointer (mouse) events
//   . press (click)
//   . double click
//   . release (up)
//   . move
//   See InterViews 3.1.
//
// - keystroke
//   handle keystroke events (see IV 3.1)
//
//
//</class>




class HG3dInputHandler: public InputHandler
{
  public:
    HG3dInputHandler (Glyph*, Style*, SceneWindow*);
    void context (GEContext* con)  { gecontext_ = con; }

    void drawui (const Allocation&);   // draw ui parts onto ge3d window
    int reset ();                      // reset motion

    float tofract_x (Window*, Coord x) const;  // convertion from window to
    float tofract_y (Window*, Coord y) const;  // fractional coordinates [0, 1]

    virtual void allocate (Canvas*, const Allocation&, Extension&);
    
    void spaceball (const Event&);      // handle spaceball event
    void sballRezero ();

    static void loadXdefaults (Style*); // change navigation constants by X-defaults

  private:
    // InputHandler
    void press (const Event&);
    void double_click (const Event&);
    void drag (const Event&);
    void release (const Event&);
    void move (const Event&);
    void keystroke (const Event&);

    enum { _icon_none = -1, _icon_eyes, _icon_body, _icon_lift, _icon_fly2,
           _icon_num,  // number of icons
           halficonsize_ = 16
         };

    SceneWindow* scene_;
    Camera* camera_;                    // scene camera
    float size_;                        // scene size
    int button_;                        // mouse button
    GEContext* gecontext_;
    int move_mode_;                     // current navigation mode (NavMode)
    int click_;                         // true if clicked (no dragging)
    int ignoredrag_;                    // ignore drag in certain cases
    float lastfx_, lastfy_;             // fract. coord. of last press or drag
    float downx_, downy_;               // coord. of last press (from window center)
    float dragx_, dragy_;               // coord. of last press/drag (from window center)
    float flyspeed_;                    // speed for fly 1 (fraction of size_)
    int flying_;                        // true if flying is active (fly 1)
    point3D poitarget_;                 // trarget point (point of interest) for fly to
    point3D poinormal_;                 // normal at target (POI) point
    int poiset_;                        // true if poitarget_ set
    int hu_icon_;                       // heads up: active icon
    int walkicon_;                      // matching icon on velocity walk
    float hu_iconpos_ [_icon_num];      // midpoint of the icons (y coord. in pixels from center)

    void selectObject (float fx, float fy);
    void selectAnchor (float fx, float fy);
    void drag_flipobj (float, float);
    void fly1_hold_button (const Event&);
    int fly1_next_frame (const Event&);
    void fly2_hold_button (const Event&, float fx, float fy);
    void hu_hold_button (const Event&, int icon, float dx, float dy);

    // navigation constants (configurable with Xdefaults)
  public:
    static float SpeedFactor_;
    static float FlyToTran_;
    static float FlyToRot_;

  private:
    static float FlipFocal_;
    static float WalkFocal_;
    static float FlipZoom_;
    static float FlipTurnHor_;
    static float FlipTurnVert_;

    static float WalkZoom_;
    static float WalkTurnHor_;
    static float WalkTurnVert_;
    static float WalkZoom3_;
    static float WalkTurnHor3_;
    static float WalkTurnVert3_;

    static float VelocityZoom_;
    static float VelocityPan_;
    static float VelocityTurnHor_;
    static float VelocityTurnVert_;
    static float VelocityZoom3_;
    static float VelocityPan3_;
    static float VelocityTurnHor3_;
    static float VelocityTurnVert3_;

    static float FlyDeadX_;
    static float FlyDeadY_;
    static float FlySpeedInc_;
    static float FlyTurnHor_;
    static float FlyTurnVert_;

    static float SBallSensitivity_;
    static int SBallTranslation_;
    static int SBallRotation_;
    static int SBallSAF_;

}; // HG3dInputHandler


inline float HG3dInputHandler::tofract_x (Window* win, Coord x) const
{ return win ? x / win->width () : x;
}

inline float HG3dInputHandler::tofract_y (Window* win, Coord y) const
{ return win ? y / win->height () : y;
}


#endif
