/**************************************************************************** GLUI User Interface Toolkit (LGPL) ---------------------------------- glui.h - Main (and only) external header for GLUI User Interface Toolkit -------------------------------------------------- Copyright (c) 1998 Paul Rademacher WWW: http://sourceforge.net/projects/glui/ Forums: http://sourceforge.net/forum/?group_id=92496 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *****************************************************************************/ #ifndef GLUI_GLUI_H #define GLUI_GLUI_H #if defined(GLUI_FREEGLUT) // FreeGLUT does not yet work perfectly with GLUI // - use at your own risk. #include #elif defined(GLUI_OPENGLUT) // OpenGLUT does not yet work properly with GLUI // - use at your own risk. #include #else #ifdef __APPLE__ #include #else #if defined(_WIN32) #include #endif #include #endif #endif #include #include #include #include #include #define GLUI_VERSION 2.3f /********** Current version **********/ //#define GLUI_USE_STATIC_LIB #ifdef GLUI_USE_STATIC_LIB #define GLUI_API #ifndef GLUI_NO_LIB_PRAGMA #pragma comment(lib, "glui32.lib") // Link automatically with GLUI library #endif #else #ifdef _WIN32 #ifdef GLUIDLL_EXPORTS #define GLUI_API __declspec(dllexport) #else #define GLUI_API __declspec(dllimport) #ifndef GLUI_NO_LIB_PRAGMA #pragma comment(lib, "gluidll32.lib") // Link automatically with GLUI library #endif #endif #else #define GLUI_API #endif #endif /********** Do some basic defines *******/ #ifndef Byte #define Byte unsigned char #endif #ifndef _RGBC_ class RGBc { public: Byte r, g, b; void set(Byte r,Byte g,Byte b) {this->r=r;this->g=g;this->b=b;} RGBc( void ) {} RGBc( Byte r, Byte g, Byte b ) { set( r, g, b ); } }; #define _RGBC_ #endif /********** List of GLUT callbacks ********/ enum GLUI_Glut_CB_Types { GLUI_GLUT_RESHAPE, GLUI_GLUT_KEYBOARD, GLUI_GLUT_DISPLAY, GLUI_GLUT_MOUSE, GLUI_GLUT_MOTION, GLUI_GLUT_SPECIAL, GLUI_GLUT_PASSIVE_MOTION, GLUI_GLUT_ENTRY, GLUI_GLUT_VISIBILITY }; /********* Constants for window placement **********/ #define GLUI_XOFF 6 #define GLUI_YOFF 6 #define GLUI_ITEMSPACING 3 #define GLUI_CHECKBOX_SIZE 13 #define GLUI_RADIOBUTTON_SIZE 13 #define GLUI_BUTTON_SIZE 20 #define GLUI_STATICTEXT_SIZE 13 #define GLUI_SEPARATOR_HEIGHT 8 #define GLUI_DEFAULT_CONTROL_WIDTH 100 #define GLUI_DEFAULT_CONTROL_HEIGHT 13 #define GLUI_EDITTEXT_BOXINNERMARGINX 3 #define GLUI_EDITTEXT_HEIGHT 20 #define GLUI_EDITTEXT_WIDTH 130 #define GLUI_EDITTEXT_MIN_INT_WIDTH 35 #define GLUI_EDITTEXT_MIN_TEXT_WIDTH 50 #define GLUI_PANEL_NAME_DROP 8 #define GLUI_PANEL_EMBOSS_TOP 4 /* #define GLUI_ROTATION_WIDTH 60 */ /* #define GLUI_ROTATION_HEIGHT 78 */ #define GLUI_ROTATION_WIDTH 50 #define GLUI_ROTATION_HEIGHT (GLUI_ROTATION_WIDTH+18) #define GLUI_MOUSE_INTERACTION_WIDTH 50 #define GLUI_MOUSE_INTERACTION_HEIGHT (GLUI_MOUSE_INTERACTION_WIDTH)+18 /** Different panel control types **/ #define GLUI_PANEL_NONE 0 #define GLUI_PANEL_EMBOSSED 1 #define GLUI_PANEL_RAISED 2 /** Max # of els in control's float_array **/ #define GLUI_DEF_MAX_ARRAY 30 /********* The control's 'active' behavior *********/ #define GLUI_CONTROL_ACTIVE_MOUSEDOWN 1 #define GLUI_CONTROL_ACTIVE_PERMANENT 2 /********* Control alignment types **********/ #define GLUI_ALIGN_CENTER 1 #define GLUI_ALIGN_RIGHT 2 #define GLUI_ALIGN_LEFT 3 /********** Limit types - how to limit spinner values *********/ #define GLUI_LIMIT_NONE 0 #define GLUI_LIMIT_CLAMP 1 #define GLUI_LIMIT_WRAP 2 /********** Translation control types ********************/ #define GLUI_TRANSLATION_XY 0 #define GLUI_TRANSLATION_Z 1 #define GLUI_TRANSLATION_X 2 #define GLUI_TRANSLATION_Y 3 #define GLUI_TRANSLATION_LOCK_NONE 0 #define GLUI_TRANSLATION_LOCK_X 1 #define GLUI_TRANSLATION_LOCK_Y 2 /********** How was a control activated? *****************/ #define GLUI_ACTIVATE_MOUSE 1 #define GLUI_ACTIVATE_TAB 2 /********** What type of live variable does a control have? **********/ #define GLUI_LIVE_NONE 0 #define GLUI_LIVE_INT 1 #define GLUI_LIVE_FLOAT 2 #define GLUI_LIVE_TEXT 3 #define GLUI_LIVE_STRING 6 #define GLUI_LIVE_DOUBLE 4 #define GLUI_LIVE_FLOAT_ARRAY 5 /************* Textbox and List Defaults - JVK ******************/ #define GLUI_TEXTBOX_HEIGHT 130 #define GLUI_TEXTBOX_WIDTH 130 #define GLUI_LIST_HEIGHT 130 #define GLUI_LIST_WIDTH 130 #define GLUI_DOUBLE_CLICK 1 #define GLUI_SINGLE_CLICK 0 #define GLUI_TAB_WIDTH 50 /* In pixels */ #define GLUI_TEXTBOX_BOXINNERMARGINX 3 #define GLUI_TEXTBOX_MIN_TEXT_WIDTH 50 #define GLUI_LIST_BOXINNERMARGINX 3 #define GLUI_LIST_MIN_TEXT_WIDTH 50 /*********************** TreePanel Defaults - JVK *****************************/ #define GLUI_TREEPANEL_DEFAULTS 0 // bar, standard bar color #define GLUI_TREEPANEL_ALTERNATE_COLOR 1 // Alternate between 8 different bar colors #define GLUI_TREEPANEL_ENABLE_BAR 2 // enable the bar #define GLUI_TREEPANEL_DISABLE_BAR 4 // disable the bar #define GLUI_TREEPANEL_DISABLE_DEEPEST_BAR 8 // disable only the deepest bar #define GLUI_TREEPANEL_CONNECT_CHILDREN_ONLY 16 // disable only the bar of the last child of each root #define GLUI_TREEPANEL_DISPLAY_HIERARCHY 32 // display some sort of hierachy in the tree node title #define GLUI_TREEPANEL_HIERARCHY_NUMERICDOT 64 // display hierarchy in 1.3.2 (etc... ) format #define GLUI_TREEPANEL_HIERARCHY_LEVEL_ONLY 128 // display hierarchy as only the level depth /******************* GLUI Scrollbar Defaults - JVK ***************************/ #define GLUI_SCROLL_ARROW_WIDTH 16 #define GLUI_SCROLL_ARROW_HEIGHT 16 #define GLUI_SCROLL_BOX_MIN_HEIGHT 5 #define GLUI_SCROLL_BOX_STD_HEIGHT 16 #define GLUI_SCROLL_STATE_NONE 0 #define GLUI_SCROLL_STATE_UP 1 #define GLUI_SCROLL_STATE_DOWN 2 #define GLUI_SCROLL_STATE_BOTH 3 #define GLUI_SCROLL_STATE_SCROLL 4 #define GLUI_SCROLL_DEFAULT_GROWTH_EXP 1.05f #define GLUI_SCROLL_VERTICAL 0 #define GLUI_SCROLL_HORIZONTAL 1 /** Size of the character width hash table for faster lookups. Make sure to keep this a power of two to avoid the slow divide. This is also a speed/memory tradeoff; 128 is enough for low ASCII. */ #define CHAR_WIDTH_HASH_SIZE 128 /********** Translation codes **********/ enum TranslationCodes { GLUI_TRANSLATION_MOUSE_NONE = 0, GLUI_TRANSLATION_MOUSE_UP, GLUI_TRANSLATION_MOUSE_DOWN, GLUI_TRANSLATION_MOUSE_LEFT, GLUI_TRANSLATION_MOUSE_RIGHT, GLUI_TRANSLATION_MOUSE_UP_LEFT, GLUI_TRANSLATION_MOUSE_UP_RIGHT, GLUI_TRANSLATION_MOUSE_DOWN_LEFT, GLUI_TRANSLATION_MOUSE_DOWN_RIGHT }; /************ A string type for us to use **********/ typedef std::string GLUI_String; GLUI_String& glui_format_str(GLUI_String &str, const char* fmt, ...); /********* Pre-declare classes as needed *********/ class GLUI; class GLUI_Control; class GLUI_Listbox; class GLUI_StaticText; class GLUI_EditText; class GLUI_Panel; class GLUI_Spinner; class GLUI_RadioButton; class GLUI_RadioGroup; class GLUI_Glut_Window; class GLUI_TreePanel; class GLUI_Scrollbar; class GLUI_List; class Arcball; /*** Flags for GLUI class constructor ***/ #define GLUI_SUBWINDOW ((long)(1<<1)) #define GLUI_SUBWINDOW_TOP ((long)(1<<2)) #define GLUI_SUBWINDOW_BOTTOM ((long)(1<<3)) #define GLUI_SUBWINDOW_LEFT ((long)(1<<4)) #define GLUI_SUBWINDOW_RIGHT ((long)(1<<5)) /*** Codes for different type of edittext boxes and spinners ***/ #define GLUI_EDITTEXT_TEXT 1 #define GLUI_EDITTEXT_INT 2 #define GLUI_EDITTEXT_FLOAT 3 #define GLUI_SPINNER_INT GLUI_EDITTEXT_INT #define GLUI_SPINNER_FLOAT GLUI_EDITTEXT_FLOAT #define GLUI_SCROLL_INT GLUI_EDITTEXT_INT #define GLUI_SCROLL_FLOAT GLUI_EDITTEXT_FLOAT // This is only for deprecated interface #define GLUI_EDITTEXT_STRING 4 /*** Definition of callbacks ***/ typedef void (*GLUI_Update_CB) (int id); typedef void (*GLUI_Control_CB)(GLUI_Control *); typedef void (*Int1_CB) (int); typedef void (*Int2_CB) (int, int); typedef void (*Int3_CB) (int, int, int); typedef void (*Int4_CB) (int, int, int, int); /************************************************************/ /** Callback Adapter Class Allows us to support different types of callbacks; like a GLUI_Update_CB function pointer--which takes an int; and a GLUI_Control_CB function pointer--which takes a GUI_Control object. */ class GLUI_API GLUI_CB { public: GLUI_CB() : idCB(0),objCB(0) {} GLUI_CB(GLUI_Update_CB cb) : idCB(cb),objCB(0) {} GLUI_CB(GLUI_Control_CB cb) : idCB(0),objCB(cb) {} // (Compiler generated copy constructor) /** This control just activated. Fire our callback.*/ void operator()(GLUI_Control *ctrl) const; bool operator!() const { return !idCB && !objCB; } operator bool() const { return !(!(*this)); } private: GLUI_Update_CB idCB; GLUI_Control_CB objCB; }; /************************************************************/ /* */ /* Base class, for hierarchical relationships */ /* */ /************************************************************/ class GLUI_Control; /** GLUI_Node is a node in a sort of tree of GLUI controls. Each GLUI_Node has a list of siblings (in a circular list) and a linked list of children. Everything onscreen is a GLUI_Node--windows, buttons, etc. The nodes are traversed for event processing, sizing, redraws, etc. */ class GLUI_API GLUI_Node { friend class GLUI_Tree; /* JVK */ friend class GLUI_Rollout; friend class GLUI_Main; public: GLUI_Node(); virtual ~GLUI_Node() {} GLUI_Node *first_sibling(); GLUI_Node *last_sibling(); GLUI_Node *prev(); GLUI_Node *next(); GLUI_Node *first_child() { return child_head; } GLUI_Node *last_child() { return child_tail; } GLUI_Node *parent() { return parent_node; } /** Link in a new child control */ virtual int add_control( GLUI_Control *control ); void link_this_to_parent_last (GLUI_Node *parent ); void link_this_to_parent_first(GLUI_Node *parent ); void link_this_to_sibling_next(GLUI_Node *sibling ); void link_this_to_sibling_prev(GLUI_Node *sibling ); void unlink(); void dump( FILE *out, const char *name ); protected: static void add_child_to_control(GLUI_Node *parent,GLUI_Control *child); GLUI_Node *parent_node; GLUI_Node *child_head; GLUI_Node *child_tail; GLUI_Node *next_sibling; GLUI_Node *prev_sibling; }; /************************************************************/ /* */ /* Standard Bitmap stuff */ /* */ /************************************************************/ enum GLUI_StdBitmaps_Codes { GLUI_STDBITMAP_CHECKBOX_OFF = 0, GLUI_STDBITMAP_CHECKBOX_ON, GLUI_STDBITMAP_RADIOBUTTON_OFF, GLUI_STDBITMAP_RADIOBUTTON_ON, GLUI_STDBITMAP_UP_ARROW, GLUI_STDBITMAP_DOWN_ARROW, GLUI_STDBITMAP_LEFT_ARROW, GLUI_STDBITMAP_RIGHT_ARROW, GLUI_STDBITMAP_SPINNER_UP_OFF, GLUI_STDBITMAP_SPINNER_UP_ON, GLUI_STDBITMAP_SPINNER_DOWN_OFF, GLUI_STDBITMAP_SPINNER_DOWN_ON, GLUI_STDBITMAP_CHECKBOX_OFF_DIS, /*** Disactivated control bitmaps ***/ GLUI_STDBITMAP_CHECKBOX_ON_DIS, GLUI_STDBITMAP_RADIOBUTTON_OFF_DIS, GLUI_STDBITMAP_RADIOBUTTON_ON_DIS, GLUI_STDBITMAP_SPINNER_UP_DIS, GLUI_STDBITMAP_SPINNER_DOWN_DIS, GLUI_STDBITMAP_LISTBOX_UP, GLUI_STDBITMAP_LISTBOX_DOWN, GLUI_STDBITMAP_LISTBOX_UP_DIS, GLUI_STDBITMAP_NUM_ITEMS }; /************************************************************/ /* */ /* Class GLUI_Bitmap */ /* */ /************************************************************/ /** GLUI_Bitmap is a simple 2D texture map. It's used to represent small textures like checkboxes, arrows, etc. via the GLUI_StdBitmaps class. */ class GLUI_Bitmap { friend class GLUI_StdBitmaps; public: GLUI_Bitmap(); ~GLUI_Bitmap(); /** Create bitmap from greyscale byte image */ void init_grey(unsigned char *array); /** Create bitmap from color int image */ void init(int *array); private: /** RGB pixel data */ unsigned char *pixels; int w, h; }; /************************************************************/ /* */ /* Class GLUI_StdBitmap */ /* */ /************************************************************/ /** Keeps an array of GLUI_Bitmap objects to represent all the images used in the UI: checkboxes, arrows, etc. */ class GLUI_StdBitmaps { public: GLUI_StdBitmaps(); ~GLUI_StdBitmaps(); /** Return the width (in pixels) of the n'th standard bitmap. */ int width (int n) const; /** Return the height (in pixels) of the n'th standard bitmap. */ int height(int n) const; /** Draw the n'th standard bitmap (one of the enums listed in GLUI_StdBitmaps_Codes) at pixel corner (x,y). */ void draw(int n, int x, int y) const; private: GLUI_Bitmap bitmaps[GLUI_STDBITMAP_NUM_ITEMS]; }; /************************************************************/ /* */ /* Master GLUI Class */ /* */ /************************************************************/ /** The master manages our interaction with GLUT. There's only one GLUI_Master_Object. */ class GLUI_API GLUI_Master_Object { friend void glui_idle_func(); public: GLUI_Master_Object(); ~GLUI_Master_Object(); GLUI_Node gluis; GLUI_Control *active_control, *curr_left_button_glut_menu; GLUI *active_control_glui; int glui_id_counter; GLUI_Glut_Window *find_glut_window( int window_id ); void set_glutIdleFunc(void (*f)(void)); /************** void (*glut_keyboard_CB)(unsigned char, int, int); void (*glut_reshape_CB)(int, int); void (*glut_special_CB)(int, int, int); void (*glut_mouse_CB)(int,int,int,int); void (*glut_passive_motion_CB)(int,int); void (*glut_visibility_CB)(int); void (*glut_motion_CB)(int,int); void (*glut_display_CB)(void); void (*glut_entry_CB)(int); **********/ void set_left_button_glut_menu_control( GLUI_Control *control ); /********** GLUT callthroughs **********/ /* These are the glut callbacks that we do not handle */ void set_glutReshapeFunc (void (*f)(int width, int height)); void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y)); void set_glutSpecialFunc (void (*f)(int key, int x, int y)); void set_glutMouseFunc (void (*f)(int, int, int, int )); void set_glutMotionFunc(void (*f)(int x, int y)); void set_glutDisplayFunc(void (*f)(void)) {glutDisplayFunc(f);} void set_glutTimerFunc(unsigned int millis, void (*f)(int value), int value) { ::glutTimerFunc(millis,f,value);} void set_glutOverlayDisplayFunc(void(*f)(void)){glutOverlayDisplayFunc(f);} void set_glutSpaceballMotionFunc(Int3_CB f) {glutSpaceballMotionFunc(f);} void set_glutSpaceballRotateFunc(Int3_CB f) {glutSpaceballRotateFunc(f);} void set_glutSpaceballButtonFunc(Int2_CB f) {glutSpaceballButtonFunc(f);} void set_glutTabletMotionFunc(Int2_CB f) {glutTabletMotionFunc(f);} void set_glutTabletButtonFunc(Int4_CB f) {glutTabletButtonFunc(f);} /* void set_glutWindowStatusFunc(Int1_CB f) {glutWindowStatusFunc(f);} */ void set_glutMenuStatusFunc(Int3_CB f) {glutMenuStatusFunc(f);} void set_glutMenuStateFunc(Int1_CB f) {glutMenuStateFunc(f);} void set_glutButtonBoxFunc(Int2_CB f) {glutButtonBoxFunc(f);} void set_glutDialsFunc(Int2_CB f) {glutDialsFunc(f);} GLUI *create_glui( const char *name, long flags=0, int x=-1, int y=-1, int w=-1, int h=-1 ); GLUI *create_glui_subwindow( int parent_window, long flags=0 ); GLUI *find_glui_by_window_id( int window_id ); void get_viewport_area( int *x, int *y, int *w, int *h ); void auto_set_viewport(); void close_all(); void sync_live_all(); void reshape(); float get_version() { return GLUI_VERSION; } void glui_setIdleFuncIfNecessary(void); private: GLUI_Node glut_windows; void (*glut_idle_CB)(void); void add_cb_to_glut_window(int window,int cb_type,void *cb); }; /** This is the only GLUI_Master_Object in existence. */ extern GLUI_API GLUI_Master_Object GLUI_Master; /************************************************************/ /* */ /* Class for managing a GLUT window */ /* */ /************************************************************/ /** A top-level window. The GLUI_Master GLUT callback can route events to the callbacks in this class, for arbitrary use by external users. (see GLUI_Master_Object::set_glutKeyboardFunc). This entire approach seems to be superceded by the "subwindow" flavor of GLUI. */ class GLUI_Glut_Window : public GLUI_Node { public: GLUI_Glut_Window(); int glut_window_id; /*********** Pointers to GLUT callthrough functions *****/ void (*glut_keyboard_CB)(unsigned char, int, int); void (*glut_special_CB)(int, int, int); void (*glut_reshape_CB)(int, int); void (*glut_passive_motion_CB)(int,int); void (*glut_mouse_CB)(int,int,int,int); void (*glut_visibility_CB)(int); void (*glut_motion_CB)(int,int); void (*glut_display_CB)(void); void (*glut_entry_CB)(int); }; /************************************************************/ /* */ /* Main Window GLUI class (not user-level) */ /* */ /************************************************************/ /** A GLUI_Main handles GLUT events for one window, routing them to the appropriate controls. The central user-visible "GLUI" class inherits from this class; users should not allocate GLUT_Main objects. There's a separate GLUI_Main object for: - Each top-level window with GUI stuff in it. - Each "subwindow" of another top-level window. All the GLUI_Main objects are listed in GLUI_Master.gluis. A better name for this class might be "GLUI_Environment"; this class provides the window-level context for every control. */ class GLUI_Main : public GLUI_Node { /********** Friend classes *************/ friend class GLUI_Control; friend class GLUI_Rotation; friend class GLUI_Translation; friend class GLUI; friend class GLUI_Master_Object; /*********** Friend functions **********/ friend void glui_mouse_func(int button, int state, int x, int y); friend void glui_keyboard_func(unsigned char key, int x, int y); friend void glui_special_func(int key, int x, int y); friend void glui_passive_motion_func(int x, int y); friend void glui_reshape_func( int w, int h ); friend void glui_visibility_func(int state); friend void glui_motion_func(int x, int y); friend void glui_entry_func(int state); friend void glui_display_func( void ); friend void glui_idle_func(void); friend void glui_parent_window_reshape_func( int w, int h ); friend void glui_parent_window_keyboard_func( unsigned char, int, int ); friend void glui_parent_window_special_func( int, int, int ); friend void glui_parent_window_mouse_func( int, int, int, int ); protected: /*** Variables ***/ int main_gfx_window_id; int mouse_button_down; int glut_window_id; int top_level_glut_window_id; GLUI_Control *active_control; GLUI_Control *mouse_over_control; GLUI_Panel *main_panel; enum buffer_mode_t { buffer_front=1, ///< Draw updated controls directly to screen. buffer_back=2 ///< Double buffering: postpone updates until next redraw. }; buffer_mode_t buffer_mode; ///< Current drawing mode int curr_cursor; int w, h; long flags; bool closing; int parent_window; int glui_id; /********** Misc functions *************/ GLUI_Control *find_control( int x, int y ); GLUI_Control *find_next_control( GLUI_Control *control ); GLUI_Control *find_next_control_rec( GLUI_Control *control ); GLUI_Control *find_next_control_( GLUI_Control *control ); GLUI_Control *find_prev_control( GLUI_Control *control ); void create_standalone_window( const char *name, int x=-1, int y=-1, int w=100, int h=100 ); void create_subwindow( int parent,int window_alignment ); void setup_default_glut_callbacks( void ); void mouse(int button, int state, int x, int y); void keyboard(unsigned char key, int x, int y); void special(int key, int x, int y); void passive_motion(int x, int y); void reshape( int w, int h ); void visibility(int state); void motion(int x, int y); void entry(int state); void display( void ); void idle(void); int needs_idle(void); void (*glut_mouse_CB)(int, int, int, int); void (*glut_keyboard_CB)(unsigned char, int, int); void (*glut_special_CB)(int, int, int); void (*glut_reshape_CB)(int, int); /*********** Controls ************/ virtual int add_control( GLUI_Node *parent, GLUI_Control *control ); /********** Constructors and Destructors ***********/ GLUI_Main( void ); public: GLUI_StdBitmaps std_bitmaps; GLUI_String window_name; RGBc bkgd_color; float bkgd_color_f[3]; void *font; int curr_modifiers; void adjust_glut_xy( int &x, int &y ) { y = h-y; } void activate_control( GLUI_Control *control, int how ); void align_controls( GLUI_Control *control ); void deactivate_current_control( void ); /** Draw a 3D-look pushed-out box around this rectangle */ void draw_raised_box( int x, int y, int w, int h ); /** Draw a 3D-look pushed-in box around this rectangle */ void draw_lowered_box( int x, int y, int w, int h ); /** Return true if this control should redraw itself immediately (front buffer); Or queue up a redraw and return false if it shouldn't (back buffer). */ bool should_redraw_now(GLUI_Control *ctl); /** Switch to the appropriate draw buffer now. Returns the old draw buffer. This routine should probably only be called from inside the GLUI_DrawingSentinal, in glui_internal_control.h */ int set_current_draw_buffer(); /** Go back to using this draw buffer. Undoes set_current_draw_buffer. */ void restore_draw_buffer( int buffer_state ); /** Pack, resize the window, and redraw all the controls. */ void refresh(); /** Redraw the main graphics window */ void post_update_main_gfx(); /** Recompute the sizes and positions of all controls */ void pack_controls(); void close_internal(); void check_subwindow_position(); void set_ortho_projection(); void set_viewport(); int get_glut_window_id( void ) { return glut_window_id; } /* JVK */ }; /************************************************************/ /* */ /* GLUI_Control: base class for all controls */ /* */ /************************************************************/ /** All the GUI objects inherit from GLUI_Control: buttons, checkboxes, labels, edit boxes, scrollbars, etc. Most of the work of this class is in routing events, like keystrokes, mouseclicks, redraws, and sizing events. Yes, this is a huge and hideous class. It needs to be split up into simpler subobjects. None of the data members should be directly accessed by users (they should be protected, not public); only subclasses. */ class GLUI_API GLUI_Control : public GLUI_Node { public: /** Onscreen coordinates */ int w, h; /* dimensions of control */ int x_abs, y_abs; int x_off, y_off_top, y_off_bot; /* INNER margins, by which child controls are indented */ int contain_x, contain_y; int contain_w, contain_h; /* if this is a container control (e.g., radiogroup or panel) this indicated dimensions of inner area in which controls reside */ /** "activation" for tabbing between controls. */ int active_type; ///< "GLUI_CONTROL_ACTIVE_..." bool active; ///< If true, we've got the focus bool can_activate; ///< If false, remove from tab order. bool spacebar_mouse_click; ///< Spacebar simulates click. /** Callbacks */ long user_id; ///< Integer to pass to callback function. GLUI_CB callback; ///< User callback function, or NULL. /** Variable value storage */ float float_val; /**< Our float value */ int int_val; /**< Our integer value */ float float_array_val[GLUI_DEF_MAX_ARRAY]; int float_array_size; GLUI_String text; /**< The text inside this control */ /** "Live variable" updating */ void *ptr_val; /**< A pointer to the user's live variable value */ int live_type; bool live_inited; /* These variables store the last value that live variable was known to have. */ int last_live_int; float last_live_float; GLUI_String last_live_text; float last_live_float_array[GLUI_DEF_MAX_ARRAY]; /** Properties of our control */ GLUI *glui; /**< Our containing event handler (NEVER NULL during event processing!) */ bool is_container; /**< Is this a container class (e.g., panel) */ int alignment; bool enabled; /**< Is this control grayed out? */ GLUI_String name; /**< The name of this control */ void *font; /**< Our glutbitmap font */ bool collapsible, is_open; GLUI_Node collapsed_node; bool hidden; /* Collapsed controls (and children) are hidden */ int char_widths[CHAR_WIDTH_HASH_SIZE][2]; /* Character width hash table */ public: /*** Get/Set values ***/ virtual void set_name( const char *string ); virtual void set_int_val( int new_int ) { int_val = new_int; output_live(true); } virtual void set_float_val( float new_float ) { float_val = new_float; output_live(true); } virtual void set_ptr_val( void *new_ptr ) { ptr_val = new_ptr; output_live(true); } virtual void set_float_array_val( float *array_ptr ); virtual float get_float_val( void ) { return float_val; } virtual int get_int_val( void ) { return int_val; } virtual void get_float_array_val( float *array_ptr ); virtual int get_id( void ) const { return user_id; } virtual void set_id( int id ) { user_id=id; } virtual int mouse_down_handler( int local_x, int local_y ) { return false; } virtual int mouse_up_handler( int local_x, int local_y, bool inside ) { return false; } virtual int mouse_held_down_handler( int local_x, int local_y, bool inside) { return false; } virtual int key_handler( unsigned char key, int modifiers ) { return false; } virtual int special_handler( int key,int modifiers ) { return false; } virtual void update_size( void ) { } virtual void idle( void ) { } virtual int mouse_over( int state, int x, int y ) { return false; } virtual void enable( void ); virtual void disable( void ); virtual void activate( int how ) { active = true; } virtual void deactivate( void ) { active = false; } /** Hide (shrink into a rollout) and unhide (expose from a rollout) */ void hide_internal( int recurse ); void unhide_internal( int recurse ); /** Return true if it currently makes sense to draw this class. */ int can_draw( void ) { return (glui != NULL && hidden == false); } /** Redraw this control. In single-buffering mode (drawing to GL_FRONT), this is just a call to translate_and_draw_front (after a can_draw() check). In double-buffering mode (drawing to GL_BACK), this queues up a redraw and returns false, since you shouldn't draw yet. */ void redraw(void); /** Redraw everybody in our window. */ void redraw_window(void); virtual void align( void ); void pack( int x, int y ); /* Recalculate positions and offsets */ void pack_old( int x, int y ); void draw_recursive( int x, int y ); int set_to_glut_window( void ); void restore_window( int orig ); void translate_and_draw_front( void ); void translate_to_origin( void ) {glTranslatef((float)x_abs+.5,(float)y_abs+.5,0.0);} virtual void draw( int x, int y )=0; void set_font( void *new_font ); void *get_font( void ); int string_width( const char *text ); int string_width( const GLUI_String &str ) { return string_width(str.c_str()); } int char_width( char c ); void draw_name( int x, int y ); void draw_box_inwards_outline( int x_min, int x_max, int y_min, int y_max ); void draw_box( int x_min, int x_max, int y_min, int y_max, float r, float g, float b ); void draw_bkgd_box( int x_min, int x_max, int y_min, int y_max ); void draw_emboss_box( int x_min, int x_max,int y_min,int y_max); void draw_string( const char *text ); void draw_string( const GLUI_String &s ) { draw_string(s.c_str()); } void draw_char( char c ); void draw_active_box( int x_min, int x_max, int y_min, int y_max ); void set_to_bkgd_color( void ); void set_w( int new_w ); void set_h( int new_w ); void set_alignment( int new_align ); void sync_live( int recurse, int draw ); /* Reads live variable */ void init_live( void ); void output_live( int update_main_gfx ); /** Writes live variable **/ virtual void set_text( const char *t ) {} void execute_callback( void ); void get_this_column_dims( int *col_x, int *col_y, int *col_w, int *col_h, int *col_x_off, int *col_y_off ); virtual bool needs_idle( void ) const; virtual bool wants_tabs() const { return false; } GLUI_Control(void) { x_off = GLUI_XOFF; y_off_top = GLUI_YOFF; y_off_bot = GLUI_YOFF; x_abs = GLUI_XOFF; y_abs = GLUI_YOFF; active = false; enabled = true; int_val = 0; last_live_int = 0; float_array_size = 0; glui_format_str(name, "Control: %p", this); float_val = 0.0; last_live_float = 0.0; ptr_val = NULL; glui = NULL; w = GLUI_DEFAULT_CONTROL_WIDTH; h = GLUI_DEFAULT_CONTROL_HEIGHT; font = NULL; active_type = GLUI_CONTROL_ACTIVE_MOUSEDOWN; alignment = GLUI_ALIGN_LEFT; is_container = false; can_activate = true; /* By default, you can activate a control */ spacebar_mouse_click = true; /* Does spacebar simulate a mouse click? */ live_type = GLUI_LIVE_NONE; text = ""; last_live_text == ""; live_inited = false; collapsible = false; is_open = true; hidden = false; memset(char_widths, -1, sizeof(char_widths)); /* JVK */ int i; for( i=0; iint_val = 1; set_color(red, green, blue); } } void disable_bar() { if (column) { column->int_val = 0; } } void set_child_number(int c) { child_number = c; } void set_level_color(float r, float g, float b) { lred = r; lgreen = g; lblue = b; } void set_color(float r, float g, float b) { red = r; green = g; blue = b; } protected: void common_init() { currently_inside = false; initially_inside = false; can_activate = true; is_container = true; h = GLUI_DEFAULT_CONTROL_HEIGHT + 7; w = GLUI_DEFAULT_CONTROL_WIDTH; y_off_top = 21; collapsible = true; red = .5; green = .5; blue = .5; lred = 0; lgreen = 0; lblue = 0; column = NULL; is_current = 0; child_number = 0; format = 0; panel = NULL; name = ""; level_name = ""; level = 0; }; }; /************************************************************/ /* */ /* TreePanel class (container) JVK */ /* */ /************************************************************/ /** Manages, maintains, and formats a tree of GLUI_Tree objects. These are shown in a heirarchical, collapsible display. FIXME: There's an infinite loop in the traversal code (OSL 2006/06) */ class GLUI_TreePanel : public GLUI_Panel { public: GLUI_TreePanel(GLUI_Node *parent, const char *name, bool open=false, int inset=0); int max_levels; int next_id; int format; float red; float green; float blue; float lred; float lgreen; float lblue; int root_children; /* These variables allow the tree panel to traverse the tree using only two function calls. (Well, four, if you count going in reverse */ GLUI_Tree *curr_branch; /* Current Branch */ GLUI_Panel *curr_root; /* Current Root */ public: void set_color(float r, float g, float b); void set_level_color(float r, float g, float b); void set_format(int f) { format = f; } /* Adds branch to curr_root */ GLUI_Tree * ab(const char *name, GLUI_Tree *root = NULL); /* Goes up one level, resets curr_root and curr_branch to parents*/ void fb(GLUI_Tree *branch= NULL); /* Deletes the curr_branch, goes up one level using fb */ void db(GLUI_Tree *branch = NULL); /* Finds the very last branch of curr_root, resets vars */ void descendBranch(GLUI_Panel *root = NULL); /* Resets curr_root and curr branch to TreePanel and lastChild */ void resetToRoot(GLUI_Panel *new_root = NULL); void next( void ); void refresh( void ); void expand_all( void ); void collapse_all( void ); void update_all( void ); void initNode(GLUI_Tree *temp); void formatNode(GLUI_Tree *temp); protected: int uniqueID( void ) { next_id++; return next_id - 1; } void common_init() { GLUI_Panel(); next_id = 0; curr_root = this; curr_branch = NULL; red = .5; green = .5; blue = .5; root_children = 0; } }; /************************************************************/ /* */ /* User-Level GLUI class */ /* */ /************************************************************/ class GLUI_Rotation; class GLUI_Translation; /** The main user-visible interface object to GLUI. */ class GLUI : public GLUI_Main { public: /** DEPRECATED interface for creating new GLUI objects */ int add_control( GLUI_Control *control ) { return main_panel->add_control(control); } void add_column( int draw_bar = true ); void add_column_to_panel( GLUI_Panel *panel, int draw_bar = true ); void add_separator( void ); void add_separator_to_panel( GLUI_Panel *panel ); GLUI_RadioGroup *add_radiogroup( int *live_var=NULL, int user_id=-1,GLUI_CB callback=GLUI_CB()); GLUI_RadioGroup *add_radiogroup_to_panel( GLUI_Panel *panel, int *live_var=NULL, int user_id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_RadioButton *add_radiobutton_to_group( GLUI_RadioGroup *group, const char *name ); GLUI_Listbox *add_listbox( const char *name, int *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Listbox *add_listbox_to_panel( GLUI_Panel *panel, const char *name, int *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB()); GLUI_Rotation *add_rotation( const char *name, float *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Rotation *add_rotation_to_panel( GLUI_Panel *panel, const char *name, float *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB()); GLUI_Translation *add_translation( const char *name, int trans_type, float *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Translation *add_translation_to_panel( GLUI_Panel *panel, const char *name, int trans_type, float *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB()); GLUI_Checkbox *add_checkbox( const char *name, int *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB()); GLUI_Checkbox *add_checkbox_to_panel( GLUI_Panel *panel, const char *name, int *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB()); GLUI_Button *add_button( const char *name, int id=-1, GLUI_CB callback=GLUI_CB()); GLUI_Button *add_button_to_panel( GLUI_Panel *panel, const char *name, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_StaticText *add_statictext( const char *name ); GLUI_StaticText *add_statictext_to_panel( GLUI_Panel *panel, const char *name ); GLUI_EditText *add_edittext( const char *name, int data_type=GLUI_EDITTEXT_TEXT, void*live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_EditText *add_edittext_to_panel( GLUI_Panel *panel, const char *name, int data_type=GLUI_EDITTEXT_TEXT, void *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_EditText *add_edittext( const char *name, GLUI_String& live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_EditText *add_edittext_to_panel( GLUI_Panel *panel, const char *name, GLUI_String& live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Spinner *add_spinner( const char *name, int data_type=GLUI_SPINNER_INT, void *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Spinner *add_spinner_to_panel( GLUI_Panel *panel, const char *name, int data_type=GLUI_SPINNER_INT, void *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Panel *add_panel( const char *name, int type=GLUI_PANEL_EMBOSSED ); GLUI_Panel *add_panel_to_panel( GLUI_Panel *panel, const char *name, int type=GLUI_PANEL_EMBOSSED ); GLUI_Rollout *add_rollout( const char *name, int open=true, int type=GLUI_PANEL_EMBOSSED); GLUI_Rollout *add_rollout_to_panel( GLUI_Panel *panel, const char *name, int open=true, int type=GLUI_PANEL_EMBOSSED); /** Set the window where our widgets should be displayed. */ void set_main_gfx_window( int window_id ); int get_glut_window_id( void ) { return glut_window_id; } void enable( void ) { main_panel->enable(); } void disable( void ); void sync_live( void ); void close( void ); void show( void ); void hide( void ); /***** GLUT callback setup functions *****/ /* void set_glutDisplayFunc(void (*f)(void)); void set_glutReshapeFunc(void (*f)(int width, int height)); void set_glutKeyboardFunc(void (*f)(unsigned char key, int x, int y)); void set_glutSpecialFunc(void (*f)(int key, int x, int y)); void set_glutMouseFunc(void (*f)(int button, int state, int x, int y)); void set_glutMotionFunc(void (*f)(int x, int y)); void set_glutPassiveMotionFunc(void (*f)(int x, int y)); void set_glutEntryFunc(void (*f)(int state)); void set_glutVisibilityFunc(void (*f)(int state)); void set_glutInit( int *argcp, const char **argv ); void set_glutInitWindowSize(int width, int height); void set_glutInitWindowPosition(int x, int y); void set_glutInitDisplayMode(unsigned int mode); int set_glutCreateWindow(const char *name); */ /***** Constructors and desctructors *****/ int init( const char *name, long flags, int x, int y, int parent_window, int w=-1, int h=-1 ); protected: virtual int add_control( GLUI_Node *parent, GLUI_Control *control ) { return GLUI_Main::add_control( parent, control ); } }; /************************************************************/ /* */ /* EditText class */ /* */ /************************************************************/ class GLUI_EditText : public GLUI_Control { public: int has_limits; int data_type; GLUI_String orig_text; int insertion_pt; int title_x_offset; int text_x_offset; int substring_start; /*substring that gets displayed in box*/ int substring_end; int sel_start, sel_end; /* current selection */ int num_periods; int last_insertion_pt; float float_low, float_high; int int_low, int_high; GLUI_Spinner *spinner; int debug; int draw_text_only; int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); int key_handler( unsigned char key,int modifiers ); int special_handler( int key, int modifiers ); void activate( int how ); void deactivate( void ); void draw( int x, int y ); int mouse_over( int state, int x, int y ); int find_word_break( int start, int direction ); int substring_width( int start, int end ); void clear_substring( int start, int end ); int find_insertion_pt( int x, int y ); int update_substring_bounds( void ); void update_and_draw_text( void ); void draw_text( int x, int y ); void draw_insertion_pt( void ); void set_numeric_text( void ); void update_x_offsets( void ); void update_size( void ); void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP); void set_int_limits( int low, int high, int limit_type=GLUI_LIMIT_CLAMP ); void set_float_val( float new_val ); void set_int_val( int new_val ); void set_text( const char *text ); void set_text( const GLUI_String &s) { set_text(s.c_str()); } const char *get_text() { return text.c_str(); } void dump( FILE *out, const char *text ); // Constructor, no live variable GLUI_EditText( GLUI_Node *parent, const char *name, int text_type=GLUI_EDITTEXT_TEXT, int id=-1, GLUI_CB callback=GLUI_CB() ); // Constructor, int live variable GLUI_EditText( GLUI_Node *parent, const char *name, int *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); // Constructor, float live variable GLUI_EditText( GLUI_Node *parent, const char *name, float *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); // Constructor, char* live variable GLUI_EditText( GLUI_Node *parent, const char *name, char *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); // Constructor, std::string live variable GLUI_EditText( GLUI_Node *parent, const char *name, std::string &live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); // Deprecated constructor, only called internally GLUI_EditText( GLUI_Node *parent, const char *name, int text_type, void *live_var, int id, GLUI_CB callback ); // Deprecated constructor, only called internally GLUI_EditText( void ) { common_init(); } protected: void common_init( void ) { h = GLUI_EDITTEXT_HEIGHT; w = GLUI_EDITTEXT_WIDTH; title_x_offset = 0; text_x_offset = 55; insertion_pt = -1; last_insertion_pt = -1; name = ""; substring_start = 0; data_type = GLUI_EDITTEXT_TEXT; substring_end = 2; num_periods = 0; has_limits = GLUI_LIMIT_NONE; sel_start = 0; sel_end = 0; active_type = GLUI_CONTROL_ACTIVE_PERMANENT; can_activate = true; spacebar_mouse_click = false; spinner = NULL; debug = false; draw_text_only = false; } void common_construct( GLUI_Node *parent, const char *name, int data_type, int live_type, void *live_var, int id, GLUI_CB callback ); }; /************************************************************/ /* */ /* CommandLine class */ /* */ /************************************************************/ class GLUI_CommandLine : public GLUI_EditText { public: typedef GLUI_EditText Super; enum { HIST_SIZE = 100 }; std::vector hist_list; int curr_hist; int oldest_hist; int newest_hist; bool commit_flag; public: int key_handler( unsigned char key,int modifiers ); int special_handler( int key,int modifiers ); void deactivate( void ); virtual const char *get_history( int command_number ) const { return hist_list[command_number - oldest_hist].c_str(); } virtual GLUI_String& get_history_str( int command_number ) { return hist_list[command_number - oldest_hist]; } virtual const GLUI_String& get_history_str( int command_number ) const { return hist_list[command_number - oldest_hist]; } virtual void recall_history( int history_number ); virtual void scroll_history( int direction ); virtual void add_to_history( const char *text ); virtual void reset_history( void ); void dump( FILE *out, const char *text ); GLUI_CommandLine( GLUI_Node *parent, const char *name, void *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_CommandLine( void ) { common_init(); } protected: void common_init() { hist_list.resize(HIST_SIZE); curr_hist = 0; oldest_hist = 0; newest_hist = 0; commit_flag = false; } }; /************************************************************/ /* */ /* RadioGroup class (container) */ /* */ /************************************************************/ class GLUI_RadioGroup : public GLUI_Control { public: int num_buttons; void draw( int x, int y ); void set_name( const char *text ); void set_int_val( int int_val ); void set_selected( int int_val ); void draw_group( int translate ); GLUI_RadioGroup( GLUI_Node *parent, int *live_var=NULL, int user_id=-1,GLUI_CB callback=GLUI_CB() ); GLUI_RadioGroup( void ) { common_init(); } protected: void common_init( void ) { x_off = 0; y_off_top = 0; y_off_bot = 0; is_container = true; w = 300; h = 300; num_buttons = 0; name = ""; can_activate = false; live_type = GLUI_LIVE_INT; } }; /************************************************************/ /* */ /* RadioButton class (container) */ /* */ /************************************************************/ class GLUI_RadioButton : public GLUI_Control { public: int orig_value; bool currently_inside; int text_x_offset; int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); void draw( int x, int y ); void update_size( void ); void draw_active_area( void ); void draw_checked( void ); void draw_unchecked( void ); void draw_O( void ); GLUI_RadioButton( GLUI_RadioGroup *group, const char *name ); GLUI_RadioGroup *group; protected: void common_init() { glui_format_str( name, "RadioButton: %p", (void *) this ); h = GLUI_RADIOBUTTON_SIZE; group = NULL; orig_value = -1; text_x_offset = 18; can_activate = true; } }; /************************************************************/ /* */ /* Separator class (container) */ /* */ /************************************************************/ class GLUI_Separator : public GLUI_Control { public: void draw( int x, int y ); GLUI_Separator( GLUI_Node *parent ); GLUI_Separator( void ) { common_init(); } protected: void common_init() { w = 100; h = GLUI_SEPARATOR_HEIGHT; can_activate = false; } }; #define GLUI_SPINNER_ARROW_WIDTH 12 #define GLUI_SPINNER_ARROW_HEIGHT 8 #define GLUI_SPINNER_ARROW_Y 2 #define GLUI_SPINNER_STATE_NONE 0 #define GLUI_SPINNER_STATE_UP 1 #define GLUI_SPINNER_STATE_DOWN 2 #define GLUI_SPINNER_STATE_BOTH 3 #define GLUI_SPINNER_DEFAULT_GROWTH_EXP 1.05f /************************************************************/ /* */ /* Spinner class (container) */ /* */ /************************************************************/ class GLUI_Spinner : public GLUI_Control { public: // Constructor, no live var GLUI_Spinner( GLUI_Node* parent, const char *name, int data_type=GLUI_SPINNER_INT, int id=-1, GLUI_CB callback=GLUI_CB() ); // Constructor, int live var GLUI_Spinner( GLUI_Node* parent, const char *name, int *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); // Constructor, float live var GLUI_Spinner( GLUI_Node* parent, const char *name, float *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); // Deprecated constructor GLUI_Spinner( GLUI_Node* parent, const char *name, int data_type, void *live_var, int id=-1, GLUI_CB callback=GLUI_CB() ); // Deprecated constructor GLUI_Spinner( void ) { common_init(); } bool currently_inside; int state; float growth, growth_exp; int last_x, last_y; int data_type; int callback_count; int last_int_val; float last_float_val; int first_callback; float user_speed; GLUI_EditText *edittext; int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); int key_handler( unsigned char key,int modifiers ); int special_handler( int key,int modifiers ); void draw( int x, int y ); void draw_pressed( void ); void draw_unpressed( void ); void draw_text( int sunken ); void update_size( void ); void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP); void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP); int find_arrow( int local_x, int local_y ); void do_drag( int x, int y ); void do_callbacks( void ); void do_click( void ); void idle( void ); bool needs_idle( void ) const; const char *get_text( void ); void set_float_val( float new_val ); void set_int_val( int new_val ); float get_float_val( void ); int get_int_val( void ); void increase_growth( void ); void reset_growth( void ); void set_speed( float speed ) { user_speed = speed; } protected: void common_init() { glui_format_str( name, "Spinner: %p", this ); h = GLUI_EDITTEXT_HEIGHT; w = GLUI_EDITTEXT_WIDTH; x_off = 0; y_off_top = 0; y_off_bot = 0; can_activate = true; state = GLUI_SPINNER_STATE_NONE; edittext = NULL; growth_exp = GLUI_SPINNER_DEFAULT_GROWTH_EXP; callback_count = 0; first_callback = true; user_speed = 1.0; } void common_construct( GLUI_Node* parent, const char *name, int data_type, void *live_var, int id, GLUI_CB callback ); }; /************************************************************/ /* */ /* StaticText class */ /* */ /************************************************************/ class GLUI_StaticText : public GLUI_Control { public: void set_text( const char *text ); void draw( int x, int y ); void draw_text( void ); void update_size( void ); void erase_text( void ); GLUI_StaticText(GLUI_Node *parent, const char *name); GLUI_StaticText( void ) { common_init(); } protected: void common_init() { h = GLUI_STATICTEXT_SIZE; name = ""; can_activate = false; } }; /************************************************************/ /* */ /* TextBox class - JVK */ /* */ /************************************************************/ class GLUI_TextBox : public GLUI_Control { public: /* GLUI Textbox - JVK */ GLUI_TextBox(GLUI_Node *parent, GLUI_String &live_var, bool scroll = false, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_TextBox( GLUI_Node *parent, bool scroll = false, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_String orig_text; int insertion_pt; int substring_start; /*substring that gets displayed in box*/ int substring_end; int sel_start, sel_end; /* current selection */ int last_insertion_pt; int debug; int draw_text_only; int tab_width; int start_line; int num_lines; int curr_line; int visible_lines; int insert_x; /* Similar to "insertion_pt", these variables keep */ int insert_y; /* track of where the ptr is, but in pixels */ int keygoal_x; /* where up down keys would like to put insertion pt*/ GLUI_Scrollbar *scrollbar; int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); int key_handler( unsigned char key,int modifiers ); int special_handler( int key,int modifiers ); void activate( int how ); void deactivate( void ); void enable( void ); void disable( void ); void draw( int x, int y ); int mouse_over( int state, int x, int y ); int get_box_width(); int find_word_break( int start, int direction ); int substring_width( int start, int end, int initial_width=0 ); void clear_substring( int start, int end ); int find_insertion_pt( int x, int y ); int update_substring_bounds( void ); void update_and_draw_text( void ); void draw_text( int x, int y ); void draw_insertion_pt( void ); void update_x_offsets( void ); void update_size( void ); void set_text( const char *text ); const char *get_text( void ) { return text.c_str(); } void dump( FILE *out, char *text ); void set_tab_w(int w) { tab_width = w; } void set_start_line(int l) { start_line = l; } static void scrollbar_callback(GLUI_Control*); bool wants_tabs( void ) const { return true; } protected: void common_init() { h = GLUI_TEXTBOX_HEIGHT; w = GLUI_TEXTBOX_WIDTH; tab_width = GLUI_TAB_WIDTH; num_lines = 0; visible_lines = 0; start_line = 0; curr_line = 0; insert_y = -1; insert_x = -1; insertion_pt = -1; last_insertion_pt = -1; name[0] = '\0'; substring_start = 0; substring_end = 2; sel_start = 0; sel_end = 0; active_type = GLUI_CONTROL_ACTIVE_PERMANENT; can_activate = true; spacebar_mouse_click = false; scrollbar = NULL; debug = false; draw_text_only = false; } void common_construct( GLUI_Node *parent, GLUI_String *live_var, bool scroll, int id, GLUI_CB callback); }; /************************************************************/ /* */ /* List class - JVK */ /* */ /************************************************************/ class GLUI_List_Item : public GLUI_Node { public: GLUI_String text; int id; }; /************************************************************/ /* */ /* List class - JVK */ /* */ /************************************************************/ class GLUI_List : public GLUI_Control { public: /* GLUI List - JVK */ GLUI_List( GLUI_Node *parent, bool scroll = false, int id=-1, GLUI_CB callback=GLUI_CB() ); /*, GLUI_Control *object = NULL ,GLUI_InterObject_CB obj_cb = NULL);*/ GLUI_List( GLUI_Node *parent, GLUI_String& live_var, bool scroll = false, int id=-1, GLUI_CB callback=GLUI_CB() /*,GLUI_Control *object = NULL */ /*,GLUI_InterObject_CB obj_cb = NULL*/); GLUI_String orig_text; int debug; int draw_text_only; int start_line; int num_lines; int curr_line; int visible_lines; GLUI_Scrollbar *scrollbar; GLUI_List_Item items_list; GLUI_Control *associated_object; GLUI_CB obj_cb; int cb_click_type; int last_line; int last_click_time; int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); int key_handler( unsigned char key,int modifiers ); int special_handler( int key,int modifiers ); void activate( int how ); void deactivate( void ); void draw( int x, int y ); int mouse_over( int state, int x, int y ); int get_box_width(); int find_word_break( int start, int direction ); int substring_width( const char *t, int start, int end ); int find_line( int x, int y ); void update_and_draw_text( void ); void draw_text( const char *t, int selected, int x, int y ); void update_size( void ); int add_item( int id, const char *text ); int delete_item( const char *text ); int delete_item( int id ); int delete_all(); GLUI_List_Item *get_item_ptr( const char *text ); GLUI_List_Item *get_item_ptr( int id ); void dump( FILE *out, const char *text ); void set_start_line(int l) { start_line = l; } static void scrollbar_callback(GLUI_Control*); int get_current_item() { return curr_line; } void set_click_type(int d) { cb_click_type = d; } void set_object_callback(GLUI_CB cb=GLUI_CB(), GLUI_Control*obj=NULL) { obj_cb=cb; associated_object=obj; } protected: void common_init() { h = GLUI_LIST_HEIGHT; w = GLUI_LIST_WIDTH; num_lines = 0; visible_lines = 0; start_line = 0; curr_line = 0; name[0] = '\0'; active_type = GLUI_CONTROL_ACTIVE_PERMANENT; can_activate = true; spacebar_mouse_click = false; scrollbar = NULL; debug = false; draw_text_only = false; cb_click_type = GLUI_SINGLE_CLICK; last_line = -1; last_click_time = 0; associated_object = NULL; }; void common_construct( GLUI_Node *parent, GLUI_String* live_var, bool scroll, int id, GLUI_CB callback /*,GLUI_Control *object*/ /*,GLUI_InterObject_CB obj_cb*/); }; /************************************************************/ /* */ /* Scrollbar class - JVK */ /* */ /************************************************************/ class GLUI_Scrollbar : public GLUI_Control { public: // Constructor, no live var GLUI_Scrollbar( GLUI_Node *parent, const char *name, int horz_vert=GLUI_SCROLL_HORIZONTAL, int data_type=GLUI_SCROLL_INT, int id=-1, GLUI_CB callback=GLUI_CB() /*,GLUI_Control *object = NULL*/ /*,GLUI_InterObject_CB obj_cb = NULL*/ ); // Constructor, int live var GLUI_Scrollbar( GLUI_Node *parent, const char *name, int horz_vert, int *live_var, int id=-1, GLUI_CB callback=GLUI_CB() /*,GLUI_Control *object = NULL*/ /*,GLUI_InterObject_CB obj_cb = NULL*/ ); // Constructor, float live var GLUI_Scrollbar( GLUI_Node *parent, const char *name, int horz_vert, float *live_var, int id=-1, GLUI_CB callback=GLUI_CB() /*,GLUI_Control *object = NULL*/ /*,GLUI_InterObject_CB obj_cb = NULL*/ ); bool currently_inside; int state; float growth, growth_exp; int last_x, last_y; int data_type; int callback_count; int last_int_val; ///< Used to prevent repeated callbacks. float last_float_val; int first_callback; float user_speed; float float_min, float_max; int int_min, int_max; int horizontal; double last_update_time; ///< GLUI_Time() we last advanced scrollbar. double velocity_limit; ///< Maximum distance to advance per second. int box_length; int box_start_position; int box_end_position; int track_length; /* Rather than directly access an Editbox or Textbox for changing variables, a pointer to some object is defined along with a static callback in the form func(void *, int) - the int is the new value, the void * must be cast to that particular object type before use. */ void * associated_object; /* Lets the Spinner manage it's own callbacks */ GLUI_CB object_cb; /* function pointer to object call_back */ int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); int key_handler( unsigned char key,int modifiers ); int special_handler( int key,int modifiers ); void draw( int x, int y ); void draw_pressed( void ); void draw_unpressed( void ); void draw_text( int sunken ); void update_size( void ); void set_int_limits( int low, int high,int limit_type=GLUI_LIMIT_CLAMP); void set_float_limits( float low,float high,int limit_type=GLUI_LIMIT_CLAMP); int find_arrow( int local_x, int local_y ); void do_drag( int x, int y ); void do_callbacks( void ); void draw_scroll( void ); void do_click( void ); void idle( void ); bool needs_idle( void ) const; void set_int_val( int new_val ); void set_float_val( float new_val ); void increase_growth( void ); void reset_growth( void ); void set_speed( float speed ) { user_speed = speed; }; void update_scroll_parameters(); void set_object_callback(GLUI_CB cb=GLUI_CB(), GLUI_Control*obj=NULL) { object_cb=cb; associated_object=obj; } protected: void common_init ( void ); void common_construct( GLUI_Node *parent, const char *name, int horz_vert, int data_type, void* live_var, int id, GLUI_CB callback /*,GLUI_Control *object ,GLUI_InterObject_CB obj_cb*/ ); virtual void draw_scroll_arrow(int arrowtype, int x, int y); virtual void draw_scroll_box(int x, int y, int w, int h); }; /************************************************************/ /* */ /* Listbox class */ /* */ /************************************************************/ class GLUI_Listbox_Item : public GLUI_Node { public: GLUI_String text; int id; }; class GLUI_Listbox : public GLUI_Control { public: GLUI_String curr_text; GLUI_Listbox_Item items_list; int depressed; int orig_value; bool currently_inside; int text_x_offset, title_x_offset; int glut_menu_id; int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); int key_handler( unsigned char key,int modifiers ); int special_handler( int key,int modifiers ); void update_size( void ); void draw( int x, int y ); int mouse_over( int state, int x, int y ); void set_int_val( int new_val ); void dump( FILE *output ); int add_item( int id, const char *text ); int delete_item( const char *text ); int delete_item( int id ); int sort_items( void ); int do_selection( int item ); GLUI_Listbox_Item *get_item_ptr( const char *text ); GLUI_Listbox_Item *get_item_ptr( int id ); GLUI_Listbox( GLUI_Node *parent, const char *name, int *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Listbox( void ) { common_init(); } protected: /** Change w and return true if we need to be widened to fit the current item. */ bool recalculate_item_width( void ); void common_init() { glui_format_str( name, "Listbox: %p", this ); w = GLUI_EDITTEXT_WIDTH; h = GLUI_EDITTEXT_HEIGHT; orig_value = -1; title_x_offset = 0; text_x_offset = 55; can_activate = true; curr_text = ""; live_type = GLUI_LIVE_INT; /* This has an integer live var */ depressed = false; glut_menu_id = -1; } ~GLUI_Listbox(); }; /************************************************************/ /* */ /* Mouse_Interaction class */ /* */ /************************************************************/ /** This is the superclass of translation and rotation widgets. */ class GLUI_Mouse_Interaction : public GLUI_Control { public: /*int get_main_area_size( void ) { return MIN( h-18, */ int draw_active_area_only; int mouse_down_handler( int local_x, int local_y ); int mouse_up_handler( int local_x, int local_y, bool inside ); int mouse_held_down_handler( int local_x, int local_y, bool inside ); int special_handler( int key, int modifiers ); void update_size( void ); void draw( int x, int y ); void draw_active_area( void ); /*** The following methods (starting with "iaction_") need to be overloaded ***/ virtual int iaction_mouse_down_handler( int local_x, int local_y ) = 0; virtual int iaction_mouse_up_handler( int local_x, int local_y, bool inside )=0; virtual int iaction_mouse_held_down_handler( int local_x, int local_y, bool inside )=0; virtual int iaction_special_handler( int key, int modifiers )=0; virtual void iaction_draw_active_area_persp( void )=0; virtual void iaction_draw_active_area_ortho( void )=0; virtual void iaction_dump( FILE *output )=0; virtual void iaction_init( void ) = 0; GLUI_Mouse_Interaction( void ) { glui_format_str( name, "Mouse_Interaction: %p", this ); w = GLUI_MOUSE_INTERACTION_WIDTH; h = GLUI_MOUSE_INTERACTION_HEIGHT; can_activate = true; live_type = GLUI_LIVE_NONE; alignment = GLUI_ALIGN_CENTER; draw_active_area_only = false; } }; /************************************************************/ /* */ /* Rotation class */ /* */ /************************************************************/ /** An onscreen rotation controller--allows the user to interact with a 3D rotation via a spaceball-like interface. */ class GLUI_Rotation : public GLUI_Mouse_Interaction { public: Arcball *ball; GLUquadricObj *quadObj; bool can_spin, spinning; float damping; int iaction_mouse_down_handler( int local_x, int local_y ); int iaction_mouse_up_handler( int local_x, int local_y, bool inside ); int iaction_mouse_held_down_handler( int local_x, int local_y, bool inside ); int iaction_special_handler( int key, int modifiers ); void iaction_init( void ) { init_ball(); } void iaction_draw_active_area_persp( void ); void iaction_draw_active_area_ortho( void ); void iaction_dump( FILE *output ); /* void update_size( void ); */ /* void draw( int x, int y ); */ /* int mouse_over( int state, int x, int y ); */ void setup_texture( void ); void setup_lights( void ); void draw_ball( float radius ); void init_ball( void ); void reset( void ); bool needs_idle( void ) const; void idle( void ); void copy_float_array_to_ball( void ); void copy_ball_to_float_array( void ); void set_spin( float damp_factor ); GLUI_Rotation( GLUI_Node *parent, const char *name, float *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Rotation(void) { common_init(); } protected: void common_init(); }; /************************************************************/ /* */ /* Translation class */ /* */ /************************************************************/ /** An onscreen translation controller--allows the user to interact with a 3D translation. */ class GLUI_Translation : public GLUI_Mouse_Interaction { public: int trans_type; /* Is this an XY or a Z controller? */ int down_x, down_y; float scale_factor; GLUquadricObj *quadObj; int trans_mouse_code; float orig_x, orig_y, orig_z; int locked; int iaction_mouse_down_handler( int local_x, int local_y ); int iaction_mouse_up_handler( int local_x, int local_y, bool inside ); int iaction_mouse_held_down_handler( int local_x, int local_y, bool inside ); int iaction_special_handler( int key, int modifiers ); void iaction_init( void ) { } void iaction_draw_active_area_persp( void ); void iaction_draw_active_area_ortho( void ); void iaction_dump( FILE *output ); void set_speed( float s ) { scale_factor = s; } void setup_texture( void ); void setup_lights( void ); void draw_2d_arrow( int radius, int filled, int orientation ); void draw_2d_x_arrows( int radius ); void draw_2d_y_arrows( int radius ); void draw_2d_z_arrows( int radius ); void draw_2d_xy_arrows( int radius ); int get_mouse_code( int x, int y ); /* Float array is either a single float (for single-axis controls), or two floats for X and Y (if an XY controller) */ float get_z( void ) { return float_array_val[0]; } float get_x( void ) { return float_array_val[0]; } float get_y( void ) { if ( trans_type == GLUI_TRANSLATION_XY ) return float_array_val[1]; else return float_array_val[0]; } void set_z( float val ); void set_x( float val ); void set_y( float val ); void set_one_val( float val, int index ); GLUI_Translation( GLUI_Node *parent, const char *name, int trans_type, float *live_var=NULL, int id=-1, GLUI_CB callback=GLUI_CB() ); GLUI_Translation( void ) { common_init(); } protected: void common_init() { locked = GLUI_TRANSLATION_LOCK_NONE; glui_format_str( name, "Translation: %p", this ); w = GLUI_MOUSE_INTERACTION_WIDTH; h = GLUI_MOUSE_INTERACTION_HEIGHT; can_activate = true; live_type = GLUI_LIVE_FLOAT_ARRAY; float_array_size = 0; alignment = GLUI_ALIGN_CENTER; trans_type = GLUI_TRANSLATION_XY; scale_factor = 1.0; quadObj = NULL; trans_mouse_code = GLUI_TRANSLATION_MOUSE_NONE; } }; /********** Misc functions *********************/ int _glutBitmapWidthString( void *font, const char *s ); void _glutBitmapString( void *font, const char *s ); /********** Our own callbacks for glut *********/ /* These are the callbacks that we pass to glut. They take some action if necessary, then (possibly) call the user-level glut callbacks. */ void glui_display_func( void ); void glui_reshape_func( int w, int h ); void glui_keyboard_func(unsigned char key, int x, int y); void glui_special_func(int key, int x, int y); void glui_mouse_func(int button, int state, int x, int y); void glui_motion_func(int x, int y); void glui_passive_motion_func(int x, int y); void glui_entry_func(int state); void glui_visibility_func(int state); void glui_idle_func(void); void glui_parent_window_reshape_func( int w, int h ); void glui_parent_window_keyboard_func(unsigned char key, int x, int y); void glui_parent_window_mouse_func(int, int, int, int ); void glui_parent_window_special_func(int key, int x, int y); #endif