diff options
author | Ton Roosendaal <ton@blender.org> | 2005-11-20 13:04:45 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2005-11-20 13:04:45 +0300 |
commit | 77332fa698fb79cc1d0c1539161e0e85c93b68f7 (patch) | |
tree | b02b7ce3c8245c51ff96eb4f45d4532846e8ff78 /source | |
parent | a86b0af575c6dad58b8c6ef223d20f5e76a055ed (diff) |
Patch by Matt Ebb: upgraded usablitiy of text button.
Textbuttons now allow a selection too (like any textbutton in other UIs).
By default, on activating a textbutton, the entire button text is selected
when you enter the button. A single arrowkey or LMB click reveils the
cursor then. Here's more user notes:
LMB click: If inside the button, places the text cursor at the clicked
position. If outside the button, confirms/finishes editing
LMB drag: Selects the text between the start and end point of the drag.
Backspace: Deletes selected text, or backspaces a character
Shift Backspace: Deletes all, as before.
Delete: Deletes selected text or forward deletes a character
Shift LeftArrow: Extends the selection left
Shift RightArrow: Extends the selection right
LeftArrow: If there's a selection, move the cursor to the left edge of the
selection, otherwise move the cursor left a character.
RightArrow: If there's a selection, move the cursor to the right edge of
the selection, otherwise move the cursor right a character.
UpArrow/Home: Move the cursor to the beginning of the line
DownArrow/End: Move the cursor to the end of the line
Ctrl Left arrow and Ctrl Right arrow to jump between directory separators
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/include/BIF_resources.h | 2 | ||||
-rw-r--r-- | source/blender/include/interface.h | 8 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 8 | ||||
-rw-r--r-- | source/blender/python/api2_2x/doc/Theme.py | 1 | ||||
-rw-r--r-- | source/blender/python/api2_2x/windowTheme.c | 4 | ||||
-rw-r--r-- | source/blender/src/interface.c | 263 | ||||
-rw-r--r-- | source/blender/src/interface_draw.c | 62 | ||||
-rw-r--r-- | source/blender/src/resources.c | 4 | ||||
-rw-r--r-- | source/blender/src/usiblender.c | 10 |
9 files changed, 304 insertions, 58 deletions
diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h index 8df1117c6d4..8c05d96ec72 100644 --- a/source/blender/include/BIF_resources.h +++ b/source/blender/include/BIF_resources.h @@ -409,6 +409,8 @@ enum { TH_REDALERT, TH_CUSTOM, + TH_BUT_TEXTFIELD_HI, + TH_THEMEUI, // common colors among spaces diff --git a/source/blender/include/interface.h b/source/blender/include/interface.h index 0b61ed80010..7a45e6566b4 100644 --- a/source/blender/include/interface.h +++ b/source/blender/include/interface.h @@ -63,7 +63,11 @@ #define PNL_TABBED 8 #define PNL_OVERLAP 16 - +/* Button text selection: + * extension direction, selextend, inside ui_do_but_TEX */ +#define EXTEND_LEFT 1 +#define EXTEND_RIGHT 2 +#define SELWIDTH (but->selend - but->selsta) typedef struct { short xim, yim; @@ -103,7 +107,7 @@ typedef struct { struct uiBut { uiBut *next, *prev; - short type, pointype, bit, bitnr, retval, strwidth, ofs, pos; + short type, pointype, bit, bitnr, retval, strwidth, ofs, pos, selsta, selend; int flag; char *str; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 352b2cc4928..aa835780b1a 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -48,6 +48,7 @@ typedef struct ThemeUI { char setting2[4]; char num[4]; char textfield[4]; + char textfield_hi[4]; char popup[4]; char text[4]; char text_hi[4]; @@ -56,10 +57,9 @@ typedef struct ThemeUI { char menu_hilite[4]; char menu_text[4]; char menu_text_hi[4]; - - char but_drawtype, pad; - short pad1; - int pad2; + + char but_drawtype; + char pad1[3]; } ThemeUI; diff --git a/source/blender/python/api2_2x/doc/Theme.py b/source/blender/python/api2_2x/doc/Theme.py index 743b40a7e8b..6cbafab9653 100644 --- a/source/blender/python/api2_2x/doc/Theme.py +++ b/source/blender/python/api2_2x/doc/Theme.py @@ -130,6 +130,7 @@ class Theme: @ivar setting2: theme rgba var. @ivar num: theme rgba var. @ivar textfield: theme rgba var. + @ivar textfield_hi: theme rgba var. @ivar popup: theme rgba var. @ivar text: theme rgba var. @ivar text_hi: theme rgba var. diff --git a/source/blender/python/api2_2x/windowTheme.c b/source/blender/python/api2_2x/windowTheme.c index ca4d1603bb7..d07323d0ccd 100644 --- a/source/blender/python/api2_2x/windowTheme.c +++ b/source/blender/python/api2_2x/windowTheme.c @@ -361,6 +361,7 @@ static PyObject *ThemeUI_getAttr( BPy_ThemeUI * self, char *name ) ELSEIF_TUI_RGBA( setting2 ) ELSEIF_TUI_RGBA( num ) ELSEIF_TUI_RGBA( textfield ) + ELSEIF_TUI_RGBA( textfield_hi ) ELSEIF_TUI_RGBA( popup ) ELSEIF_TUI_RGBA( text ) ELSEIF_TUI_RGBA( text_hi ) @@ -375,7 +376,7 @@ static PyObject *ThemeUI_getAttr( BPy_ThemeUI * self, char *name ) attrib = Py_BuildValue( "[ssssssssssssssssss]", "theme", "outline", "neutral", "action", "setting", "setting1", "setting2", - "num", "textfield", "popup", "text", + "num", "textfield", "textfield_hi", "popup", "text", "text_hi", "menu_back", "menu_item", "menu_hilite", "menu_text", "menu_text_hi", "drawType" ); @@ -401,6 +402,7 @@ static int ThemeUI_setAttr( BPy_ThemeUI * self, char *name, PyObject * value ) ELSEIF_TUI_RGBA( setting2 ) ELSEIF_TUI_RGBA( num ) ELSEIF_TUI_RGBA( textfield ) + ELSEIF_TUI_RGBA( textfield_hi ) ELSEIF_TUI_RGBA( popup ) ELSEIF_TUI_RGBA( text ) ELSEIF_TUI_RGBA( text_hi ) diff --git a/source/blender/src/interface.c b/source/blender/src/interface.c index 4c9cb4738f6..f589efa71e1 100644 --- a/source/blender/src/interface.c +++ b/source/blender/src/interface.c @@ -1283,6 +1283,51 @@ static uiBut *ui_but_last(uiBlock *block) return NULL; } + +/* ************* IN-BUTTON TEXT SELECTION/EDITING ************* */ + +static short ui_delete_selection_edittext(uiBut *but) +{ + int x; + short deletedwidth=0; + char *str; + + str= (char *)but->poin; + + deletedwidth = SELWIDTH; + + for(x=0; x< strlen(str); x++) { + if (but->selend + x <= strlen(str) ) { + str[but->selsta + x]= str[but->selend + x]; + } else { + str[but->selsta + x]= '\0'; + break; + } + } + but->pos = but->selend = but->selsta; + + return deletedwidth; +} + +static void ui_set_cursor_pos_edittext(uiBut *but, short sx) +{ + char backstr[UI_MAX_DRAW_STR]; + + BLI_strncpy(backstr, but->drawstr, UI_MAX_DRAW_STR); + but->pos= strlen(backstr)-but->ofs; + + while((but->aspect*BIF_GetStringWidth(but->font, backstr+but->ofs, 0) + but->x1) > sx) { + if (but->pos <= 0) break; + but->pos--; + backstr[but->pos+but->ofs] = 0; + } + + but->pos -= strlen(but->str); + but->pos += but->ofs; + if(but->pos<0) but->pos= 0; +} + + /* ************* EVENTS ************* */ void uiGetMouse(int win, short *adr) @@ -1495,9 +1540,9 @@ static int ui_do_but_ROW(uiBlock *block, uiBut *but) static int ui_do_but_TEX(uiBut *but) { unsigned short dev; - short x, mval[2], len=0, dodraw; + short x, mval[2], len=0, dodraw, selextend=0; char *str, backstr[UI_MAX_DRAW_STR]; - short capturing; + short capturing, sx, sy, prevx; str= (char *)but->poin; @@ -1505,20 +1550,14 @@ static int ui_do_but_TEX(uiBut *but) uiGetMouse(mywinget(), mval); - /* calculate cursor pos with current mousecoords */ BLI_strncpy(backstr, but->drawstr, UI_MAX_DRAW_STR); - but->pos= strlen(backstr)-but->ofs; - - while((but->aspect*BIF_GetStringWidth(but->font, backstr+but->ofs, 0) + but->x1) > mval[0]) { - if (but->pos <= 0) break; - but->pos--; - backstr[but->pos+but->ofs] = 0; - } - but->pos -= strlen(but->str); - but->pos += but->ofs; - if(but->pos<0) but->pos= 0; - + /* set cursor pos to the end of the text */ + but->pos = strlen(but->str); + + but->selsta = 0; + but->selend = strlen(but->drawstr) - strlen(but->str); + /* backup */ BLI_strncpy(backstr, but->poin, UI_MAX_DRAW_STR); @@ -1538,21 +1577,62 @@ static int ui_do_but_TEX(uiBut *but) dev = extern_qread_ext(&val, &ascii); if(dev==INPUTCHANGE) break; - else if(get_mbut() & L_MOUSE) break; else if(get_mbut() & R_MOUSE) break; + else if(get_mbut() & L_MOUSE) { + uiGetMouse(mywinget(), mval); + sx = mval[0]; sy = mval[1]; + + if ((but->y1 <= sy) && (sy <= but->y2) && (but->x1 <= sx) && (sx <= but->x2)) { + ui_set_cursor_pos_edittext(but, mval[0]); + + but->selsta = but->selend = but->pos; + + /* drag text select */ + prevx= mval[0]; + while (get_mbut() & L_MOUSE) { + uiGetMouse(mywinget(), mval); + + if(prevx!=mval[0]) { + + if (mval[0] > sx) selextend = EXTEND_RIGHT; + else if (mval[0] < sx) selextend = EXTEND_LEFT; + + ui_set_cursor_pos_edittext(but, mval[0]); + + if (selextend == EXTEND_RIGHT) but->selend = but->pos; + if (selextend == EXTEND_LEFT) but->selsta = but->pos; + + ui_check_but(but); + ui_draw_but(but); + ui_block_flush_back(but->block); + } + PIL_sleep_ms(10); + } + dodraw= 1; + } else break; + } else if(dev==ESCKEY) break; else if(dev==MOUSEX) val= 0; else if(dev==MOUSEY) val= 0; if(ascii) { - if(len < but->max) { - for(x= but->max; x>but->pos; x--) - str[x]= str[x-1]; - str[but->pos]= ascii; - but->pos++; - len++; - str[len]= '\0'; - dodraw= 1; + if(len <= but->max) { + + /* type over the current selection */ + if (SELWIDTH > 0) { + len -= ui_delete_selection_edittext(but); + } + + /* add ascii characters */ + if(len < but->max) { + for(x= but->max; x>but->pos; x--) + str[x]= str[x-1]; + str[but->pos]= ascii; + but->pos++; + len++; + str[len]= '\0'; + dodraw= 1; + } } } else if(val) { @@ -1560,25 +1640,125 @@ static int ui_do_but_TEX(uiBut *but) switch (dev) { case RIGHTARROWKEY: - if(G.qual & LR_SHIFTKEY) but->pos= strlen(str); - else but->pos++; - if(but->pos>strlen(str)) but->pos= strlen(str); + /* if there's a selection */ + if (SELWIDTH > 0) { + /* extend the selection based on the first direction taken */ + if(G.qual & LR_SHIFTKEY) { + if (!selextend) { + selextend = EXTEND_RIGHT; + } + if (selextend == EXTEND_RIGHT) { + but->selend++; + if (but->selend > len) but->selend = len; + } else if (selextend == EXTEND_LEFT) { + but->selsta++; + /* if the selection start has gone past the end, + * flip them so they're in sync again */ + if (but->selsta == but->selend) { + but->pos = but->selsta; + selextend = EXTEND_RIGHT; + } + } + } else { + but->selsta = but->pos = but->selend; + selextend = 0; + } + } else { + if(G.qual & LR_SHIFTKEY) { + /* make a selection, starting from the cursor position */ + but->selsta = but->pos; + + but->pos++; + if(but->pos>strlen(str)) but->pos= strlen(str); + + but->selend = but->pos; + } else if(G.qual & LR_CTRLKEY) { + while(but->pos < len){ + but->pos++; +#ifdef WIN32 + if(str[but->pos]=='\\') break; +#else + if(str[but->pos]=='/') break; +#endif + } + } else { + but->pos++; + if(but->pos>strlen(str)) but->pos= strlen(str); + } + } dodraw= 1; break; case LEFTARROWKEY: - if(G.qual & LR_SHIFTKEY) but->pos= 0; - else if(but->pos>0) but->pos--; + /* if there's a selection */ + if (SELWIDTH > 0) { + /* extend the selection based on the first direction taken */ + if(G.qual & LR_SHIFTKEY) { + if (!selextend) { + selextend = EXTEND_LEFT; + } + if (selextend == EXTEND_LEFT) { + but->selsta--; + if (but->selsta < 0) but->selsta = 0; + } else if (selextend == EXTEND_RIGHT) { + but->selend--; + /* if the selection start has gone past the end, + * flip them so they're in sync again */ + if (but->selsta == but->selend) { + but->pos = but->selsta; + selextend = EXTEND_LEFT; + } + } + } else { + but->pos = but->selend = but->selsta; + selextend = 0; + } + } else { + if(G.qual & LR_SHIFTKEY) { + /* make a selection, starting from the cursor position */ + but->selend = but->pos; + + but->pos--; + if(but->pos<0) but->pos= 0; + + but->selsta = but->pos; + } else if(G.qual & LR_CTRLKEY) { + while(but->pos > 0){ + but->pos--; +#ifdef WIN32 + if(str[but->pos]=='\\') break; +#else + if(str[but->pos]=='/') break; +#endif + } + } else { + if(but->pos>0) but->pos--; + } + } dodraw= 1; break; + case DOWNARROWKEY: case ENDKEY: - but->pos= strlen(str); + if(G.qual & LR_SHIFTKEY) { + but->selsta = but->pos; + but->selend = strlen(str); + selextend = EXTEND_RIGHT; + } else { + but->selsta = but->selend = but->pos= strlen(str); + } dodraw= 1; break; - + + case UPARROWKEY: case HOMEKEY: - but->pos= 0; + if(G.qual & LR_SHIFTKEY) { + but->selend = but->pos; + but->selsta = 0; + selextend = EXTEND_LEFT; + } else { + but->selsta = but->selend = but->pos= 0; + } dodraw= 1; break; @@ -1588,7 +1768,13 @@ static int ui_do_but_TEX(uiBut *but) break; case DELKEY: - if(but->pos>=0 && but->pos<strlen(str)) { + if (SELWIDTH > 0) { + len -= ui_delete_selection_edittext(but); + + if (len < 0) len = 0; + dodraw=1; + } + else if(but->pos>=0 && but->pos<strlen(str)) { for(x=but->pos; x<=strlen(str); x++) str[x]= str[x+1]; str[--len]='\0'; @@ -1598,7 +1784,13 @@ static int ui_do_but_TEX(uiBut *but) case BACKSPACEKEY: if(len!=0) { - if(get_qual() & LR_SHIFTKEY) { + if (SELWIDTH > 0) { + len -= ui_delete_selection_edittext(but); + + if (len < 0) len = 0; + dodraw=1; + } + else if(get_qual() & LR_SHIFTKEY) { str[0]= 0; but->pos= 0; len= 0; @@ -1613,6 +1805,7 @@ static int ui_do_but_TEX(uiBut *but) } } break; + case TABKEY: if(but->autocomplete_func) { but->autocomplete_func(str, but->autofunc_arg); @@ -5448,7 +5641,7 @@ short pupmenu(char *instr) } } - uiBoundsBlock(block, 2); + uiBoundsBlock(block, 1); event= uiDoBlocks(&listb, 0); @@ -5596,7 +5789,7 @@ short pupmenu_col(char *instr, int maxrow) //uiDefButI(block, BUTM, B_NOP, md->items[a].str, x1, y1, (short)(width-(rows>1)), (short)(boxh-1), &val, (float)md->items[a].retval, 0.0, 0, 0, ""); } - uiBoundsBlock(block, 3); + uiBoundsBlock(block, 1); event= uiDoBlocks(&listb, 0); diff --git a/source/blender/src/interface_draw.c b/source/blender/src/interface_draw.c index 966d402a009..e0e09e36aac 100644 --- a/source/blender/src/interface_draw.c +++ b/source/blender/src/interface_draw.c @@ -1452,6 +1452,8 @@ static void ui_draw_text_icon(uiBut *but) float x; int len; char *cpoin; + short t, pos, ch; + short selsta_tmp, selend_tmp, selsta_draw, selwidth_draw; /* check for button text label */ if (but->type == ICONTEXTROW) { @@ -1459,25 +1461,53 @@ static void ui_draw_text_icon(uiBut *but) } else { - // text button cursor + /* text button selection and cursor */ if(but->pos != -1) { - short t, pos, ch; - - pos= but->pos+strlen(but->str); - if(pos >= but->ofs) { - if(but->drawstr[0]!=0) { - ch= but->drawstr[pos]; - but->drawstr[pos]= 0; - t= but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3; - - but->drawstr[pos]= ch; + if (SELWIDTH > 0) { + /* text button selection */ + selsta_tmp = but->selsta + strlen(but->str); + selend_tmp = but->selend + strlen(but->str); + if (but->ofs >= strlen(but->str)) + selsta_tmp += (but->ofs - strlen(but->str)); + + if(but->drawstr[0]!=0) { + ch= but->drawstr[selsta_tmp]; + but->drawstr[selsta_tmp]= 0; + + selsta_draw = but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3; + + but->drawstr[selsta_tmp]= ch; + + + ch= but->drawstr[selend_tmp]; + but->drawstr[selend_tmp]= 0; + + selwidth_draw = but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3; + + but->drawstr[selend_tmp]= ch; + + BIF_ThemeColor(TH_BUT_TEXTFIELD_HI); + glRects(but->x1+selsta_draw+1, but->y1+2, but->x1+selwidth_draw+1, but->y2-2); } - else t= 3; - - glColor3ub(255,0,0); - glRects(but->x1+t, but->y1+2, but->x1+t+3, but->y2-2); - } + } else { + /* text cursor */ + pos= but->pos+strlen(but->str); + if(pos >= but->ofs) { + if(but->drawstr[0]!=0) { + ch= but->drawstr[pos]; + but->drawstr[pos]= 0; + + t= but->aspect*BIF_GetStringWidth(but->font, but->drawstr+but->ofs, (U.transopts & USER_TR_BUTTONS)) + 3; + + but->drawstr[pos]= ch; + } + else t= 3; + + glColor3ub(255,0,0); + glRects(but->x1+t, but->y1+2, but->x1+t+2, but->y2-2); + } + } } if(but->drawstr[0]!=0) { int transopts; diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index 6075b5e1d59..078bcec2aaa 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -674,6 +674,8 @@ char *BIF_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) cp= btheme->tui.num; break; case TH_BUT_TEXTFIELD: cp= btheme->tui.textfield; break; + case TH_BUT_TEXTFIELD_HI: + cp= btheme->tui.textfield_hi; break; case TH_BUT_POPUP: cp= btheme->tui.popup; break; case TH_BUT_TEXT: @@ -872,6 +874,7 @@ void BIF_InitTheme(void) SETCOL(btheme->tui.setting2, 0xA1,0x99,0xA7, 255); SETCOL(btheme->tui.num, 0x90,0x90,0x90, 255); SETCOL(btheme->tui.textfield, 0x90,0x90,0x90, 255); + SETCOL(btheme->tui.textfield_hi,0xc6,0x77,0x77, 255); SETCOL(btheme->tui.popup, 0xA0,0xA0,0xA0, 255); SETCOL(btheme->tui.text, 0,0,0, 255); @@ -1038,6 +1041,7 @@ char *BIF_ThemeColorsPup(int spacetype) sprintf(str, "Special Setting 2 %%x%d|", TH_BUT_SETTING2); strcat(cp, str); sprintf(str, "Number Input %%x%d|", TH_BUT_NUM); strcat(cp, str); sprintf(str, "Text Input %%x%d|", TH_BUT_TEXTFIELD); strcat(cp, str); + sprintf(str, "Text Input Highlight %%x%d|", TH_BUT_TEXTFIELD_HI); strcat(cp, str); sprintf(str, "Popup %%x%d|", TH_BUT_POPUP); strcat(cp, str); sprintf(str, "Text %%x%d|", TH_BUT_TEXT); strcat(cp, str); sprintf(str, "Text Highlight %%x%d|", TH_BUT_TEXT_HI); strcat(cp, str); diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 83f7b0b4554..25b46b064a9 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -259,7 +259,17 @@ static void init_userdef_file(void) /* TEMPORAL, remove me! (ton) */ U.uiflag |= USER_PLAINMENUS; } + + /* check for text field selection highlight, set it to text editor highlight by default */ + if(btheme->tui.textfield_hi[3]==0) { + SETCOL(btheme->tui.textfield_hi, + btheme->text.shade2[0], + btheme->text.shade2[1], + btheme->text.shade2[2], + 255); + } } + if(U.obcenter_dia==0) U.obcenter_dia= 6; } |