From: curt Date: Fri, 12 Jun 1998 01:04:52 +0000 (+0000) Subject: Initial revision. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=cfe0e18e4efd3294f315f2fbeb19171a286bcb8c;p=flightgear.git Initial revision. --- diff --git a/PUI/Makefile.am b/PUI/Makefile.am new file mode 100644 index 000000000..05a1a5482 --- /dev/null +++ b/PUI/Makefile.am @@ -0,0 +1,24 @@ +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) + diff --git a/PUI/pu.cxx b/PUI/pu.cxx new file mode 100644 index 000000000..cde921b70 --- /dev/null +++ b/PUI/pu.cxx @@ -0,0 +1,238 @@ + +#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< checkHit ( button, PU_DRAG, x, + glutGet((GLenum)GLUT_WINDOW_HEIGHT) - y ) ; +} + diff --git a/PUI/pu.h b/PUI/pu.h new file mode 100644 index 000000000..dd26e9aa1 --- /dev/null +++ b/PUI/pu.h @@ -0,0 +1,744 @@ +#ifndef _PU_H_ +#define _PU_H_ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +# include +#endif + +#include +#include +#include +#include + +#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 + diff --git a/PUI/puBox.cxx b/PUI/puBox.cxx new file mode 100644 index 000000000..0fcb52427 --- /dev/null +++ b/PUI/puBox.cxx @@ -0,0 +1,193 @@ +#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]max[0] ) max[0] = bx->max[0] ; + if ( max[1]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 ) ; + } +} + + diff --git a/PUI/puButton.cxx b/PUI/puButton.cxx new file mode 100644 index 000000000..24a9802e1 --- /dev/null +++ b/PUI/puButton.cxx @@ -0,0 +1,50 @@ + +#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 () ; +} + diff --git a/PUI/puButtonBox.cxx b/PUI/puButtonBox.cxx new file mode 100644 index 000000000..4969c8311 --- /dev/null +++ b/PUI/puButtonBox.cxx @@ -0,0 +1,100 @@ + +#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< 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 ; +} + + diff --git a/PUI/puInterface.cxx b/PUI/puInterface.cxx new file mode 100644 index 000000000..cac02c396 --- /dev/null +++ b/PUI/puInterface.cxx @@ -0,0 +1,245 @@ + +#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 ; +} + + diff --git a/PUI/puLocal.h b/PUI/puLocal.h new file mode 100644 index 000000000..14a66ed1c --- /dev/null +++ b/PUI/puLocal.h @@ -0,0 +1,16 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#ifdef WIN32 +#include +#else +#include +#endif +#include +#include +#include "pu.h" + diff --git a/PUI/puMenuBar.cxx b/PUI/puMenuBar.cxx new file mode 100644 index 000000000..87a2299b4 --- /dev/null +++ b/PUI/puMenuBar.cxx @@ -0,0 +1,83 @@ + +#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 () ; +} + + diff --git a/PUI/puObject.cxx b/PUI/puObject.cxx new file mode 100644 index 000000000..1230396fd --- /dev/null +++ b/PUI/puObject.cxx @@ -0,0 +1,222 @@ + +#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." ; +} + + diff --git a/PUI/puOneShot.cxx b/PUI/puOneShot.cxx new file mode 100644 index 000000000..7d0f7c9ba --- /dev/null +++ b/PUI/puOneShot.cxx @@ -0,0 +1,9 @@ + +#include "puLocal.h" + +void puOneShot::doHit ( int button, int updown, int x, int y ) +{ + puButton::doHit ( button, updown, x, y ) ; + setValue ( 0 ) ; +} + diff --git a/PUI/puPopup.cxx b/PUI/puPopup.cxx new file mode 100644 index 000000000..59a5fef5c --- /dev/null +++ b/PUI/puPopup.cxx @@ -0,0 +1,3 @@ + +#include "puLocal.h" + diff --git a/PUI/puPopupMenu.cxx b/PUI/puPopupMenu.cxx new file mode 100644 index 000000000..52ffbd9ac --- /dev/null +++ b/PUI/puPopupMenu.cxx @@ -0,0 +1,127 @@ + +#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 ; +} + diff --git a/PUI/puSlider.cxx b/PUI/puSlider.cxx new file mode 100644 index 000000000..298269e48 --- /dev/null +++ b/PUI/puSlider.cxx @@ -0,0 +1,106 @@ + +#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 ; + } + } +} + + diff --git a/PUI/puText.cxx b/PUI/puText.cxx new file mode 100644 index 000000000..032c01629 --- /dev/null +++ b/PUI/puText.cxx @@ -0,0 +1,8 @@ + +#include "puLocal.h" + +void puText::draw ( int dx, int dy ) +{ + draw_label ( dx, dy ) ; +} +