--- /dev/null
+libdir = ${exec_prefix}/lib
+
+lib_LTLIBRARIES = libPui.la
+
+libPui_la_SOURCES = \
+ pu.h puLocal.h \
+ pu.cxx \
+ puBox.cxx \
+ puButton.cxx \
+ puButtonBox.cxx \
+ puDialogBox.cxx \
+ puFrame.cxx \
+ puInput.cxx \
+ puInterface.cxx \
+ puMenuBar.cxx \
+ puObject.cxx \
+ puOneShot.cxx \
+ puPopup.cxx \
+ puPopupMenu.cxx \
+ puSlider.cxx \
+ puText.cxx
+
+INCLUDES += -I$(top_builddir)
+
--- /dev/null
+
+#include "puLocal.h"
+
+#define PU_STRING_X_FUDGE 6
+#define PU_STRING_Y_FUDGE 6
+
+int puRefresh = TRUE ;
+
+puColour _puDefaultColourTable[] =
+{
+ { 0.5, 0.5, 0.5, 1.0 }, /* PUCOL_FOREGROUND */
+ { 0.3, 0.3, 0.3, 1.0 }, /* PUCOL_BACKGROUND */
+ { 0.7, 0.7, 0.7, 1.0 }, /* PUCOL_HIGHLIGHT */
+ { 0.0, 0.0, 0.0, 1.0 }, /* PUCOL_LABEL */
+ { 1.0, 1.0, 1.0, 1.0 }, /* PUCOL_TEXT */
+
+ { 0.0, 0.0, 0.0, 0.0 } /* ILLEGAL */
+} ;
+
+
+puValue::~puValue () {}
+
+static int _puCursor_enable = FALSE ;
+static int _puCursor_x = 0 ;
+static int _puCursor_y = 0 ;
+static float _puCursor_bgcolour [4] = { 1.0f, 1.0f, 1.0f, 1.0f } ;
+static float _puCursor_fgcolour [4] = { 0.0f, 0.0f, 0.0f, 1.0f } ;
+
+void puHideCursor ( void ) { _puCursor_enable = FALSE ; }
+void puShowCursor ( void ) { _puCursor_enable = TRUE ; }
+int puCursorIsHidden ( void ) { return ! _puCursor_enable ; }
+
+void puCursor ( int x, int y )
+{
+ _puCursor_x = x ;
+ _puCursor_y = y ;
+}
+
+int puGetStringDescender ( void *fnt )
+{
+ if ( fnt == NULL )
+ fnt = GLUT_BITMAP_9_BY_15 ;
+
+ if ( fnt == GLUT_BITMAP_8_BY_13 ) return 2 ;
+ if ( fnt == GLUT_BITMAP_9_BY_15 ) return 3 ;
+ if ( fnt == GLUT_BITMAP_TIMES_ROMAN_10 ) return 2 ;
+ if ( fnt == GLUT_BITMAP_TIMES_ROMAN_24 ) return 5 ;
+ if ( fnt == GLUT_BITMAP_HELVETICA_10 ) return 2 ;
+ if ( fnt == GLUT_BITMAP_HELVETICA_12 ) return 3 ;
+ if ( fnt == GLUT_BITMAP_HELVETICA_18 ) return 4 ;
+
+ return 0 ;
+}
+
+int puGetStringHeight ( void *fnt )
+{
+ /* Height *excluding* descender */
+
+ if ( fnt == NULL )
+ fnt = GLUT_BITMAP_9_BY_15 ;
+
+ if ( fnt == GLUT_BITMAP_8_BY_13 ) return 9 ;
+ if ( fnt == GLUT_BITMAP_9_BY_15 ) return 10 ;
+ if ( fnt == GLUT_BITMAP_TIMES_ROMAN_10 ) return 7 ;
+ if ( fnt == GLUT_BITMAP_TIMES_ROMAN_24 ) return 17 ;
+ if ( fnt == GLUT_BITMAP_HELVETICA_10 ) return 8 ;
+ if ( fnt == GLUT_BITMAP_HELVETICA_12 ) return 9 ;
+ if ( fnt == GLUT_BITMAP_HELVETICA_18 ) return 14 ;
+
+ return 0 ;
+}
+
+int puGetStringWidth ( void *fnt, char *str )
+{
+ if ( str == NULL )
+ return 0 ;
+
+ if ( fnt == NULL )
+ fnt = GLUT_BITMAP_9_BY_15 ;
+
+ int res = 0 ;
+
+ while ( *str != '\0' )
+ {
+ res += glutBitmapWidth ( fnt, *str ) ;
+ str++ ;
+ }
+
+ return res ;
+}
+
+
+void puDrawString ( void *fnt, char *str, int x, int y )
+{
+ if ( str == NULL )
+ return ;
+
+ if ( fnt == NULL )
+ fnt = GLUT_BITMAP_9_BY_15 ;
+
+ glRasterPos2f ( x, y ) ;
+
+ while ( *str != '\0' )
+ {
+ glutBitmapCharacter ( fnt, *str ) ;
+ str++ ;
+ }
+}
+
+
+static void puDrawCursor ( int x, int y )
+{
+ glColor4fv ( _puCursor_bgcolour ) ;
+
+ glBegin ( GL_TRIANGLES ) ;
+ glVertex2i ( x, y ) ;
+ glVertex2i ( x + 13, y - 4 ) ;
+ glVertex2i ( x + 4, y - 13 ) ;
+
+ glVertex2i ( x + 8, y - 3 ) ;
+ glVertex2i ( x + 17, y - 12 ) ;
+ glVertex2i ( x + 12, y - 17 ) ;
+
+ glVertex2i ( x + 12, y - 17 ) ;
+ glVertex2i ( x + 3, y - 8 ) ;
+ glVertex2i ( x + 8, y - 3 ) ;
+ glEnd () ;
+
+ glColor4fv ( _puCursor_fgcolour ) ;
+
+ glBegin ( GL_TRIANGLES ) ;
+ glVertex2i ( x+1, y-1 ) ;
+ glVertex2i ( x + 11, y - 4 ) ;
+ glVertex2i ( x + 4, y - 11 ) ;
+
+ glVertex2i ( x + 8, y - 5 ) ;
+ glVertex2i ( x + 15, y - 12 ) ;
+ glVertex2i ( x + 12, y - 15 ) ;
+
+ glVertex2i ( x + 12, y - 15 ) ;
+ glVertex2i ( x + 5, y - 8 ) ;
+ glVertex2i ( x + 8, y - 5 ) ;
+ glEnd () ;
+}
+
+void puInit ( void )
+{
+ static int firsttime = TRUE ;
+
+ if ( firsttime )
+ {
+ puInterface *base_interface = new puInterface ( 0, 0 ) ;
+ puPushInterface ( base_interface ) ;
+ puPushLiveInterface ( base_interface ) ;
+ firsttime = FALSE ;
+ }
+}
+
+static void puSetOpenGLState ( void )
+{
+ int w = glutGet ( (GLenum) GLUT_WINDOW_WIDTH ) ;
+ int h = glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ;
+
+ glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT ) ;
+ glDisable ( GL_LIGHTING ) ;
+ glDisable ( GL_FOG ) ;
+ glDisable ( GL_TEXTURE_2D ) ;
+ glDisable ( GL_DEPTH_TEST ) ;
+ glDisable ( GL_CULL_FACE ) ;
+
+ glViewport ( 0, 0, w, h ) ;
+ glMatrixMode ( GL_PROJECTION ) ;
+ glPushMatrix () ;
+ glLoadIdentity () ;
+ gluOrtho2D ( 0, w, 0, h ) ;
+ glMatrixMode ( GL_MODELVIEW ) ;
+ glPushMatrix () ;
+ glLoadIdentity () ;
+}
+
+static void puRestoreOpenGLState ( void )
+{
+ glMatrixMode ( GL_PROJECTION ) ;
+ glPopMatrix () ;
+ glMatrixMode ( GL_MODELVIEW ) ;
+ glPopMatrix () ;
+ glPopAttrib () ;
+}
+
+
+void puDisplay ( void )
+{
+ puSetOpenGLState () ;
+ puGetUltimateLiveInterface () -> draw ( 0, 0 ) ;
+
+ if ( _puCursor_enable )
+ puDrawCursor ( _puCursor_x,
+ glutGet((GLenum)GLUT_WINDOW_HEIGHT) - _puCursor_y ) ;
+
+ puRestoreOpenGLState () ;
+}
+
+int puKeyboard ( int key, int updown )
+{
+ return puGetBaseLiveInterface () -> checkKey ( key, updown ) ;
+}
+
+
+static int last_buttons = 0 ;
+
+int puMouse ( int button, int updown, int x, int y )
+{
+ puCursor ( x, y ) ;
+
+ if ( updown == PU_DOWN )
+ last_buttons |= ( 1 << button ) ;
+ else
+ last_buttons &= ~( 1 << button ) ;
+
+ return puGetBaseLiveInterface () -> checkHit ( button, updown, x,
+ glutGet((GLenum)GLUT_WINDOW_HEIGHT) - y ) ;
+}
+
+int puMouse ( int x, int y )
+{
+ puCursor ( x, y ) ;
+
+ if ( last_buttons == 0 )
+ return FALSE ;
+
+ int button = (last_buttons & (1<<PU_LEFT_BUTTON )) ? PU_LEFT_BUTTON :
+ (last_buttons & (1<<PU_MIDDLE_BUTTON)) ? PU_MIDDLE_BUTTON :
+ (last_buttons & (1<<PU_RIGHT_BUTTON )) ? PU_RIGHT_BUTTON : 0 ;
+
+ return puGetBaseLiveInterface () -> checkHit ( button, PU_DRAG, x,
+ glutGet((GLenum)GLUT_WINDOW_HEIGHT) - y ) ;
+}
+
--- /dev/null
+#ifndef _PU_H_
+#define _PU_H_
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+# include <windows.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <GL/glut.h>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+/*
+ Webster's Dictionary (for American English) permits
+ Color or Colour as acceptable spellings - but
+ The Oxford English Dictionary (for English) only
+ permits Colour.
+
+ Hence, the logical thing to do is to use 'colour',
+ which *ought* to be acceptable on both sides of
+ the atlantic.
+
+ However, as a concession to the illogical:
+*/
+
+#define setColorScheme setColourScheme
+#define setColor setColour
+#define getColor getColour
+#define puColor puColour
+#define puSetColor puSetColour
+#define puSetDefaultColorScheme puSetDefaultColourScheme
+#define puGetDefaultColorScheme puGetDefaultColourScheme
+
+
+typedef void *puFont ;
+
+#define PUFONT_8_BY_13 GLUT_BITMAP_8_BY_13
+#define PUFONT_9_BY_15 GLUT_BITMAP_9_BY_15
+#define PUFONT_TIMES_ROMAN_10 GLUT_BITMAP_TIMES_ROMAN_10
+#define PUFONT_TIMES_ROMAN_24 GLUT_BITMAP_TIMES_ROMAN_24
+#define PUFONT_HELVETICA_10 GLUT_BITMAP_HELVETICA_10
+#define PUFONT_HELVETICA_12 GLUT_BITMAP_HELVETICA_12
+#define PUFONT_HELVETICA_18 GLUT_BITMAP_HELVETICA_18
+
+#define PU_LEFT_BUTTON GLUT_LEFT_BUTTON
+#define PU_MIDDLE_BUTTON GLUT_MIDDLE_BUTTON
+#define PU_RIGHT_BUTTON GLUT_RIGHT_BUTTON
+#define PU_DOWN GLUT_DOWN
+#define PU_UP GLUT_UP
+#define PU_UP_AND_DOWN 254
+#define PU_DRAG 255
+#define PU_CONTINUAL PU_DRAG
+
+#define PU_KEY_GLUT_SPECIAL_OFFSET 256
+#define PU_KEY_F1 (GLUT_KEY_F1 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F2 (GLUT_KEY_F2 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F3 (GLUT_KEY_F3 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F4 (GLUT_KEY_F4 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F5 (GLUT_KEY_F5 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F6 (GLUT_KEY_F6 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F7 (GLUT_KEY_F7 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F8 (GLUT_KEY_F8 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F9 (GLUT_KEY_F9 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F10 (GLUT_KEY_F10 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F11 (GLUT_KEY_F11 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_F12 (GLUT_KEY_F12 + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_LEFT (GLUT_KEY_LEFT + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_UP (GLUT_KEY_UP + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_RIGHT (GLUT_KEY_RIGHT + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_DOWN (GLUT_KEY_DOWN + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_PAGE_UP (GLUT_KEY_PAGE_UP + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_PAGE_DOWN (GLUT_KEY_PAGE_DOWN + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_HOME (GLUT_KEY_HOME + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_END (GLUT_KEY_END + PU_KEY_GLUT_SPECIAL_OFFSET)
+#define PU_KEY_INSERT (GLUT_KEY_INSERT + PU_KEY_GLUT_SPECIAL_OFFSET)
+
+#define PUPLACE_DEFAULT PUPLACE_RIGHT
+#define PUPLACE_ABOVE 0
+#define PUPLACE_BELOW 1
+#define PUPLACE_LEFT 2
+#define PUPLACE_RIGHT 3
+
+#define PUCOL_FOREGROUND 0
+#define PUCOL_BACKGROUND 1
+#define PUCOL_HIGHLIGHT 2
+#define PUCOL_LABEL 3
+#define PUCOL_LEGEND 4
+#define PUCOL_MAX 5
+
+#define PUSLIDER_CLICK 0
+#define PUSLIDER_ALWAYS 1
+#define PUSLIDER_DELTA 2
+
+/* These styles may be negated to get 'highlighted' graphics */
+
+#define PUSTYLE_DEFAULT PUSTYLE_BEVELLED
+#define PUSTYLE_NONE 0
+#define PUSTYLE_PLAIN 1
+#define PUSTYLE_BEVELLED 2
+#define PUSTYLE_BOXED 3
+#define PUSTYLE_DROPSHADOW 4
+#define PUSTYLE_SPECIAL_UNDERLINED 5
+#define PUSTYLE_SMALL_BEVELLED 6
+#define PUSTYLE_RADIO 7
+#define PUSTYLE_MAX 8
+
+/* These are the gaps that we try to leave around text objects */
+
+#define PUSTR_TGAP 5
+#define PUSTR_BGAP 5
+#define PUSTR_LGAP 5
+#define PUSTR_RGAP 5
+#define PUSTR_MAX_HEIGHT ( 25 + PUSTR_TGAP + PUSTR_BGAP )
+
+#define PU_RADIO_BUTTON_SIZE 16
+
+extern int puRefresh ;
+
+#define PUCLASS_VALUE 0x00000001
+#define PUCLASS_OBJECT 0x00000002
+#define PUCLASS_INTERFACE 0x00000004
+#define PUCLASS_FRAME 0x00000008
+#define PUCLASS_TEXT 0x00000010
+#define PUCLASS_BUTTON 0x00000020
+#define PUCLASS_ONESHOT 0x00000040
+#define PUCLASS_POPUP 0x00000080
+#define PUCLASS_POPUPMENU 0x00000100
+#define PUCLASS_MENUBAR 0x00000200
+#define PUCLASS_INPUT 0x00000400
+#define PUCLASS_BUTTONBOX 0x00000800
+#define PUCLASS_SLIDER 0x00001000
+#define PUCLASS_DIALOGBOX 0x00002000
+
+class puValue ;
+class puObject ;
+class puInterface ;
+class puButtonBox ;
+class puFrame ;
+class puText ;
+class puButton ;
+class puOneShot ;
+class puPopup ;
+class puPopupMenu ;
+class puMenuBar ;
+class puInput ;
+class puSlider ;
+
+typedef float puColour [ 4 ] ; /* RGBA */
+
+struct puBox
+{
+ int min [ 2 ] ;
+ int max [ 2 ] ;
+
+ void draw ( int dx, int dy, int style, puColour colour[], int am_default ) ;
+ void extend ( puBox *bx ) ;
+
+ void empty ( void ) { min[0]=min[1]=1000000 ; max[0]=max[1]=-1000000 ; }
+ int isEmpty ( void ) { return min[0]>max[0] || min[1]>max[1] ; }
+} ;
+
+#define PUSTRING_MAX 80
+
+/* If you change - or add to these, be sure to change _puDefaultColourTable */
+
+extern puColour _puDefaultColourTable[] ;
+
+
+inline void puSetColour ( puColour dst, puColour src )
+{
+ dst[0] = src[0] ; dst[1] = src[1] ; dst[2] = src[2] ; dst[3] = src[3] ;
+}
+
+inline void puSetColour ( puColour c, float r, float g, float b, float a = 1.0f )
+{
+ c [ 0 ] = r ; c [ 1 ] = g ; c [ 2 ] = b ; c [ 3 ] = a ;
+}
+
+
+void puInit ( void ) ;
+void puDisplay ( void ) ;
+int puMouse ( int button, int updown, int x, int y ) ;
+int puMouse ( int x, int y ) ;
+int puKeyboard ( int key, int updown ) ;
+void puHideCursor ( void ) ;
+void puShowCursor ( void ) ;
+int puCursorIsHidden ( void ) ;
+
+void puDrawString ( puFont fnt, char *str, int x, int y ) ;
+int puGetStringWidth ( puFont fnt, char *str ) ;
+int puGetStringHeight ( puFont fnt = NULL ) ;
+int puGetStringDescender ( puFont fnt = NULL ) ;
+
+class puValue
+{
+protected:
+ int type ;
+ int integer ;
+ float floater ;
+ char string [ PUSTRING_MAX ] ;
+public:
+ puValue () { type = PUCLASS_VALUE ; clrValue () ; }
+
+ virtual ~puValue () ;
+
+ int getType ( void ) { return type ; }
+ char *getTypeString ( void ) ;
+ void clrValue ( void ) { setValue ( "" ) ; }
+
+ void setValue ( puValue *pv )
+ {
+ integer = pv -> integer ;
+ floater = pv -> floater ;
+ strcpy ( string, pv -> string ) ;
+ puRefresh = TRUE ;
+ }
+
+ void setValue ( int i ) { integer = i ; floater = (float) i ; sprintf ( string, "%d", i ) ; puRefresh = TRUE ; }
+ void setValue ( float f ) { integer = (int) f ; floater = f ; sprintf ( string, "%g", f ) ; puRefresh = TRUE ; }
+ void setValue ( char *s ) {
+ if ( s == NULL || s[0] == '\0' )
+ {
+ integer = 0 ;
+ floater = 0.0f ;
+ s = "" ;
+ }
+ else
+ {
+ integer = atoi(s) ;
+ floater = atof(s) ;
+
+ if ( string != s ) strcpy ( string, s ) ;
+ }
+ puRefresh = TRUE ;
+ }
+
+ void getValue ( int *i ) { *i = integer ; }
+ void getValue ( float *f ) { *f = floater ; }
+ void getValue ( char **s ) { *s = string ; }
+ void getValue ( char *s ) { strcpy ( s, string ) ; }
+
+ int getValue ( void ) { return integer ; }
+} ;
+
+typedef void (*puCallback)(class puObject *) ;
+
+void puSetDefaultStyle ( int style ) ;
+int puGetDefaultStyle ( void ) ;
+void puSetDefaultFonts ( puFont legendFont, puFont labelFont ) ;
+void puGetDefaultFonts ( puFont *legendFont, puFont *labelFont ) ;
+void puSetDefaultColourScheme ( float r, float g, float b, float a = 1.0 ) ;
+void puGetDefaultColourScheme ( float *r, float *g, float *b, float *a = NULL );
+
+class puObject : public puValue
+{
+protected:
+ puValue default_value ;
+
+ puBox bbox ; /* Bounding box of entire Object */
+ puBox abox ; /* Active (clickable) area */
+ puColour colour [ PUCOL_MAX ] ;
+ puInterface *parent ;
+
+ int active_mouse_edge ; /* is it PU_UP or PU_DOWN (or both) that activates this? */
+ int style ;
+ int visible ;
+ int active ;
+ int highlighted ;
+ int am_default ;
+
+ char *label ; puFont labelFont ; int labelPlace ;
+ char *legend ; puFont legendFont ;
+
+ void *user_data ;
+ puCallback cb ;
+
+ virtual void draw_label ( int dx, int dy ) ;
+ virtual int isHit ( int x, int y ) { return isVisible() && isActive() &&
+ x >= abox.min[0] &&
+ x <= abox.max[0] &&
+ y >= abox.min[1] &&
+ y <= abox.max[1] ; }
+ virtual void doHit ( int button, int updown, int x, int y ) ;
+
+public:
+ puObject ( int minx, int miny, int maxx, int maxy ) ;
+ ~puObject () ;
+
+ puObject *next ;
+ puObject *prev ;
+
+ puBox *getBBox ( void ) { return & bbox ; }
+ puBox *getABox ( void ) { return & abox ; }
+
+ void setPosition ( int x, int y )
+ {
+ if ( abox.isEmpty() )
+ {
+ abox.max[0] = abox.min[0] = x ;
+ abox.max[1] = abox.min[1] = y ;
+ }
+ else
+ {
+ abox.max[0] += x - abox.min[0] ;
+ abox.max[1] += y - abox.min[1] ;
+ abox.min[0] = x ;
+ abox.min[1] = y ;
+ }
+ recalc_bbox() ; puRefresh = TRUE ;
+ }
+
+ void setSize ( int w, int h )
+ {
+ abox.max[0] = abox.min[0] + w ;
+ abox.max[1] = abox.min[1] + h ;
+ recalc_bbox() ; puRefresh = TRUE ;
+ }
+
+ void getPosition ( int *x, int *y )
+ {
+ if ( abox . isEmpty () )
+ {
+ if ( x ) *x = 0 ;
+ if ( y ) *y = 0 ;
+ }
+ else
+ {
+ if ( x ) *x = abox.min[0] ;
+ if ( y ) *y = abox.min[1] ;
+ }
+ }
+
+ void getSize ( int *w, int *h )
+ {
+ if ( abox . isEmpty () )
+ {
+ if ( w ) *w = 0 ;
+ if ( h ) *h = 0 ;
+ }
+ else
+ {
+ if ( w ) *w = abox.max[0] - abox.min[0] ;
+ if ( h ) *h = abox.max[1] - abox.min[1] ;
+ }
+ }
+
+ virtual void recalc_bbox ( void ) ;
+ virtual int checkHit ( int button, int updown, int x, int y ) ;
+ virtual int checkKey ( int key , int updown ) ;
+ virtual void draw ( int dx, int dy ) = 0 ;
+
+ puInterface *getParent ( void ) { return parent ; }
+ puObject *getNextObject ( void ) { return next ; }
+ puObject *getPrevObject ( void ) { return prev ; }
+
+ void setCallback ( puCallback c ) { cb = c ; }
+ puCallback getCallback ( void ) { return cb ; }
+ void invokeCallback ( void ) { if ( cb ) (*cb)(this) ; }
+
+ void makeReturnDefault ( int def ) { am_default = def ; }
+ int isReturnDefault ( void ) { return am_default ; }
+
+ void setActiveDirn ( int e ) { active_mouse_edge = e ; }
+ int getActiveDirn ( void ) { return active_mouse_edge ; }
+
+ void setLegend ( char *l ) { legend = l ; recalc_bbox() ; puRefresh = TRUE ; }
+ char *getLegend ( void ) { return legend ; }
+
+ void setLegendFont ( puFont f ) { legendFont = f ; recalc_bbox() ; puRefresh = TRUE ; }
+ puFont getLegendFont ( void ) { return legendFont ; }
+
+ void setLabel ( char *l ) { label = l ; recalc_bbox() ; puRefresh = TRUE ; }
+ char *getLabel ( void ) { return label ; }
+
+ void setLabelFont ( puFont f ) { labelFont = f ; recalc_bbox() ; puRefresh = TRUE ; }
+ puFont getLabelFont ( void ) { return labelFont ; }
+
+ void setLabelPlace ( int lp ) { labelPlace = lp ; recalc_bbox() ; puRefresh = TRUE ; }
+ int getLabelPlace ( void ) { return labelPlace ; }
+
+ void activate ( void ) { if ( ! active ) { active = TRUE ; puRefresh = TRUE ; } }
+ void greyOut ( void ) { if ( active ) { active = FALSE ; puRefresh = TRUE ; } }
+ int isActive ( void ) { return active ; }
+
+ void highlight ( void ) { if ( ! highlighted ) { highlighted = TRUE ; puRefresh = TRUE ; } }
+ void lowlight ( void ) { if ( highlighted ) { highlighted = FALSE ; puRefresh = TRUE ; } }
+ int isHighlighted( void ){ return highlighted ; }
+
+ void reveal ( void ) { if ( ! visible ) { visible = TRUE ; puRefresh = TRUE ; } }
+ void hide ( void ) { if ( visible ) { visible = FALSE ; puRefresh = TRUE ; } }
+ int isVisible ( void ) { return visible ; }
+
+ void setStyle ( int which )
+ {
+ style = which ;
+ recalc_bbox () ;
+ puRefresh = TRUE ;
+ }
+
+ int getStyle ( void ) { return style ; }
+
+ void setColourScheme ( float r, float g, float b, float a = 1.0f ) ;
+
+ void setColour ( int which, float r, float g, float b, float a = 1.0f )
+ {
+ puSetColour ( colour [ which ], r, g, b, a ) ;
+ puRefresh = TRUE ;
+ }
+
+ void getColour ( int which, float *r, float *g, float *b, float *a = NULL )
+ {
+ if ( r ) *r = colour[which][0] ;
+ if ( g ) *g = colour[which][1] ;
+ if ( b ) *b = colour[which][2] ;
+ if ( a ) *a = colour[which][3] ;
+ }
+
+ void setUserData ( void *data ) { user_data = data ; }
+ void *getUserData ( void ) { return user_data ; }
+
+ void defaultValue ( void ) { setValue ( & default_value ) ; }
+
+ void setDefaultValue ( int i ) { default_value . setValue ( i ) ; }
+ void setDefaultValue ( float f ) { default_value . setValue ( f ) ; }
+ void setDefaultValue ( char *s ) { default_value . setValue ( s ) ; }
+
+ void getDefaultValue ( int *i ) { default_value . getValue ( i ) ; }
+ void getDefaultValue ( float *f ) { default_value . getValue ( f ) ; }
+ void getDefaultValue ( char **s ) { default_value . getValue ( s ) ; }
+ int getDefaultValue ( void ) { return default_value . getValue () ; }
+} ;
+
+/*
+ The 'live' interface stack is used for clicking and rendering.
+*/
+
+void puPushLiveInterface ( puInterface *in ) ;
+void puPopLiveInterface ( void ) ;
+int puNoLiveInterface ( void ) ;
+puInterface *puGetBaseLiveInterface ( void ) ;
+puInterface *puGetUltimateLiveInterface ( void ) ;
+
+/*
+ The regular interface stack is used for adding widgets
+*/
+
+void puPushInterface ( puInterface *in ) ;
+void puPopInterface ( void ) ;
+int puNoInterface ( void ) ;
+puInterface *puGetCurrInterface ( void ) ;
+
+class puInterface : public puObject
+{
+protected:
+ int num_children ;
+ puObject *dlist ;
+
+ void doHit ( int button, int updown, int x, int y ) ;
+
+public:
+
+ puInterface ( int x, int y ) : puObject ( x, y, x, y )
+ {
+ type |= PUCLASS_INTERFACE ;
+ dlist = NULL ;
+ num_children = 0 ;
+ puPushInterface ( this ) ;
+ puPushLiveInterface ( this ) ;
+ }
+
+ ~puInterface () ;
+
+ void recalc_bbox ( void ) ;
+ virtual void add ( puObject *new_object ) ;
+ virtual void remove ( puObject *old_object ) ;
+
+ void draw ( int dx, int dy ) ;
+ int checkHit ( int button, int updown, int x, int y ) ;
+ int checkKey ( int key , int updown ) ;
+
+ puObject *getFirstChild ( void ) { return dlist ; }
+ int getNumChildren ( void ) { return num_children ; }
+
+ virtual void close ( void )
+ {
+ if ( puGetCurrInterface () != this )
+ fprintf ( stderr, "PUI: puInterface::close() is mismatched!\n" ) ;
+ else
+ puPopInterface () ;
+ }
+} ;
+
+class puFrame : public puObject
+{
+protected:
+ virtual int isHit ( int /* x */, int /* y */ ) { return FALSE ; }
+public:
+ void draw ( int dx, int dy ) ;
+ puFrame ( int minx, int miny, int maxx, int maxy ) :
+ puObject ( minx, miny, maxx, maxy )
+ {
+ type |= PUCLASS_FRAME ;
+ }
+} ;
+
+
+class puText : public puObject
+{
+protected:
+ virtual int isHit ( int /* x */, int /* y */ ) { return FALSE ; }
+public:
+ void draw ( int dx, int dy ) ;
+ puText ( int x, int y ) : puObject ( x, y, x, y )
+ {
+ type |= PUCLASS_TEXT ;
+ }
+} ;
+
+
+class puButton : public puObject
+{
+protected:
+public:
+ void doHit ( int button, int updown, int x, int y ) ;
+ void draw ( int dx, int dy ) ;
+ puButton ( int minx, int miny, char *l ) :
+ puObject ( minx, miny,
+ minx + puGetStringWidth ( NULL, l ) + PUSTR_LGAP + PUSTR_RGAP,
+ miny + puGetStringHeight () + puGetStringDescender () + PUSTR_TGAP + PUSTR_BGAP )
+ {
+ type |= PUCLASS_BUTTON ;
+ setLegend ( l ) ;
+ }
+
+ puButton ( int minx, int miny, int maxx, int maxy ) :
+ puObject ( minx, miny, maxx, maxy )
+ {
+ type |= PUCLASS_BUTTON ;
+ }
+} ;
+
+
+class puSlider : public puObject
+{
+protected:
+ int vert ;
+ float last_cb_value ;
+ float cb_delta ;
+ int cb_mode ;
+ float slider_fraction ;
+public:
+ void doHit ( int button, int updown, int x, int y ) ;
+ void draw ( int dx, int dy ) ;
+ puSlider ( int minx, int miny, int sz, int vertical = FALSE ) :
+ puObject ( minx, miny, vertical ?
+ ( minx + puGetStringWidth ( NULL, "W" ) +
+ PUSTR_LGAP + PUSTR_RGAP ) :
+ ( minx + sz ),
+ vertical ?
+ ( miny + sz ) :
+ ( miny + puGetStringHeight () +
+ puGetStringDescender () +
+ PUSTR_TGAP + PUSTR_BGAP )
+ )
+ {
+ type |= PUCLASS_SLIDER ;
+ slider_fraction = 0.1f ;
+ getValue ( & last_cb_value ) ;
+ vert = vertical ;
+ cb_delta = 0.1f ;
+ cb_mode = PUSLIDER_ALWAYS ;
+ }
+
+ void setCBMode ( int m ) { cb_mode = m ; }
+ float getCBMode ( void ) { return cb_mode ; }
+
+ int isVertical ( void ) { return vert ; }
+
+ void setDelta ( float f ) { cb_delta = (f<=0.0f) ? 0.1f : (f>=1.0) ? 0.9 : f ; }
+ float getDelta ( void ) { return cb_delta ; }
+
+ void setSliderFraction ( float f ) { slider_fraction = (f<=0.0f) ? 0.1f : (f>=1.0) ? 0.9 : f ; }
+ float getSliderFraction ( void ) { return slider_fraction ; }
+} ;
+
+
+
+class puOneShot : public puButton
+{
+protected:
+public:
+ void doHit ( int button, int updown, int x, int y ) ;
+
+ puOneShot ( int minx, int miny, char *l ) : puButton ( minx, miny, l )
+ {
+ type |= PUCLASS_ONESHOT ;
+ }
+
+ puOneShot ( int minx, int miny, int maxx, int maxy ) :
+ puButton ( minx, miny, maxx, maxy )
+ {
+ type |= PUCLASS_ONESHOT ;
+ }
+} ;
+
+
+
+class puPopup : public puInterface
+{
+protected:
+public:
+ puPopup ( int x, int y ) : puInterface ( x, y )
+ {
+ type |= PUCLASS_POPUP ;
+ hide () ;
+ }
+} ;
+
+class puPopupMenu : public puPopup
+{
+protected:
+public:
+ puPopupMenu ( int x, int y ) : puPopup ( x, y )
+ {
+ type |= PUCLASS_POPUPMENU ;
+ }
+
+ puObject *add_item ( char *str, puCallback cb ) ;
+ int checkHit ( int button, int updown, int x, int y ) ;
+ int checkKey ( int key , int updown ) ;
+ void close ( void ) ;
+} ;
+
+
+class puMenuBar : public puInterface
+{
+protected:
+public:
+ puMenuBar ( int h = -1 ) :
+ puInterface ( 0, h < 0 ? glutGet((GLenum) GLUT_WINDOW_HEIGHT ) -
+ ( puGetStringHeight() + PUSTR_TGAP + PUSTR_BGAP ) : h )
+ {
+ type |= PUCLASS_MENUBAR ;
+ }
+
+ void add_submenu ( char *str, char *items[], puCallback cb[] ) ;
+ void close ( void ) ;
+} ;
+
+
+class puInput : public puObject
+{
+ int accepting ;
+ int cursor_position ;
+ int select_start_position ;
+ int select_end_position ;
+
+ void normalize_cursors ( void ) ;
+
+public:
+ void draw ( int dx, int dy ) ;
+ void doHit ( int button, int updown, int x, int y ) ;
+ int checkKey ( int key, int updown ) ;
+
+ int isAcceptingInput ( void ) { return accepting ; }
+ void rejectInput ( void ) { accepting = FALSE ; }
+ void acceptInput ( void ) { accepting = TRUE ;
+ cursor_position = strlen ( string ) ;
+ select_start_position = select_end_position = -1 ; }
+
+ int getCursor ( void ) { return cursor_position ; }
+ void setCursor ( int c ) { cursor_position = c ; }
+
+ void setSelectRegion ( int s, int e )
+ {
+ select_start_position = s ;
+ select_end_position = e ;
+ }
+
+ void getSelectRegion ( int *s, int *e )
+ {
+ if ( s ) *s = select_start_position ;
+ if ( e ) *e = select_end_position ;
+ }
+
+ puInput ( int minx, int miny, int maxx, int maxy ) :
+ puObject ( minx, miny, maxx, maxy )
+ {
+ type |= PUCLASS_INPUT ;
+
+ accepting = FALSE ;
+
+ cursor_position = 0 ;
+ select_start_position = -1 ;
+ select_end_position = -1 ;
+
+ setColourScheme ( 0.8, 0.7, 0.7 ) ; /* Yeukky Pink */
+ }
+} ;
+
+
+class puButtonBox : public puObject
+{
+protected:
+ int one_only ;
+ int num_kids ;
+ char **button_labels ;
+
+public:
+
+ puButtonBox ( int minx, int miny, int maxx, int maxy,
+ char **labels, int one_button ) ;
+
+ int isOneButton ( void ) { return one_only ; }
+
+ int checkKey ( int key , int updown ) ;
+ int checkHit ( int button, int updown, int x, int y ) ;
+ void draw ( int dx, int dy ) ;
+} ;
+
+
+
+class puDialogBox : public puPopup
+{
+protected:
+public:
+
+ puDialogBox ( int x, int y ) : puPopup ( x, y )
+ {
+ type |= PUCLASS_DIALOGBOX ;
+ }
+} ;
+
+#endif
+
--- /dev/null
+#include "puLocal.h"
+
+#define PU_BEVEL 5
+#define PU_SMALL_BEVEL 2
+#define PU_DFLT_OFFSET 8
+#define PU_BOX_WIDTH 2
+#define PU_DROPSHADOW_OFFSET 10
+
+void puBox::extend ( puBox *bx )
+{
+ if ( bx -> isEmpty () ) return ;
+
+ if ( min[0]>bx->min[0] ) min[0] = bx->min[0] ;
+ if ( min[1]>bx->min[1] ) min[1] = bx->min[1] ;
+ if ( max[0]<bx->max[0] ) max[0] = bx->max[0] ;
+ if ( max[1]<bx->max[1] ) max[1] = bx->max[1] ;
+}
+
+
+
+void puBox::draw ( int dx, int dy, int style, puColour colour[], int am_default )
+{
+ int hi, mid, lo ;
+
+ /* Colour assignments */
+
+ switch ( style )
+ {
+ case PUSTYLE_NONE :
+ return ;
+
+ case PUSTYLE_PLAIN :
+ case PUSTYLE_DROPSHADOW :
+ mid = PUCOL_FOREGROUND ;
+ lo = PUCOL_BACKGROUND ;
+ break ;
+
+ case PUSTYLE_SMALL_BEVELLED :
+ case PUSTYLE_BEVELLED :
+ case PUSTYLE_BOXED :
+ case PUSTYLE_SPECIAL_UNDERLINED :
+ mid = PUCOL_FOREGROUND ;
+ hi = PUCOL_HIGHLIGHT ;
+ lo = PUCOL_BACKGROUND ;
+ break ;
+
+ case PUSTYLE_RADIO :
+ case -PUSTYLE_RADIO :
+ hi = PUCOL_HIGHLIGHT ;
+ lo = PUCOL_BACKGROUND ;
+ break ;
+
+ case -PUSTYLE_PLAIN :
+ case -PUSTYLE_DROPSHADOW :
+ mid = PUCOL_HIGHLIGHT ;
+ lo = PUCOL_BACKGROUND ;
+ break ;
+
+ case -PUSTYLE_SMALL_BEVELLED :
+ case -PUSTYLE_BEVELLED :
+ case -PUSTYLE_BOXED :
+ case -PUSTYLE_SPECIAL_UNDERLINED :
+ mid = PUCOL_FOREGROUND ;
+ hi = PUCOL_BACKGROUND ;
+ lo = PUCOL_HIGHLIGHT ;
+ break ;
+
+ default :
+ fprintf ( stderr, "PUI: Unrecognised 'style' %d\n", style ) ;
+ return ;
+ }
+
+ switch ( abs(style) )
+ {
+ case PUSTYLE_PLAIN :
+ glColor4fv ( colour [ mid ] ) ;
+ glRecti ( dx + min[0], dy + min[1],
+ dx + max[0], dy + max[1] ) ;
+ break ;
+
+ case PUSTYLE_SMALL_BEVELLED :
+ glColor4fv ( colour [ hi ] ) ;
+ glBegin ( GL_QUAD_STRIP ) ;
+ glVertex2i ( dx + min[0] + PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL ) ;
+ glVertex2i ( dx + min[0], dy + min[1] ) ;
+ glVertex2i ( dx + min[0] + PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
+ glVertex2i ( dx + min[0], dy + max[1] ) ;
+ glVertex2i ( dx + max[0] - PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
+ glVertex2i ( dx + max[0], dy + max[1] ) ;
+ glEnd () ;
+ glColor4fv ( colour [ lo ] ) ;
+ glBegin ( GL_QUAD_STRIP ) ;
+ glVertex2i ( dx + min[0], dy + min[1] ) ;
+ glVertex2i ( dx + min[0] + PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL ) ;
+ glVertex2i ( dx + max[0], dy + min[1] ) ;
+ glVertex2i ( dx + max[0] - PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL ) ;
+ glVertex2i ( dx + max[0], dy + max[1] ) ;
+ glVertex2i ( dx + max[0] - PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
+ glEnd () ;
+ glColor4fv ( colour [ mid ] ) ;
+ glRecti ( dx + min[0] + PU_SMALL_BEVEL, dy + min[1] + PU_SMALL_BEVEL,
+ dx + max[0] - PU_SMALL_BEVEL, dy + max[1] - PU_SMALL_BEVEL ) ;
+ break ;
+
+ case PUSTYLE_BEVELLED :
+ glColor4fv ( colour [ hi ] ) ;
+ glBegin ( GL_QUAD_STRIP ) ;
+ glVertex2i ( dx + min[0] + PU_BEVEL, dy + min[1] + PU_BEVEL ) ;
+ glVertex2i ( dx + min[0], dy + min[1] ) ;
+ glVertex2i ( dx + min[0] + PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
+ glVertex2i ( dx + min[0], dy + max[1] ) ;
+ glVertex2i ( dx + max[0] - PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
+ glVertex2i ( dx + max[0], dy + max[1] ) ;
+ glEnd () ;
+ glColor4fv ( colour [ lo ] ) ;
+ glBegin ( GL_QUAD_STRIP ) ;
+ glVertex2i ( dx + min[0], dy + min[1] ) ;
+ glVertex2i ( dx + min[0] + PU_BEVEL, dy + min[1] + PU_BEVEL ) ;
+ glVertex2i ( dx + max[0], dy + min[1] ) ;
+ glVertex2i ( dx + max[0] - PU_BEVEL, dy + min[1] + PU_BEVEL ) ;
+ glVertex2i ( dx + max[0], dy + max[1] ) ;
+ glVertex2i ( dx + max[0] - PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
+ glEnd () ;
+ glColor4fv ( colour [ mid ] ) ;
+ glRecti ( dx + min[0] + PU_BEVEL, dy + min[1] + PU_BEVEL,
+ dx + max[0] - PU_BEVEL, dy + max[1] - PU_BEVEL ) ;
+ break ;
+
+ case PUSTYLE_BOXED :
+ glColor4fv ( colour [ hi ] ) ;
+ glRecti ( dx + min[0], dy + min[1],
+ dx + max[0], dy + max[1] ) ;
+ glColor4fv ( colour [ mid ] ) ;
+ glRecti ( dx + min[0]+PU_BOX_WIDTH, dy + min[1]+PU_BOX_WIDTH,
+ dx + max[0]-PU_BOX_WIDTH, dy + max[1]-PU_BOX_WIDTH ) ;
+ break ;
+
+ case PUSTYLE_RADIO :
+ glColor4fv ( colour [ lo ] ) ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1] ) ;
+ glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE , dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
+ glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1] + PU_RADIO_BUTTON_SIZE ) ;
+ glVertex2i ( dx + min[0] , dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
+ glEnd () ;
+
+ if ( style < 0 )
+ {
+ glColor4fv ( colour [ hi ] ) ;
+ glBegin ( GL_QUADS ) ;
+ glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1] + 2 ) ;
+ glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE-2, dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
+ glVertex2i ( dx + min[0] + PU_RADIO_BUTTON_SIZE/2, dy + min[1] + PU_RADIO_BUTTON_SIZE-2 ) ;
+ glVertex2i ( dx + min[0] + 2 , dy + min[1] + PU_RADIO_BUTTON_SIZE/2 ) ;
+ glEnd () ;
+ }
+ break ;
+
+ case PUSTYLE_SPECIAL_UNDERLINED :
+ glColor4fv ( colour [ hi ] ) ;
+ glRecti ( dx + min[0], dy + min[1],
+ dx + max[0], dy + min[1]+2 ) ;
+ glColor4fv ( colour [ mid ] ) ;
+ glRecti ( dx + min[0], dy + min[1]+1,
+ dx + max[0], dy + max[1] ) ;
+ break ;
+
+ case PUSTYLE_DROPSHADOW :
+ glColor4fv ( colour [ lo ] ) ;
+ glRecti ( dx + min[0] + PU_DROPSHADOW_OFFSET, dy + min[1] - PU_DROPSHADOW_OFFSET,
+ dx + max[0] + PU_DROPSHADOW_OFFSET, dy + max[1] - PU_DROPSHADOW_OFFSET ) ;
+ glColor4fv ( colour [ mid ] ) ;
+ glRecti ( dx + min[0], dy + min[1],
+ dx + max[0], dy + max[1] ) ;
+ break ;
+ }
+
+ if ( am_default )
+ {
+ glColor4fv ( colour [ PUCOL_BACKGROUND ] ) ;
+ glLineStipple ( 1, 0xF0F0 ) ;
+ glEnable ( GL_LINE_STIPPLE ) ;
+ glBegin ( GL_LINE_LOOP ) ;
+ glVertex2i ( dx + min[0] + PU_DFLT_OFFSET, dy + min[1] + PU_DFLT_OFFSET ) ;
+ glVertex2i ( dx + min[0] + PU_DFLT_OFFSET, dy + max[1] - PU_DFLT_OFFSET ) ;
+ glVertex2i ( dx + max[0] - PU_DFLT_OFFSET, dy + max[1] - PU_DFLT_OFFSET ) ;
+ glVertex2i ( dx + max[0] - PU_DFLT_OFFSET, dy + min[1] + PU_DFLT_OFFSET ) ;
+ glEnd () ;
+ glDisable ( GL_LINE_STIPPLE ) ;
+ }
+}
+
+
--- /dev/null
+
+#include "puLocal.h"
+
+void puButton::draw ( int dx, int dy )
+{
+ if ( !visible ) return ;
+
+ /* If button is pushed or highlighted - use inverse style for button itself */
+
+ abox . draw ( dx, dy, ( getValue() ^ highlighted ) ? -style : style, colour,
+ isReturnDefault() ) ;
+
+ /* If greyed out then halve the opacity when drawing the label and legend */
+
+ if ( active )
+ glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
+ else
+ glColor4f ( colour [ PUCOL_LEGEND ][0],
+ colour [ PUCOL_LEGEND ][1],
+ colour [ PUCOL_LEGEND ][2],
+ colour [ PUCOL_LEGEND ][3] / 2.0 ) ; /* 50% more transparent */
+
+ int xx = ( abox.max[0] - abox.min[0] - puGetStringWidth(legendFont,legend) ) / 2 ;
+ int yy = ( abox.max[1] - abox.min[1] - puGetStringHeight(legendFont) ) / 2 ;
+
+ puDrawString ( legendFont, legend,
+ dx + abox.min[0] + xx,
+ dy + abox.min[1] + yy ) ;
+
+ draw_label ( dx, dy ) ;
+}
+
+
+void puButton::doHit ( int button, int updown, int, int )
+{
+ if ( button == PU_LEFT_BUTTON )
+ {
+ if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
+ {
+ lowlight () ;
+ setValue ( (int) ! getValue () ) ;
+ invokeCallback () ;
+ }
+ else
+ highlight () ;
+ }
+ else
+ lowlight () ;
+}
+
--- /dev/null
+
+#include "puLocal.h"
+
+puButtonBox::puButtonBox ( int minx, int miny, int maxx, int maxy,
+ char **labels, int one_button ) :
+ puObject ( minx, miny, maxx, maxy )
+{
+ type |= PUCLASS_BUTTONBOX ;
+ one_only = one_button ;
+
+ button_labels = labels ;
+
+ for ( num_kids = 0 ; button_labels [ num_kids ] != NULL ; num_kids++ )
+ /* Count number of labels */ ;
+}
+
+
+int puButtonBox::checkKey ( int key, int updown )
+{
+ if ( updown == PU_UP ||
+ ! isReturnDefault() ||
+ ( key != '\r' && key != '\n' ) )
+ return FALSE ;
+
+ int v = getValue () ;
+
+ if ( ! one_only )
+ v = ~v ;
+ else
+ if ( v++ > num_kids )
+ v = 0 ;
+
+ setValue ( v ) ;
+ invokeCallback() ;
+ return TRUE ;
+}
+
+
+int puButtonBox::checkHit ( int button, int updown, int x, int y )
+{
+ if ( ! isHit ( x, y ) ||
+ ( updown != active_mouse_edge &&
+ active_mouse_edge != PU_UP_AND_DOWN ) )
+ return FALSE ;
+
+ int i = num_kids - 1 - (( y - abox.min[1] - PUSTR_BGAP ) * num_kids ) /
+ ( abox.max[1] - abox.min[1] - PUSTR_BGAP - PUSTR_TGAP ) ;
+
+ if ( i < 0 ) i = 0 ;
+ if ( i >= num_kids ) i = num_kids - 1 ;
+
+ if ( one_only )
+ setValue ( i ) ;
+ else
+ setValue ( getValue () ^ ( 1 << i ) ) ;
+
+ invokeCallback () ;
+ return TRUE ;
+}
+
+
+void puButtonBox::draw ( int dx, int dy )
+{
+ if ( !visible ) return ;
+
+ abox . draw ( dx, dy, style, colour, isReturnDefault() ) ;
+
+ for ( int i = 0 ; i < num_kids ; i++ )
+ {
+ puBox tbox ;
+
+ tbox . min [ 0 ] = abox.min [ 0 ] + PUSTR_LGAP + PUSTR_LGAP ;
+ tbox . min [ 1 ] = abox.min [ 1 ] + ((abox.max[1]-abox.min[1]-PUSTR_TGAP-PUSTR_BGAP)/num_kids) * (num_kids-1-i) ;
+ tbox . max [ 0 ] = tbox.min [ 0 ] ;
+ tbox . max [ 1 ] = tbox.min [ 1 ] ;
+
+ if (( one_only && i == getValue() ) ||
+ ( !one_only && ((1<<i) & getValue() ) != 0 ) )
+ tbox . draw ( dx, dy + PUSTR_BGAP + PUSTR_BGAP, -PUSTYLE_RADIO, colour, FALSE ) ;
+ else
+ tbox . draw ( dx, dy + PUSTR_BGAP + PUSTR_BGAP, PUSTYLE_RADIO, colour, FALSE ) ;
+
+ /* If greyed out then halve the opacity when drawing the label and legend */
+
+ if ( active )
+ glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
+ else
+ glColor4f ( colour [ PUCOL_LEGEND ][0],
+ colour [ PUCOL_LEGEND ][1],
+ colour [ PUCOL_LEGEND ][2],
+ colour [ PUCOL_LEGEND ][3] / 2.0 ) ; /* 50% more transparent */
+
+ puDrawString ( legendFont, button_labels[i],
+ dx + tbox.min[0] + PU_RADIO_BUTTON_SIZE + PUSTR_LGAP,
+ dy + tbox.min[1] + puGetStringDescender(legendFont) + PUSTR_BGAP + PUSTR_BGAP) ;
+ }
+
+ draw_label ( dx, dy ) ;
+}
+
--- /dev/null
+
+#include "puLocal.h"
+
+
--- /dev/null
+
+
+#include "puLocal.h"
+
+void puFrame::draw ( int dx, int dy )
+{
+ if ( !visible ) return ;
+
+ abox . draw ( dx, dy, style, colour, FALSE ) ;
+
+ /* If greyed out then halve the opacity when drawing the label and legend */
+
+ if ( active )
+ glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
+ else
+ glColor4f ( colour [ PUCOL_LEGEND ][0],
+ colour [ PUCOL_LEGEND ][1],
+ colour [ PUCOL_LEGEND ][2],
+ colour [ PUCOL_LEGEND ][3] / 2.0 ) ; /* 50% more transparent */
+
+ int xx = ( abox.max[0] - abox.min[0] - puGetStringWidth ( legendFont, legend ) ) / 2 ;
+
+ puDrawString ( legendFont, legend,
+ dx + abox.min[0] + xx,
+ dy + abox.min[1] + puGetStringDescender ( legendFont ) + PUSTR_BGAP ) ;
+
+ draw_label ( dx, dy ) ;
+}
+
+
--- /dev/null
+
+#include "puLocal.h"
+
+void puInput::normalize_cursors ( void )
+{
+ char val [ PUSTRING_MAX ] ;
+ getValue ( val ) ;
+ int sl = strlen ( val ) ;
+
+ /* Clamp the positions to the limits of the text. */
+
+ if ( cursor_position < 0 ) cursor_position = 0 ;
+ if ( select_start_position < 0 ) select_start_position = 0 ;
+ if ( select_end_position < 0 ) select_end_position = 0 ;
+ if ( cursor_position > sl ) cursor_position = sl ;
+ if ( select_start_position > sl ) select_start_position = sl ;
+ if ( select_end_position > sl ) select_end_position = sl ;
+
+ /* Swap the ends of the select window if they get crossed over */
+
+ if ( select_end_position < select_start_position )
+ {
+ int tmp = select_end_position ;
+ select_end_position = select_start_position ;
+ select_start_position = tmp ;
+ }
+}
+
+void puInput::draw ( int dx, int dy )
+{
+ normalize_cursors () ;
+
+ if ( !visible ) return ;
+
+ /* 3D Input boxes look nicest if they are always in inverse style. */
+
+ abox . draw ( dx, dy, (style==PUSTYLE_SMALL_BEVELLED) ? -style :
+ (accepting ? -style : style ), colour, FALSE ) ;
+
+ int xx = puGetStringWidth ( legendFont, " " ) ;
+ int yy = ( abox.max[1] - abox.min[1] - puGetStringHeight(legendFont) ) / 2 ;
+
+ if ( accepting )
+ {
+ char val [ PUSTRING_MAX ] ;
+ getValue ( val ) ;
+
+ /* Highlight the select area */
+
+ if ( select_end_position > 0 &&
+ select_end_position != select_start_position )
+ {
+ val [ select_end_position ] = '\0' ;
+ int cpos2 = puGetStringWidth ( legendFont, val ) + xx + dx + abox.min[0] ;
+ val [ select_start_position ] = '\0' ;
+ int cpos1 = puGetStringWidth ( legendFont, val ) + xx + dx + abox.min[0] ;
+
+ glColor3f ( 1.0, 1.0, 0.7 ) ;
+ glRecti ( cpos1, dy + abox.min[1] + 6 ,
+ cpos2, dy + abox.max[1] - 6 ) ;
+ }
+ }
+
+ /* Draw the text */
+
+ {
+ /* If greyed out then halve the opacity when drawing the label and legend */
+
+ if ( active )
+ glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
+ else
+ glColor4f ( colour [ PUCOL_LEGEND ][0],
+ colour [ PUCOL_LEGEND ][1],
+ colour [ PUCOL_LEGEND ][2],
+ colour [ PUCOL_LEGEND ][3] / 2.0 ) ; /* 50% more transparent */
+
+ char val [ PUSTRING_MAX ] ;
+ getValue ( val ) ;
+
+ puDrawString ( legendFont, val,
+ dx + abox.min[0] + xx,
+ dy + abox.min[1] + yy ) ;
+
+ draw_label ( dx, dy ) ;
+ }
+
+ if ( accepting )
+ {
+ char val [ PUSTRING_MAX ] ;
+ getValue ( val ) ;
+
+ /* Draw the 'I' bar cursor. */
+
+ if ( cursor_position >= 0 )
+ {
+ val [ cursor_position ] = '\0' ;
+
+ int cpos = puGetStringWidth ( legendFont, val ) + xx + dx + abox.min[0] ;
+
+ glColor3f ( 0.1, 0.1, 1.0 ) ;
+ glBegin ( GL_LINES ) ;
+ glVertex2i ( cpos , dy + abox.min[1] + 7 ) ;
+ glVertex2i ( cpos , dy + abox.max[1] - 7 ) ;
+ glVertex2i ( cpos - 1, dy + abox.min[1] + 7 ) ;
+ glVertex2i ( cpos - 1, dy + abox.max[1] - 7 ) ;
+ glVertex2i ( cpos - 4, dy + abox.min[1] + 7 ) ;
+ glVertex2i ( cpos + 3, dy + abox.min[1] + 7 ) ;
+ glVertex2i ( cpos - 4, dy + abox.max[1] - 7 ) ;
+ glVertex2i ( cpos + 3, dy + abox.max[1] - 7 ) ;
+ glEnd () ;
+ }
+ }
+}
+
+
+void puInput::doHit ( int button, int updown, int x, int /* y */ )
+{
+ if ( button == PU_LEFT_BUTTON )
+ {
+ /* Most GUI's activate a button on button-UP not button-DOWN. */
+
+ if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
+ {
+ lowlight () ;
+
+ char *strval ;
+ getValue ( & strval ) ;
+ char *tmpval = new char [ strlen(strval) + 1 ] ;
+ strcpy ( tmpval, strval ) ;
+
+ int i = strlen ( tmpval ) ;
+
+ while ( x <= puGetStringWidth ( legendFont, tmpval ) + abox.min[0] &&
+ i >= 0 )
+ tmpval[--i] = '\0' ;
+
+ accepting = TRUE ;
+ cursor_position = i ;
+ normalize_cursors () ;
+ invokeCallback () ;
+ }
+ else
+ highlight () ;
+ }
+ else
+ lowlight () ;
+}
+
+int puInput::checkKey ( int key, int updown )
+{
+ (updown,updown);
+
+ if ( ! isAcceptingInput() || ! isActive () || ! isVisible () )
+ return FALSE ;
+
+ normalize_cursors () ;
+
+ char *p ;
+
+ switch ( key )
+ {
+ case PU_KEY_PAGE_UP :
+ case PU_KEY_PAGE_DOWN :
+ case PU_KEY_INSERT : return FALSE ;
+
+ case PU_KEY_UP :
+ case PU_KEY_DOWN :
+ case 0x1B /* ESC */ :
+ case '\t' :
+ case '\r' :
+ case '\n' : /* Carriage return/Line Feed/TAB -- End of input */
+ rejectInput () ;
+ normalize_cursors () ;
+ invokeCallback () ;
+ break ;
+
+ case '\b' : /* Backspace */
+ if ( cursor_position > 0 )
+ for ( p = & string [ --cursor_position ] ; *p != '\0' ; p++ )
+ *p = *(p+1) ;
+ break ;
+
+ case 0x7F : /* DEL */
+ if ( select_start_position != select_end_position )
+ {
+ char *p1 = & string [ select_start_position ] ;
+ char *p2 = & string [ select_end_position ] ;
+
+ while ( *p1 != '\0' )
+ *p1++ = *p2++ ;
+
+ select_end_position = select_start_position ;
+ }
+ else
+ for ( p = & string [ cursor_position ] ; *p != '\0' ; p++ )
+ *p = *(p+1) ;
+ break ;
+
+ case 0x15 /* ^U */ : string [ 0 ] = '\0' ; break ;
+ case PU_KEY_HOME : cursor_position = 0 ; break ;
+ case PU_KEY_END : cursor_position = PUSTRING_MAX ; break ;
+ case PU_KEY_LEFT : cursor_position-- ; break ;
+ case PU_KEY_RIGHT : cursor_position++ ; break ;
+
+ default:
+ if ( key < ' ' || key > 127 ) return FALSE ;
+
+ if ( strlen ( string ) >= PUSTRING_MAX )
+ return FALSE ;
+
+ for ( p = & string [ strlen(string) ] ;
+ p != &string[cursor_position] ; p-- )
+ *(p+1) = *p ;
+
+ *p = key ;
+ cursor_position++ ;
+ break ;
+ }
+
+ setValue ( string ) ;
+ normalize_cursors () ;
+ return TRUE ;
+}
+
+
--- /dev/null
+
+#include "puLocal.h"
+
+#define PUSTACK_MAX 100
+
+static int currLiveInterface = -1 ;
+static puInterface *liveInterfaceStack [ PUSTACK_MAX ] ;
+static int currInterface = -1 ;
+static puInterface *interfaceStack [ PUSTACK_MAX ] ;
+
+void puPushLiveInterface ( puInterface *in )
+{
+ if ( currLiveInterface < PUSTACK_MAX )
+ liveInterfaceStack [ ++currLiveInterface ] = in ;
+ else
+ fprintf ( stderr, "PUI: Too many live puInterfaces open at once!\n" ) ;
+}
+
+void puPushInterface ( puInterface *in )
+{
+ if ( currInterface < PUSTACK_MAX )
+ interfaceStack [ ++currInterface ] = in ;
+ else
+ fprintf ( stderr, "PUI: Too many puInterfaces open at once!\n" ) ;
+}
+
+void puPopLiveInterface ( void )
+{
+ if ( currLiveInterface > 0 )
+ --currLiveInterface ;
+ else
+ fprintf ( stderr, "PUI: Live puInterface stack is empty!\n" ) ;
+}
+
+void puPopInterface ( void )
+{
+ if ( currInterface > 0 )
+ --currInterface ;
+ else
+ fprintf ( stderr, "PUI: puInterface stack is empty!\n" ) ;
+}
+
+int puNoLiveInterface ( void )
+{
+ return currLiveInterface < 0 ;
+}
+
+int puNoInterface ( void )
+{
+ return currInterface < 0 ;
+}
+
+puInterface *puGetUltimateLiveInterface ( void )
+{
+ if ( currLiveInterface < 0 )
+ {
+ fprintf ( stderr, "PUI: No Live Interface!\n" ) ;
+ return NULL ;
+ }
+
+ return liveInterfaceStack [ 0 ] ;
+}
+
+
+puInterface *puGetBaseLiveInterface ( void )
+{
+ if ( currLiveInterface < 0 )
+ {
+ fprintf ( stderr, "PUI: No Live Interface!\n" ) ;
+ return NULL ;
+ }
+
+ /*
+ Work down the interface stack until you
+ either get to the bottom or find a block
+ in the form of a puDialogBox.
+ */
+
+ for ( int i = currLiveInterface ; i > 0 ; i-- )
+ if ( liveInterfaceStack [ i ] -> getType () & PUCLASS_DIALOGBOX )
+ return liveInterfaceStack [ i ] ;
+
+ return liveInterfaceStack [ 0 ] ;
+}
+
+puInterface *puGetCurrInterface ( void )
+{
+ if ( currInterface < 0 )
+ {
+ fprintf ( stderr, "PUI: No Interface!\n" ) ;
+ return NULL ;
+ }
+
+ return interfaceStack [ currInterface ] ;
+}
+
+void puInterface::remove ( puObject *obj )
+{
+ if ( dlist == NULL )
+ return ;
+
+ /* Are we the first object in the list */
+
+ if ( obj -> prev == NULL )
+ dlist = obj -> next ;
+ else
+ obj -> prev -> next = obj -> next ;
+
+ /* Are we the last object in the list */
+
+ if ( obj -> next != NULL )
+ obj -> next -> prev = obj -> prev ;
+
+ obj -> next = NULL ;
+ obj -> prev = NULL ;
+
+ num_children-- ;
+ recalc_bbox () ;
+}
+
+void puInterface::add ( puObject *new_obj )
+{
+ if ( dlist == NULL )
+ {
+ dlist = new_obj ;
+ new_obj -> next = NULL ;
+ new_obj -> prev = NULL ;
+ }
+ else
+ {
+ puObject *last ;
+
+ for ( last = dlist ; last->next != NULL ; last = last->next )
+ /* Search for end of list. */ ;
+
+ last -> next = new_obj ;
+ new_obj -> prev = last ;
+ new_obj -> next = NULL ;
+ }
+
+ num_children++ ;
+ recalc_bbox () ;
+}
+
+int puInterface::checkKey ( int key, int updown )
+{
+ if ( dlist == NULL || ! isVisible () || ! isActive () )
+ return FALSE ;
+
+ puObject *bo ;
+
+ /*
+ We have to walk the list backwards to ensure that
+ the click order is the same as the DRAW order.
+ */
+
+ for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
+ /* Find the last object in our list. */ ;
+
+ for ( ; bo != NULL ; bo = bo->prev )
+ if ( bo -> checkKey ( key, updown ) )
+ return TRUE ;
+
+ return FALSE ;
+}
+
+int puInterface::checkHit ( int button, int updown, int x, int y )
+{
+ if ( dlist == NULL || ! isVisible () || ! isActive () )
+ return FALSE ;
+
+ /*
+ This might be a bit redundant - but it's too hard to keep
+ track of changing abox sizes when daughter objects are
+ changing sizes.
+ */
+
+ recalc_bbox () ;
+
+ puObject *bo ;
+
+ x -= abox.min[0] ;
+ y -= abox.min[1] ;
+
+ /*
+ We have to walk the list backwards to ensure that
+ the click order is the same as the DRAW order.
+ */
+
+ for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
+ /* Find the last object in our list. */ ;
+
+ for ( ; bo != NULL ; bo = bo->prev )
+ if ( bo -> checkHit ( button, updown, x, y ) )
+ return TRUE ;
+
+ return FALSE ;
+}
+
+
+void puInterface::draw ( int dx, int dy )
+{
+ if ( isVisible () )
+ for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
+ bo -> draw ( dx + abox.min[0], dy + abox.min[1] ) ;
+}
+
+
+void puInterface::recalc_bbox ( void )
+{
+ puBox contents ;
+ contents . empty () ;
+
+ for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
+ contents . extend ( bo -> getBBox() ) ;
+
+ if ( contents . isEmpty () )
+ {
+ abox . max[0] = abox . min[0] ;
+ abox . max[1] = abox . min[1] ;
+ }
+ else
+ {
+ abox . max[0] = abox . min[0] + contents . max[0] ;
+ abox . max[1] = abox . min[1] + contents . max[1] ;
+ }
+
+ puObject::recalc_bbox () ;
+}
+
+
+void puInterface::doHit ( int, int, int, int )
+{
+}
+
+
+puInterface::~puInterface ()
+{
+ puPopLiveInterface () ;
+
+ for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
+ delete bo ;
+}
+
+
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+#include <math.h>
+#include <GL/glut.h>
+#include "pu.h"
+
--- /dev/null
+
+#include "puLocal.h"
+
+void drop_down_the_menu ( puObject *b )
+{
+ puPopupMenu *p = (puPopupMenu *) b -> getUserData () ;
+
+ if ( b -> getValue () )
+ p->reveal () ;
+ else
+ p->hide () ;
+
+ for ( puObject *child = b -> getParent () -> getFirstChild () ;
+ child != NULL ; child = child -> next )
+ {
+ if (( child -> getType() & PUCLASS_BUTTON ) != 0 && child != b ) child -> clrValue () ;
+ if (( child -> getType() & PUCLASS_POPUPMENU ) != 0 && child != p ) child -> hide () ;
+ }
+}
+
+void puMenuBar::add_submenu ( char *str, char *items[], puCallback cb[] )
+{
+ int w, h ;
+ getSize ( &w, &h ) ;
+
+ puOneShot *b = new puOneShot ( w+10, 0, str ) ;
+ b -> setStyle ( PUSTYLE_SPECIAL_UNDERLINED ) ;
+ b -> setColourScheme ( colour[PUCOL_FOREGROUND][0],
+ colour[PUCOL_FOREGROUND][1],
+ colour[PUCOL_FOREGROUND][2],
+ colour[PUCOL_FOREGROUND][3] ) ;
+ b -> setCallback ( drop_down_the_menu ) ;
+ b -> setActiveDirn ( PU_UP_AND_DOWN ) ;
+
+ puPopupMenu *p = new puPopupMenu ( w+10, 0 ) ;
+
+ b -> setUserData ( p ) ;
+
+ for ( int i = 0 ; items[i] != NULL ; i++ )
+ p -> add_item ( items[i], cb[i] ) ;
+
+ p->close () ;
+ recalc_bbox () ;
+}
+
+void puMenuBar::close (void)
+{
+ puInterface::close () ;
+
+ if ( dlist == NULL )
+ return ;
+
+ int width = 0 ;
+ puObject *ob ;
+
+ /*
+ Use alternate objects - which gets the puOneShot/puPopupMenu pairs
+ */
+
+ for ( ob = dlist ; ob != NULL ; ob = ob -> next )
+ {
+ int w, h ;
+
+ /* Reposition the button so it looks nice */
+
+ ob -> getSize ( &w, &h ) ;
+ ob -> setPosition ( width, 0 ) ;
+ ob = ob -> next ;
+
+ /* Reposition the submenu so it sits under the button */
+
+ int w2, h2 ;
+ ob -> getSize ( &w2, &h2 ) ;
+ ob -> setPosition ( width, -h2 ) ;
+
+ /* Next please! */
+ width += w ;
+ }
+
+ recalc_bbox () ;
+}
+
+
--- /dev/null
+
+#include "puLocal.h"
+
+inline float clamp01 ( float x )
+{
+ return (x >= 1.0) ? 1.0 : x ;
+}
+
+static void load_colour_scheme ( float col[][4], float r, float g,
+ float b, float a )
+{
+ puSetColour ( col [ PUCOL_FOREGROUND ], r, g, b, a ) ;
+ puSetColour ( col [ PUCOL_BACKGROUND ], r/2, g/2, b/2, a ) ;
+ puSetColour ( col [ PUCOL_HIGHLIGHT ], clamp01(r*1.3), clamp01(g*1.3),
+ clamp01(b*1.3), a ) ;
+
+ if ( 4 * g + 3 * r + b > 0.5 )
+ puSetColour ( col [ PUCOL_LEGEND ], 0.0, 0.0, 0.0, a ) ;
+ else
+ puSetColour ( col [ PUCOL_LEGEND ], 1.0, 1.0, 1.0, a ) ;
+}
+
+
+static int defaultStyle = PUSTYLE_DEFAULT ;
+static puFont defaultLegendFont = NULL ;
+static puFont defaultLabelFont = NULL ;
+static float defaultColourScheme [ 4 ] ;
+
+void puSetDefaultStyle ( int style ) { defaultStyle = style ; }
+int puGetDefaultStyle ( void ) { return defaultStyle ; }
+
+void puSetDefaultFonts ( puFont legendFont, puFont labelFont )
+{
+ defaultLegendFont = legendFont ;
+ defaultLabelFont = labelFont ;
+}
+
+void puGetDefaultFonts ( puFont *legendFont, puFont *labelFont )
+{
+ if ( legendFont ) *legendFont = defaultLegendFont ;
+ if ( labelFont ) *labelFont = defaultLabelFont ;
+}
+
+void puSetDefaultColourScheme ( float r, float g, float b, float a )
+{
+ defaultColourScheme[0] = r ;
+ defaultColourScheme[1] = g ;
+ defaultColourScheme[2] = b ;
+ defaultColourScheme[3] = a ;
+ load_colour_scheme ( _puDefaultColourTable, r, g, b, a ) ;
+}
+
+void puGetDefaultColourScheme ( float *r, float *g, float *b, float *a )
+{
+ if ( r ) *r = defaultColourScheme[0] ;
+ if ( g ) *g = defaultColourScheme[1] ;
+ if ( b ) *b = defaultColourScheme[2] ;
+ if ( a ) *a = defaultColourScheme[3] ;
+}
+
+
+
+void puObject::setColourScheme ( float r, float g, float b, float a )
+{
+ load_colour_scheme ( colour, r, g, b, a ) ;
+}
+
+puObject::puObject ( int minx, int miny, int maxx, int maxy ) : puValue ()
+{
+ type |= PUCLASS_OBJECT ;
+ bbox.min[0] = abox.min[0] = minx ;
+ bbox.min[1] = abox.min[1] = miny ;
+ bbox.max[0] = abox.max[0] = maxx ;
+ bbox.max[1] = abox.max[1] = maxy ;
+
+ active_mouse_edge = PU_UP ;
+ style = defaultStyle ;
+ visible = active = TRUE ;
+ highlighted = FALSE ;
+ am_default = FALSE ;
+
+ cb = NULL ;
+ user_data = NULL ;
+ next = prev = NULL ;
+ label = NULL ;
+ labelPlace = PUPLACE_DEFAULT ;
+ labelFont = defaultLabelFont ;
+ legend = NULL ;
+ legendFont = defaultLegendFont ;
+
+ for ( int i = 0 ; i < PUCOL_MAX ; i++ )
+ puSetColour ( colour[i], _puDefaultColourTable[i] ) ;
+
+ if ( ! puNoInterface() )
+ {
+ parent = puGetCurrInterface() ;
+ parent -> add ( this ) ;
+ }
+ else
+ parent = NULL ;
+}
+
+
+puObject::~puObject ()
+{
+ if ( parent != this && parent != NULL )
+ parent -> remove ( this ) ;
+}
+
+void puObject::recalc_bbox ( void )
+{
+ bbox = abox ;
+
+ if ( label != NULL )
+ switch ( labelPlace )
+ {
+ case PUPLACE_ABOVE : bbox.max[1] += puGetStringHeight ( getLabelFont() ) + puGetStringDescender ( getLabelFont () ) + PUSTR_TGAP + PUSTR_BGAP ; break ;
+ case PUPLACE_BELOW : bbox.min[1] -= puGetStringHeight ( getLabelFont() ) + puGetStringDescender ( getLabelFont () ) + PUSTR_TGAP + PUSTR_BGAP ; break ;
+ case PUPLACE_LEFT : bbox.min[0] -= puGetStringWidth ( getLabelFont(), getLabel() ) + PUSTR_LGAP + PUSTR_RGAP ; break ;
+ case PUPLACE_RIGHT : bbox.max[0] += puGetStringWidth ( getLabelFont(), getLabel() ) + PUSTR_LGAP + PUSTR_RGAP ; break ;
+ }
+
+ if ( parent != NULL )
+ parent -> recalc_bbox () ;
+}
+
+void puObject::draw_label ( int dx, int dy )
+{
+ if ( !visible ) return ;
+
+ /* If greyed out then halve the opacity when drawing the label */
+
+ if ( active )
+ glColor4fv ( colour [ PUCOL_LABEL ] ) ;
+ else
+ glColor4f ( colour [ PUCOL_LABEL ][0],
+ colour [ PUCOL_LABEL ][1],
+ colour [ PUCOL_LABEL ][2],
+ colour [ PUCOL_LABEL ][3] / 2.0 ) ; /* 50% more transparent */
+
+ switch ( labelPlace )
+ {
+ case PUPLACE_ABOVE : puDrawString ( labelFont, label, dx + abox.min[0] + PUSTR_LGAP, dy + abox.max[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
+ case PUPLACE_BELOW : puDrawString ( labelFont, label, dx + abox.min[0] + PUSTR_LGAP, dy + bbox.min[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
+ case PUPLACE_LEFT : puDrawString ( labelFont, label, dx + bbox.min[0] + PUSTR_LGAP, dy + abox.min[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
+ case PUPLACE_RIGHT : puDrawString ( labelFont, label, dx + abox.max[0] + PUSTR_LGAP, dy + abox.min[1] + puGetStringDescender(labelFont) + PUSTR_BGAP ) ; break ;
+ }
+}
+
+
+int puObject::checkKey ( int key, int updown )
+{
+ if ( updown == PU_UP )
+ return FALSE ;
+
+ if ( isReturnDefault() && ( key == '\r' || key == '\n' ) )
+ {
+ checkHit ( PU_LEFT_BUTTON, PU_DOWN, (abox.min[0]+abox.max[0])/2,
+ (abox.min[1]+abox.max[1])/2 ) ;
+ checkHit ( PU_LEFT_BUTTON, PU_UP , (abox.min[0]+abox.max[0])/2,
+ (abox.min[1]+abox.max[1])/2 ) ;
+ return TRUE ;
+ }
+
+ return FALSE ;
+}
+
+
+void puObject::doHit ( int button, int updown, int x, int y )
+{
+ (x,x);(y,y);
+
+ if ( button == PU_LEFT_BUTTON )
+ {
+ if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
+ {
+ lowlight () ;
+ invokeCallback () ;
+ }
+ else
+ highlight () ;
+ }
+ else
+ lowlight () ;
+}
+
+int puObject::checkHit ( int button, int updown, int x, int y )
+{
+ if ( isHit( x, y ) )
+ {
+ doHit ( button, updown, x, y ) ;
+ return TRUE ;
+ }
+
+ lowlight () ;
+ return FALSE ;
+}
+
+
+char *puValue::getTypeString ( void )
+{
+ int i = getType () ;
+
+ if ( i & PUCLASS_DIALOGBOX ) return "puDialogBox" ;
+ if ( i & PUCLASS_SLIDER ) return "puSlider" ;
+ if ( i & PUCLASS_BUTTONBOX ) return "puButtonBox" ;
+ if ( i & PUCLASS_INPUT ) return "puInput" ;
+ if ( i & PUCLASS_MENUBAR ) return "puMenuBar" ;
+ if ( i & PUCLASS_POPUPMENU ) return "puPopupMenu" ;
+ if ( i & PUCLASS_POPUP ) return "puPopup" ;
+ if ( i & PUCLASS_ONESHOT ) return "puOneShot" ;
+ if ( i & PUCLASS_BUTTON ) return "puButton" ;
+ if ( i & PUCLASS_TEXT ) return "puText" ;
+ if ( i & PUCLASS_FRAME ) return "puFrame" ;
+ if ( i & PUCLASS_INTERFACE ) return "puInterface" ;
+ if ( i & PUCLASS_OBJECT ) return "puObject" ;
+ if ( i & PUCLASS_VALUE ) return "puValue" ;
+
+ return "Unknown Object type." ;
+}
+
+
--- /dev/null
+
+#include "puLocal.h"
+
+void puOneShot::doHit ( int button, int updown, int x, int y )
+{
+ puButton::doHit ( button, updown, x, y ) ;
+ setValue ( 0 ) ;
+}
+
--- /dev/null
+
+#include "puLocal.h"
+
--- /dev/null
+
+#include "puLocal.h"
+
+#define PUMENU_BUTTON_HEIGHT 25
+#define PUMENU_BUTTON_EXTRA_WIDTH 25
+
+puObject *puPopupMenu::add_item ( char *str, puCallback cb )
+{
+ int w, h ;
+ getSize ( &w, &h ) ;
+ puOneShot *b = new puOneShot ( 0, h, str ) ;
+ b->setStyle ( PUSTYLE_PLAIN ) ;
+ b->setColourScheme ( colour[PUCOL_FOREGROUND][0],
+ colour[PUCOL_FOREGROUND][1],
+ colour[PUCOL_FOREGROUND][2],
+ colour[PUCOL_FOREGROUND][3] ) ;
+ b->setCallback ( cb ) ;
+ recalc_bbox () ;
+ return b ;
+}
+
+void puPopupMenu::close ( void )
+{
+ puPopup::close () ;
+
+ int widest = 0 ;
+ puObject *ob = dlist ;
+
+ for ( ob = dlist ; ob != NULL ; ob = ob -> next )
+ {
+ int w, h ;
+
+ ob -> getSize ( &w, &h ) ;
+
+ if ( w > widest ) widest = w ;
+ }
+
+ for ( ob = dlist ; ob != NULL ; ob = ob -> next )
+ ob -> setSize ( widest, PUMENU_BUTTON_HEIGHT ) ;
+
+ recalc_bbox () ;
+}
+
+
+int puPopupMenu::checkKey ( int key, int updown )
+{
+ if ( dlist == NULL || ! isVisible () || ! isActive () )
+ return FALSE ;
+
+ if ( updown == PU_DOWN )
+ {
+ hide () ;
+
+ /* Turn everything off ready for next time. */
+
+ for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
+ bo -> clrValue () ;
+ }
+
+ puObject *bo ;
+
+ /*
+ We have to walk the list backwards to ensure that
+ the click order is the same as the DRAW order.
+ */
+
+ for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
+ /* Find the last object in our list. */ ;
+
+ for ( ; bo != NULL ; bo = bo->prev )
+ if ( bo -> checkKey ( key, updown ) )
+ return TRUE ;
+
+ return FALSE ;
+}
+
+
+int puPopupMenu::checkHit ( int button, int updown, int x, int y )
+{
+ if ( dlist == NULL || ! isVisible () || ! isActive () )
+ return FALSE ;
+
+ /* Must test 'isHit' before making the menu invisible! */
+
+ int hit = isHit ( x, y ) ;
+
+ if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
+ {
+ hide () ;
+
+ /* Turn everything off ready for next time. */
+
+ for ( puObject *bo = dlist ; bo != NULL ; bo = bo->next )
+ bo -> clrValue () ;
+ }
+
+ if ( ! hit )
+ return FALSE ;
+
+ /*
+ This might be a bit redundant - but it's too hard to keep
+ track of changing abox sizes when daughter objects are
+ changing sizes.
+ */
+
+ recalc_bbox () ;
+
+ puObject *bo ;
+
+ x -= abox.min[0] ;
+ y -= abox.min[1] ;
+
+ /*
+ We have to walk the list backwards to ensure that
+ the click order is the same as the DRAW order.
+ */
+
+ for ( bo = dlist ; bo->next != NULL ; bo = bo->next )
+ /* Find the last object in our list. */ ;
+
+ for ( ; bo != NULL ; bo = bo->prev )
+ if ( bo -> checkHit ( button, updown, x, y ) )
+ return TRUE ;
+
+ return FALSE ;
+}
+
--- /dev/null
+
+#include "puLocal.h"
+
+void puSlider::draw ( int dx, int dy )
+{
+ if ( !visible ) return ;
+
+ abox . draw ( dx, dy,
+ style==PUSTYLE_BEVELLED ? -PUSTYLE_BOXED : -style,
+ colour, FALSE ) ;
+
+ int sd, od ;
+
+ if ( isVertical() ) { sd = 1 ; od = 0 ; } else { sd = 0 ; od = 1 ; }
+
+ int sz = abox.max [sd] - abox.min [sd] ;
+
+ float val ;
+
+ getValue ( & val ) ;
+
+ if ( val < 0.0f ) val = 0.0f ;
+ if ( val > 1.0f ) val = 1.0f ;
+
+ val *= (float) sz * (1.0f - slider_fraction) ;
+
+ puBox bx ;
+
+ bx . min [ sd ] = abox . min [ sd ] + (int) val ;
+ bx . max [ sd ] = (int) ( (float) bx . min [ sd ] + (float) sz * slider_fraction ) ;
+ bx . min [ od ] = abox . min [ od ] + 2 ;
+ bx . max [ od ] = abox . max [ od ] - 2 ;
+
+ bx . draw ( dx, dy, PUSTYLE_SMALL_BEVELLED, colour, FALSE ) ;
+
+ /* If greyed out then halve the opacity when drawing the label and legend */
+
+ if ( active )
+ glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
+ else
+ glColor4f ( colour [ PUCOL_LEGEND ][0],
+ colour [ PUCOL_LEGEND ][1],
+ colour [ PUCOL_LEGEND ][2],
+ colour [ PUCOL_LEGEND ][3] / 2.0 ) ; /* 50% more transparent */
+
+ int xx = ( abox.max[0] - abox.min[0] - puGetStringWidth(legendFont,legend) ) / 2 ;
+ int yy = ( abox.max[1] - abox.min[1] - puGetStringHeight(legendFont) ) / 2 ;
+
+ puDrawString ( legendFont, legend,
+ dx + abox.min[0] + xx,
+ dy + abox.min[1] + yy ) ;
+
+ draw_label ( dx, dy ) ;
+}
+
+
+void puSlider::doHit ( int button, int updown, int x, int y )
+{
+ if ( button == PU_LEFT_BUTTON )
+ {
+ int sd = isVertical() ;
+ int sz = abox.max [sd] - abox.min [sd] ;
+ int coord = isVertical() ? y : x ;
+
+ float next_value ;
+
+ if ( sz == 0 )
+ next_value = 0.5f ;
+ else
+ {
+ next_value = ( (float)coord - (float)abox.min[sd] - (float)sz * slider_fraction / 2.0f ) /
+ ( (float) sz * (1.0f - slider_fraction) ) ;
+ }
+
+ next_value = (next_value < 0.0f) ? 0.0f : (next_value > 1.0) ? 1.0f : next_value ;
+
+ setValue ( next_value ) ;
+
+ switch ( cb_mode )
+ {
+ case PUSLIDER_CLICK :
+ if ( updown == active_mouse_edge )
+ {
+ last_cb_value = next_value ;
+ invokeCallback () ;
+ }
+ break ;
+
+ case PUSLIDER_DELTA :
+ if ( fabs ( last_cb_value - next_value ) >= cb_delta )
+ {
+ last_cb_value = next_value ;
+ invokeCallback () ;
+ }
+ break ;
+
+ case PUSLIDER_ALWAYS :
+ default :
+ last_cb_value = next_value ;
+ invokeCallback () ;
+ break ;
+ }
+ }
+}
+
+
--- /dev/null
+
+#include "puLocal.h"
+
+void puText::draw ( int dx, int dy )
+{
+ draw_label ( dx, dy ) ;
+}
+