Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Thompson <quornian@googlemail.com>2008-06-25 17:51:54 +0400
committerIan Thompson <quornian@googlemail.com>2008-06-25 17:51:54 +0400
commite68834c75bc3e69641a6332dab071ebaa2d9d1d3 (patch)
tree38deda31d860f518dde5d52ac58cd667061cf422 /source/blender
parentbdc030c664640db727ea21a1e854bb62032bf705 (diff)
Added UI for suggestions list. Works with arrow-keys and mouse wheel, accept with Enter, reject with Esc or click elsewhere. Mouse selection not yet supported. The script is called from the File->Text Plugins menu.
Tidied python script, the C suggestions functions and fixed some bugs including suggestions not being freed properly.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_suggestions.h14
-rw-r--r--source/blender/blenkernel/intern/suggestions.c32
-rw-r--r--source/blender/python/api2_2x/Text.c14
-rw-r--r--source/blender/src/drawtext.c200
4 files changed, 227 insertions, 33 deletions
diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h
index bc4e18f5a67..d0f982263c0 100644
--- a/source/blender/blenkernel/BKE_suggestions.h
+++ b/source/blender/blenkernel/BKE_suggestions.h
@@ -57,18 +57,22 @@ typedef struct SuggItem {
typedef struct SuggList {
SuggItem *first, *last;
SuggItem *firstmatch, *lastmatch;
+ SuggItem *selected;
} SuggList;
void free_suggestions();
-void add_suggestion(const char *name, char type);
-void update_suggestions(const char *prefix);
+void suggest_add(const char *name, char type);
+void suggest_prefix(const char *prefix);
SuggItem *suggest_first();
SuggItem *suggest_last();
-void set_suggest_text(Text *text);
-void clear_suggest_text();
-short is_suggest_active(Text *text);
+void suggest_set_text(Text *text);
+void suggest_clear_text();
+short suggest_is_active(Text *text);
+
+void suggest_set_selected(SuggItem *sel);
+SuggItem *suggest_get_selected();
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c
index 3842146376d..ae0c7baa146 100644
--- a/source/blender/blenkernel/intern/suggestions.c
+++ b/source/blender/blenkernel/intern/suggestions.c
@@ -40,14 +40,17 @@ static SuggList suggestions= {NULL, NULL, NULL, NULL};
static Text *suggText = NULL;
void free_suggestions() {
- SuggItem *item;
- for (item = suggestions.last; item; item=item->prev)
+ SuggItem *item, *prev;
+ for (item = suggestions.last; item; item=prev) {
+ prev = item->prev;
MEM_freeN(item);
+ }
suggestions.first = suggestions.last = NULL;
suggestions.firstmatch = suggestions.lastmatch = NULL;
+ suggestions.selected = NULL;
}
-void add_suggestion(const char *name, char type) {
+void suggest_add(const char *name, char type) {
SuggItem *newitem;
newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem");
@@ -63,6 +66,7 @@ void add_suggestion(const char *name, char type) {
if (!suggestions.first) {
suggestions.first = suggestions.last = newitem;
+ suggestions.selected = newitem;
} else {
newitem->prev = suggestions.last;
suggestions.last->next = newitem;
@@ -70,13 +74,13 @@ void add_suggestion(const char *name, char type) {
}
}
-void update_suggestions(const char *prefix) {
+void suggest_prefix(const char *prefix) {
SuggItem *match, *first, *last;
int cmp, len = strlen(prefix);
if (!suggestions.first) return;
if (len==0) {
- suggestions.firstmatch = suggestions.first;
+ suggestions.selected = suggestions.firstmatch = suggestions.first;
suggestions.lastmatch = suggestions.last;
return;
}
@@ -96,10 +100,10 @@ void update_suggestions(const char *prefix) {
}
if (first) {
if (!last) last = suggestions.last;
- suggestions.firstmatch = first;
+ suggestions.selected = suggestions.firstmatch = first;
suggestions.lastmatch = last;
} else {
- suggestions.firstmatch = suggestions.lastmatch = NULL;
+ suggestions.selected = suggestions.firstmatch = suggestions.lastmatch = NULL;
}
}
@@ -111,15 +115,23 @@ SuggItem *suggest_last() {
return suggestions.lastmatch;
}
-void set_suggest_text(Text *text) {
+void suggest_set_text(Text *text) {
suggText = text;
}
-void clear_suggest_text() {
+void suggest_clear_text() {
free_suggestions();
suggText = NULL;
}
-short is_suggest_active(Text *text) {
+short suggest_is_active(Text *text) {
return suggText==text ? 1 : 0;
}
+
+void suggest_set_selected(SuggItem *sel) {
+ suggestions.selected = sel;
+}
+
+SuggItem *suggest_get_selected() {
+ return suggestions.selected;
+}
diff --git a/source/blender/python/api2_2x/Text.c b/source/blender/python/api2_2x/Text.c
index 63c77c0bb3e..0c612a95f3a 100644
--- a/source/blender/python/api2_2x/Text.c
+++ b/source/blender/python/api2_2x/Text.c
@@ -129,7 +129,7 @@ static PyMethodDef BPy_Text_methods[] = {
{"setCursorPos", ( PyCFunction ) Text_setCursorPos, METH_VARARGS,
"(row, col) - Set the cursor position to (row, col)"},
{"suggest", ( PyCFunction ) Text_suggest, METH_VARARGS,
- "(list) - List of tuples of the form (name, type) where type is one of 'm', 'v', 'f' for module, variable and function respectively"},
+ "(list) - List of tuples of the form (name, type) where type is one of 'm', 'v', 'f', 'k' for module, variable, function and keyword respectively"},
{NULL, NULL, 0, NULL}
};
@@ -544,7 +544,7 @@ static PyObject *Text_suggest( BPy_Text * self, PyObject * args )
"Active text area has no Text object");
list_len = PyList_Size(list);
- clear_suggest_text();
+ suggest_clear_text();
for (i = 0; i < list_len; i++) {
item = PyList_GetItem(list, i);
@@ -555,14 +555,14 @@ static PyObject *Text_suggest( BPy_Text * self, PyObject * args )
name = PyString_AsString(PyTuple_GetItem(item, 0));
type = PyString_AsString(PyTuple_GetItem(item, 1))[0];
- if (!strlen(name) || (type!='m' && type!='v' && type!='f'))
+ if (!strlen(name) || (type!='m' && type!='v' && type!='f' && type!='k'))
return EXPP_ReturnPyObjError(PyExc_AttributeError,
- "layer values must be in the range [1, 20]" );
+ "names must be non-empty and types in ['m', 'v', 'f', 'k']" );
- add_suggestion(name, type);
+ suggest_add(name, type);
}
- update_suggestions(prefix);
- set_suggest_text(st->text);
+ suggest_prefix(prefix);
+ suggest_set_text(st->text);
scrarea_queue_redraw(curarea);
Py_RETURN_NONE;
diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c
index 227d1f08c20..5cececa40a7 100644
--- a/source/blender/src/drawtext.c
+++ b/source/blender/src/drawtext.c
@@ -99,6 +99,10 @@ static int check_delim(char *string);
static int check_numbers(char *string);
static int check_builtinfuncs(char *string);
static int check_specialvars(char *string);
+static int check_identifier(char ch);
+
+static void get_suggest_prefix(Text *text);
+static void confirm_suggestion(Text *text);
static void *last_txt_find_string= NULL;
@@ -1000,16 +1004,63 @@ static void do_selection(SpaceText *st, int selecting)
txt_undo_add_toop(st->text, UNDO_STO, sell, selc, linep2, charp2);
}
+#define SUGG_LIST_SIZE 7
+#define SUGG_LIST_WIDTH 20
+
void draw_suggestion_list(SpaceText *st) {
- SuggItem *item, *last;
+ SuggItem *item, *first, *last, *sel;
+ TextLine *tmp;
+ char str[SUGG_LIST_WIDTH+1];
+ int w, boxw=0, boxh, i, l, x, y, b;
- if (!is_suggest_active(st->text)) return;
+ if (!st || !st->text) return;
+ if (!suggest_is_active(st->text)) return;
- for (item=suggest_first(), last=suggest_last(); item; item=item->next) {
- /* Useful for testing but soon to be replaced by UI list */
- printf("Suggest: %c %s\n", item->type, item->name);
- if (item == last)
- break;
+ first = suggest_first();
+ last = suggest_last();
+ sel = suggest_get_selected();
+ //if (!first || !last || !sel) return;
+
+ for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++);
+ boxw = SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 20;
+ boxh = SUGG_LIST_SIZE*st->lheight + 8;
+ x = spacetext_get_fontwidth(st)*st->text->curc + 50; // TODO: Replace + 50
+ y = curarea->winy - st->lheight*l - 2;
+
+ BIF_ThemeColor(TH_SHADE1);
+ glRecti(x-1, y+1, x+boxw+1, y-boxh-1);
+ BIF_ThemeColor(TH_BACK);
+ glRecti(x, y, x+boxw, y-boxh);
+
+ for (i=0, item=sel; i<3 && item && item!=first; i++, item=item->prev);
+
+ for (i=0; i<SUGG_LIST_SIZE && item; i++, item=item->next) {
+
+ y -= st->lheight;
+
+ strncpy(str, item->name, SUGG_LIST_WIDTH);
+ str[SUGG_LIST_WIDTH] = '\0';
+
+ w = BMF_GetStringWidth(spacetext_get_font(st), str);
+
+ if (item == sel) {
+ BIF_ThemeColor(TH_SHADE2);
+ glRecti(x+16, y-3, x+16+w, y+st->lheight-3);
+ }
+ b=1; /* b=1 colour block, text is default. b=0 no block, colour text */
+ switch (item->type) {
+ case 'k': BIF_ThemeColor(TH_SYNTAX_B); b=0; break;
+ case 'm': BIF_ThemeColor(TH_TEXT); break;
+ case 'f': BIF_ThemeColor(TH_SYNTAX_L); break;
+ case 'v': BIF_ThemeColor(TH_SYNTAX_N); break;
+ }
+ if (b) {
+ glRecti(x+8, y+2, x+11, y+5);
+ BIF_ThemeColor(TH_TEXT);
+ }
+ text_draw(st, str, 0, 0, 1, x+16, y-1, NULL);
+
+ if (item == last) break;
}
}
@@ -1484,6 +1535,48 @@ static void set_tabs(Text *text)
st->currtab_set = setcurr_tab(text);
}
+static void get_suggest_prefix(Text *text) {
+ int i, len;
+ char *line, tmp[256];
+
+ if (!text) return;
+ if (!suggest_is_active(text)) return;
+
+ line= text->curl->line;
+ for (i=text->curc-1; i>=0; i--)
+ if (!check_identifier(line[i]))
+ break;
+ i++;
+ len= text->curc-i;
+ if (len > 255) {
+ printf("Suggestion prefix too long\n");
+ return;
+ }
+ strncpy(tmp, line+i, len);
+ tmp[len]= '\0';
+ suggest_prefix(tmp);
+}
+
+static void confirm_suggestion(Text *text) {
+ int i, len;
+ char *line;
+ SuggItem *sel;
+
+ if (!text) return;
+ if (!suggest_is_active(text)) return;
+
+ sel = suggest_get_selected();
+ if (!sel) return;
+
+ line= text->curl->line;
+ for (i=text->curc-1; i>=0; i--)
+ if (!check_identifier(line[i]))
+ break;
+ i++;
+ len= text->curc-i;
+ txt_insert_buf(text, sel->name+len);
+}
+
void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
{
unsigned short event= evt->event;
@@ -1492,6 +1585,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
SpaceText *st= curarea->spacedata.first;
Text *text;
int do_draw=0, p;
+ int suggesting=0, do_suggest=0; /* 0:just redraw, -1:clear, 1:update prefix */
if (st==NULL || st->spacetype != SPACE_TEXT) return;
@@ -1554,6 +1648,8 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
return;
}
+
+ suggesting = suggest_is_active(text);
if (event==LEFTMOUSE) {
if (val) {
@@ -1573,6 +1669,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
do_draw= 1;
}
+ do_suggest= -1;
}
} else if (event==MIDDLEMOUSE) {
if (val) {
@@ -1586,6 +1683,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
{
do_textscroll(st, 1);
}
+ do_suggest= -1;
}
} else if (event==RIGHTMOUSE) {
if (val) {
@@ -1618,6 +1716,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
default:
break;
}
+ do_suggest= -1;
}
} else if (ascii) {
if (text && text->id.lib) {
@@ -1627,8 +1726,10 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if (st->showsyntax) get_format_string(st);
pop_space_text(st);
do_draw= 1;
+ do_suggest= 1;
}
} else if (val) {
+ do_suggest= -1;
switch (event) {
case AKEY:
if (G.qual & LR_ALTKEY) {
@@ -1891,6 +1992,9 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
do_draw= 1;
}
break;
+ case ESCKEY:
+ do_suggest= -1;
+ break;
case TABKEY:
if (text && text->id.lib) {
error_libdata();
@@ -1920,6 +2024,11 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
error_libdata();
break;
}
+ if (suggesting) {
+ confirm_suggestion(text);
+ if (st->showsyntax) get_format_string(st);
+ break;
+ }
//double check tabs before splitting the line
st->currtab_set = setcurr_tab(text);
txt_split_curline(text);
@@ -1951,6 +2060,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if (st->showsyntax) get_format_string(st);
do_draw= 1;
pop_space_text(st);
+ do_suggest= 1;
break;
case DELKEY:
if (text && text->id.lib) {
@@ -1970,8 +2080,16 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case INSERTKEY:
st->overwrite= !st->overwrite;
do_draw= 1;
+ do_suggest= 0;
break;
case DOWNARROWKEY:
+ if (suggesting) {
+ SuggItem *sel = suggest_get_selected();
+ if (sel && sel!=suggest_last() && sel->next)
+ suggest_set_selected(sel->next);
+ do_suggest= 0;
+ break;
+ }
txt_move_down(text, G.qual & LR_SHIFTKEY);
set_tabs(text);
do_draw= 1;
@@ -2000,17 +2118,42 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
pop_space_text(st);
break;
case UPARROWKEY:
+ if (suggesting) {
+ SuggItem *sel = suggest_get_selected();
+ if (sel && sel!=suggest_first() && sel->prev)
+ suggest_set_selected(sel->prev);
+ do_suggest= 0;
+ break;
+ }
txt_move_up(text, G.qual & LR_SHIFTKEY);
set_tabs(text);
do_draw= 1;
pop_space_text(st);
break;
case PAGEDOWNKEY:
- screen_skip(st, st->viewlines);
+ if (suggesting) {
+ int i;
+ SuggItem *sel = suggest_get_selected();
+ for (i=0; i<SUGG_LIST_SIZE-1 && sel && sel!=suggest_last() && sel->next; i++, sel=sel->next)
+ suggest_set_selected(sel->next);
+ do_suggest= 0;
+ break;
+ } else {
+ screen_skip(st, st->viewlines);
+ }
do_draw= 1;
break;
case PAGEUPKEY:
- screen_skip(st, -st->viewlines);
+ if (suggesting) {
+ int i;
+ SuggItem *sel = suggest_get_selected();
+ for (i=0; i<SUGG_LIST_SIZE-1 && sel && sel!=suggest_first() && sel->prev; i++, sel=sel->prev)
+ suggest_set_selected(sel->prev);
+ do_suggest= 0;
+ break;
+ } else {
+ screen_skip(st, -st->viewlines);
+ }
do_draw= 1;
break;
case HOMEKEY:
@@ -2024,14 +2167,39 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
pop_space_text(st);
break;
case WHEELUPMOUSE:
- screen_skip(st, -U.wheellinescroll);
+ if (suggesting) {
+ SuggItem *sel = suggest_get_selected();
+ if (sel && sel!=suggest_first() && sel->prev)
+ suggest_set_selected(sel->prev);
+ do_suggest= 0;
+ } else {
+ screen_skip(st, -U.wheellinescroll);
+ }
do_draw= 1;
break;
case WHEELDOWNMOUSE:
- screen_skip(st, U.wheellinescroll);
+ if (suggesting) {
+ SuggItem *sel = suggest_get_selected();
+ if (sel && sel!=suggest_last() && sel->next)
+ suggest_set_selected(sel->next);
+ do_suggest= 0;
+ } else {
+ screen_skip(st, U.wheellinescroll);
+ }
do_draw= 1;
break;
+ default:
+ do_suggest= 0;
+ }
+ }
+
+ if (suggesting) {
+ if (do_suggest == -1) {
+ suggest_clear_text();
+ } else if (do_suggest == 1) {
+ get_suggest_prefix(text);
}
+ do_draw= 1;
}
if (do_draw) {
@@ -2223,6 +2391,16 @@ static int check_numbers(char *string)
return 0;
}
+static int check_identifier(char ch) {
+ if (ch < '0') return 0;
+ if (ch <= '9') return 1;
+ if (ch < 'A') return 0;
+ if (ch <= 'Z' || ch == '_') return 1;
+ if (ch < 'a') return 0;
+ if (ch <= 'z') return 1;
+ return 0;
+}
+
void convert_tabs (struct SpaceText *st, int tab)
{
Text *text = st->text;