void GLUI_List::draw_text(const char *t, int selected, int x, int y ) { int text_x, i, x_pos; int box_width; GLUI_DRAWINGSENTINAL_IDIOM /** Find where to draw the text **/ text_x = 2 + GLUI_LIST_BOXINNERMARGINX; /** Draw selection area dark **/ if ( enabled && selected ) { glColor3f( 0.0f, 0.0f, .6f ); glBegin( GL_QUADS ); glVertex2i(text_x, y+5 ); glVertex2i( w-text_x, y+5 ); glVertex2i(w-text_x, y+19 ); glVertex2i(text_x, y+19 ); glEnd(); } box_width = get_box_width(); if ( !selected || !enabled ) { /* No current selection */ x_pos = text_x; /* or control disabled */ if ( enabled ) glColor3b( 0, 0, 0 ); else glColor3b( 32, 32, 32 ); glRasterPos2i( text_x, y+15); i = 0; while( t[i] != '\0' && substring_width(t,0,i) < box_width) { glutBitmapCharacter( get_font(), t[i] ); x_pos += char_width( t[i] ); i++; } } else { /* There is a selection */ i = 0; x_pos = text_x; glColor3f( 1., 1., 1. ); glRasterPos2i( text_x, y+15); while( t[i] != '\0' && substring_width(t,0,i) < box_width) { glutBitmapCharacter( get_font(), t[i] ); x_pos += char_width( t[i] ); i++; } } }
void GLUI_EditText::draw_insertion_pt( void ) { int curr_x, i; if ( NOT can_draw() ) return; /*** Don't draw insertion pt if control is disabled ***/ if ( NOT enabled ) return; if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); if ( sel_start != sel_end OR insertion_pt < 0 ) { return; /* Don't draw insertion point if there is a current selection */ } /* printf( "insertion pt: %d\n", insertion_pt ); */ curr_x = this->x_abs + text_x_offset + substring_width( substring_start, substring_end ) + 2 /* The edittext box has a 2-pixel margin */ + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space between the text and the box **/ for( i=substring_end; i>=insertion_pt; i-- ) { curr_x -= char_width( text[i] ); } glColor3f( 0.0, 0.0, 0.0 ); glBegin( GL_LINE_LOOP ); /*** glVertex2i( curr_x, y_abs + 4 ); glVertex2i( curr_x, y_abs + 4 ); glVertex2i( curr_x, y_abs + h - 3 ); glVertex2i( curr_x, y_abs + h - 3 ); ***/ curr_x -= x_abs; glVertex2i( curr_x, 0 + 4 ); glVertex2i( curr_x, 0 + 4 ); glVertex2i( curr_x, 0 + h - 3 ); glVertex2i( curr_x, 0 + h - 3 ); glEnd(); if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); }
int GLUI_EditText::find_insertion_pt( int x, int y ) { int curr_x, i; /*** See if we clicked outside box ***/ if ( x < this->x_abs + text_x_offset ) return -1; /* We move from right to left, looking to see if the mouse was clicked to the right of the ith character */ curr_x = this->x_abs + text_x_offset + substring_width( substring_start, substring_end ) + 2 /* The edittext box has a 2-pixel margin */ + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space between the text and the box **/ /*** See if we clicked in an empty box ***/ if ( (int) text.length() == 0 ) return 0; /** find mouse click in text **/ for( i=substring_end; i>=substring_start; i-- ) { curr_x -= char_width( text[i] ); if ( x > curr_x ) { /* printf( "-> %d\n", i ); */ return i+1; } } return 0; /* Well, the mouse wasn't after any of the characters...see if it's before the beginning of the substring */ if ( 0 ) { if ( x > (x_abs + text_x_offset + 2 ) ) return substring_start; return -1; /* Nothing found */ } }
int GLUI_EditText::update_substring_bounds( void ) { int box_width; int text_len = (int)text.length(); int old_start, old_end; old_start = substring_start; old_end = substring_end; /*** Calculate the width of the usable area of the edit box ***/ box_width = MAX( this->w - this->text_x_offset - 4 /* 2 * the two-line box border */ - 2 * GLUI_EDITTEXT_BOXINNERMARGINX, 0 ); CLAMP( substring_end, 0, MAX(text_len-1,0) ); CLAMP( substring_start, 0, MAX(text_len-1,0) ); if ( debug ) dump( stdout, "-> UPDATE SS" ); if ( insertion_pt >= 0 AND insertion_pt < substring_start ) { /* cursor moved left */ substring_start = insertion_pt; while ( substring_width( substring_start, substring_end ) > box_width ) substring_end--; } else if ( insertion_pt > substring_end ) { /* cursor moved right */ substring_end = insertion_pt-1; while ( substring_width( substring_start, substring_end ) > box_width ) substring_start++; } else { /* cursor is within old substring bounds */ if ( last_insertion_pt > insertion_pt ) { /* cursor moved left */ } else { while ( substring_width( substring_start, substring_end ) > box_width ) substring_end--; while(substring_end < text_len-1 AND substring_width( substring_start, substring_end ) <= box_width) substring_end++; } } while ( substring_width( substring_start, substring_end ) > box_width ) substring_end--; last_insertion_pt = insertion_pt; /*** No selection if not enabled ***/ if ( NOT enabled ) { sel_start = sel_end = 0; } if ( debug ) dump( stdout, "<- UPDATE SS" ); if ( substring_start == old_start AND substring_end == old_end ) return false; /*** bounds did not change ***/ else return true; /*** bounds did change ***/ }
void GLUI_TextBox::draw_insertion_pt( void ) { int curr_x, box_width, text_length, eol, sol, line; if ( NOT can_draw() ) return; /*** Don't draw insertion pt if control is disabled ***/ if ( NOT enabled ) return; if ( sel_start != sel_end OR insertion_pt < 0 ) { return; /* Don't draw insertion point if there is a current selection */ } if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); /* printf( "insertion pt: %d\n", insertion_pt ); */ box_width = get_box_width(); // This function is unable to distinguish whether an insertion // point on a line break should be drawn on the line before or the line after. // This depends on the sequence of operations used to get there, and this // function just doesn't have that information. If curr_line were kept up // to date elsewhere that could be used here to disambiguate, but arrow keys // and such do not update it. sol = 0; eol = 0; text_length = text.length()-1; //while (eol < text_length && text[eol] != '\n' // && substring_width(sol, eol + 1) < box_width ) // eol++; line = 0; while (eol < insertion_pt && eol <= text_length) { if (text[eol] == '\n' || substring_width(sol, eol + 1) >= box_width) { eol++; if (text[eol]=='\n'||eol!=insertion_pt ||(eol==insertion_pt && eol>0 && text[eol-1]=='\n')) { sol = eol; line++; } } else { eol++; } } //glColor3f(1,0,0); //glRecti(0, curr_line*LINE_HEIGHT, 3, (curr_line+1)*LINE_HEIGHT); curr_line = line; if (scrollbar) scrollbar->set_int_val(start_line); if (curr_line < start_line || curr_line > (start_line + visible_lines)) /* Insertion pt out of draw area */ return; curr_x = this->x_abs + 2 /* The edittext box has a 2-pixel margin */ + GLUI_TEXTBOX_BOXINNERMARGINX; /** plus this many pixels blank space between the text and the box **/ curr_x += substring_width(sol,insertion_pt-1); if ((insertion_pt == (int)text.length() && text[text.length()-1] == '\n') || curr_x-this->x_abs > (w - 2 - GLUI_TEXTBOX_BOXINNERMARGINX)) { // Insert on the next line curr_x = this->x_abs + GLUI_TEXTBOX_BOXINNERMARGINX; line++; } /* update insertion coordinates */ insert_x = curr_x+5; /* I hate magic numbers too, these offset the imagined insertion point */ insert_y = (curr_line-start_line+2)*LINE_HEIGHT; glColor3f( 0.0, 0.0, 0.0 ); glBegin( GL_LINE_LOOP ); curr_x -= x_abs; glVertex2i( curr_x+1, (curr_line-start_line)*LINE_HEIGHT + 4 ); glVertex2i( curr_x, (curr_line-start_line)*LINE_HEIGHT + 4 ); glVertex2i( curr_x+1, (curr_line-start_line)*LINE_HEIGHT + 16 ); glVertex2i( curr_x, (curr_line-start_line)*LINE_HEIGHT + 16 ); glEnd(); if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); }
int GLUI_TextBox::find_insertion_pt( int x, int y ) { /*** See if we clicked outside box ***/ if ( x < this->x_abs || y < this->y_abs) return -1; /*** See if we clicked in an empty box ***/ if ( text.empty() ) return 0; /* update insert variables */ insert_x = x; insert_y = y; int text_length = text.length()-1; int box_width = get_box_width(); int sol = 0; int eol = 0; int line = 0; int y_off = y - (y_abs + 2 + GLUI_TEXTBOX_BOXINNERMARGINX); int x_off = x - (x_abs + 2 + GLUI_TEXTBOX_BOXINNERMARGINX); /* Find the line clicked, The possibility of long lines getting wrapped complicates this. */ while ((line-start_line+1)*LINE_HEIGHT < y_off && eol < text_length) { while (eol < text_length && text[eol] != '\n' && substring_width(sol, eol+1) <= box_width) { eol++; } if (text[eol]=='\n' && eol<text_length) { eol++; } line++; sol = eol; } curr_line = line; // Now search to the end of this line for the closest insertion point int prev_w=0,total_w=0,prev_eol=eol; while (eol <= text_length && (total_w=substring_width(prev_eol,eol,prev_w))< x_off && (eol==text_length||text[eol]!='\n')) { prev_w=total_w; eol++; prev_eol=eol; } if (total_w>=x_off) { // did we go far enough? (see if click was >1/2 width of last char) int decision_pt = prev_w+(total_w-prev_w)/2; if (x_off>decision_pt) eol++; } return eol; #if 0 while (eol < text_length && text[eol] != '\n' && substring_width(sol, eol+1) < box_width ) { eol++; } /* We move from right to left, looking to see if the mouse was clicked to the right of the ith character */ #if 0 int curr_x = this->x_abs + substring_width( sol, eol ) + 2 /* The edittext box has a 2-pixel margin */ + GLUI_TEXTBOX_BOXINNERMARGINX; /** plus this many pixels blank space between the text and the box **/ #endif /** find mouse click in text **/ if (x_off > substring_width(sol, eol)) return eol; for(i = sol; i <= eol+1; i++) { if (x_off <= substring_width(sol, i)) return i+1; } return 0; #endif }
int GLUI_TextBox::update_substring_bounds( void ) { int box_width; int text_len = text.length(); int old_start, old_end; old_start = substring_start; old_end = substring_end; /*** Calculate the width of the usable area of the edit box ***/ box_width = get_box_width(); CLAMP( substring_end, 0, MAX(text_len-1,0) ); CLAMP( substring_start, 0, MAX(text_len-1,0) ); if ( debug ) dump( stdout, "-> UPDATE SS" ); if ( insertion_pt >= 0 AND insertion_pt < substring_start ) { /* cursor moved left */ substring_start = insertion_pt; while ( substring_width( substring_start, substring_end ) > box_width ) substring_end--; } else if ( insertion_pt > substring_end ) { /* cursor moved right */ substring_end = insertion_pt-1; while ( substring_width( substring_start, substring_end ) > box_width ) substring_start++; } else { /* cursor is within old substring bounds */ if ( last_insertion_pt > insertion_pt ) { /* cursor moved left */ } else { while ( substring_width( substring_start, substring_end ) > box_width ) substring_end--; while(substring_width( substring_start, substring_end+1 ) <= box_width AND substring_end < text_len-1 ) substring_end++; } } while ( substring_width( substring_start, substring_end ) > box_width ) substring_end--; last_insertion_pt = insertion_pt; /*** No selection if not enabled ***/ if ( NOT enabled ) { sel_start = sel_end = 0; } if ( debug ) dump( stdout, "<- UPDATE SS" ); if ( substring_start == old_start AND substring_end == old_end ) return false; /*** bounds did not change ***/ else return true; /*** bounds did change ***/ }
void GLUI_TextBox::draw( int x, int y ) { GLUI_DRAWINGSENTINAL_IDIOM int line = 0; int text_length; int box_width; int i; /* Bevelled Border */ glBegin( GL_LINES ); glColor3f( .5, .5, .5 ); glVertex2i( 0, 0 ); glVertex2i( w, 0 ); glVertex2i( 0, 0 ); glVertex2i( 0, h ); glColor3f( 1., 1., 1. ); glVertex2i( 0, h ); glVertex2i( w, h ); glVertex2i( w, h ); glVertex2i( w, 0 ); if ( enabled ) glColor3f( 0., 0., 0. ); else glColor3f( .25, .25, .25 ); glVertex2i( 1, 1 ); glVertex2i( w-1, 1 ); glVertex2i( 1, 1 ); glVertex2i( 1, h-1 ); glColor3f( .75, .75, .75 ); glVertex2i( 1, h-1 ); glVertex2i( w-1, h-1 ); glVertex2i( w-1, h-1 ); glVertex2i( w-1, 1 ); glEnd(); /* Draw Background if enabled*/ if (enabled) { glColor3f( 1., 1., 1. ); glDisable( GL_CULL_FACE ); glBegin( GL_QUADS ); glVertex2i( 2, 2 ); glVertex2i( w-2, 2 ); glVertex2i( w-2, h-2 ); glVertex2i(2, h-2 ); glEnd(); } else { glColor3f( .8, .8, .8 ); glDisable( GL_CULL_FACE ); glBegin( GL_QUADS ); glVertex2i( 2, 2 ); glVertex2i( w-2, 2 ); glVertex2i( w-2, h-2 ); glVertex2i(2, h-2 ); glEnd(); } /* Begin Drawing Lines of Text */ substring_start = 0; substring_end = 0; text_length = text.length()-1; /* Figure out how wide the box is */ box_width = get_box_width(); /* Get the first line substring */ while (substring_width(substring_start, substring_end+1 ) < box_width && substring_end < text_length && text[substring_end+1] != '\n') substring_end++; /* Figure out which lines are visible*/ visible_lines = (int)(h-20)/LINE_HEIGHT; if (start_line < (curr_line-visible_lines)) { for (i = 0; ((curr_line-i)*LINE_HEIGHT+20) > h; i++); start_line = i; } else if ( start_line > curr_line) { start_line = curr_line; } line = 0; do { if (line && substring_end < text_length) { substring_start = substring_end+1; while (substring_width(substring_start, substring_end+1 ) < box_width && substring_end < text_length && text[substring_end+1] != '\n') substring_end++; } if (text[substring_end+1] == '\n') { /* Skip newline */ substring_end++; } if (line < start_line || (line > curr_line && curr_line > (start_line + visible_lines))) { line++; continue; } if ((line - start_line) <= visible_lines) draw_text(0,(line - start_line)*LINE_HEIGHT); /* tabs and other nasties are handled by substring_width */ line++; } while (substring_end < text_length); num_lines = line; draw_insertion_pt(); if (scrollbar) { scrollbar->set_int_limits(MAX(0,num_lines/*-1*/-visible_lines),0); glPushMatrix(); glTranslatef(scrollbar->x_abs-x_abs, scrollbar->y_abs-y_abs,0.0); scrollbar->draw_scroll(); glPopMatrix(); } }