From 6c0f4660ed60ea8dd46519e3367ee5c0efdcf4f8 Mon Sep 17 00:00:00 2001 From: Ian Thompson Date: Wed, 6 Aug 2008 13:46:44 +0000 Subject: [PATCH] Various UI drawing and event tweaks to make markers feel more natural and avoid getting in the way. If there is a marker under the cursor, ESC will remove it and others in its group. Otherwise all temporary markers are removed. Tab finds/cycles/removes temp. markers, cycles non-temp. markers (under cursor) and behaves normally in all other cases. --- release/scripts/textplugin_templates.py | 5 +- source/blender/blenkernel/BKE_text.h | 2 + source/blender/blenkernel/intern/text.c | 76 +++++++++++++++++++------ source/blender/src/drawtext.c | 59 +++++++++++++------ 4 files changed, 105 insertions(+), 37 deletions(-) diff --git a/release/scripts/textplugin_templates.py b/release/scripts/textplugin_templates.py index e0e7746abca..0cd772f863e 100644 --- a/release/scripts/textplugin_templates.py +++ b/release/scripts/textplugin_templates.py @@ -48,9 +48,10 @@ def main(): if not txt: return - line, c = current_line(txt) + row, c = txt.getCursorPos() + line = txt.asLines()[row] indent=0 - while indenttop determines at what line the top of the text is displayed. If the user moves the cursor the st containing that cursor should be popped ... other st's retain their own top location. -*/ /***************/ +Markers +-- +The mrk->flags define the behaviour and relationships between markers. The +upper two bytes are used to hold a group ID, the lower two are normal flags. If +TMARK_EDITALL is set the group ID defines which other markers should be edited. +The mrk->clr field is used to visually group markers where the flags may not +match. A template system, for example, may allow editing of repeating tokens +(in one group) but include other marked positions (in another group) all in the +same template with the same colour. -/****************/ /* - Undo - +Undo +-- Undo/Redo works by storing events in a queue, and a pointer to the current position in the @@ -2657,6 +2664,13 @@ int setcurr_tab (Text *text) /* Text marker utility functions */ /*********************************/ +static int color_match(TextMarker *a, TextMarker *b) { + return (a->clr[0]==b->clr[0] && + a->clr[1]==b->clr[1] && + a->clr[2]==b->clr[2] && + a->clr[3]==b->clr[3]); +} + /* Creates and adds a marker to the list maintaining sorted order */ void txt_add_marker(Text *text, TextLine *line, int start, int end, char clr[4], int flags) { TextMarker *tmp, *marker; @@ -2681,8 +2695,9 @@ void txt_add_marker(Text *text, TextLine *line, int start, int end, char clr[4], else BLI_addhead(&text->markers, marker); } -/* Returns the first matching marker on the specified line between two points - If flags is zero, all markers will be searched */ +/* Returns the first matching marker on the specified line between two points, + with at least the specified flags set. If flags is zero, all markers will be + searched */ TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int flags) { TextMarker *marker, *next; int lineno= txt_get_span(text->lines.first, line); @@ -2690,7 +2705,7 @@ TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int en for (marker=text->markers.first; marker; marker=next) { next= marker->next; - if (flags && marker->flags != flags) continue; + if ((marker->flags & flags) != flags) continue; else if (marker->lineno < lineno) continue; else if (marker->lineno > lineno) break; @@ -2701,8 +2716,8 @@ TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int en return NULL; } -/* Clears all matching markers on the specified line between two points - If flags is zero, all markers will be cleared */ +/* Clears all markers on the specified line between two points with at least + the specified flags set. If flags is zero, all markers will be cleared */ void txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int flags) { TextMarker *marker, *next; int lineno= txt_get_span(text->lines.first, line); @@ -2710,7 +2725,7 @@ void txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int for (marker=text->markers.first; marker; marker=next) { next= marker->next; - if (flags && marker->flags != flags) continue; + if ((marker->flags & flags) != flags) continue; else if (marker->lineno < lineno) continue; else if (marker->lineno > lineno) break; @@ -2720,26 +2735,27 @@ void txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int } } -/* Clears all markers with matching flags (useful for clearing temporary markers) */ +/* Clears all markers with at least the specified flags set (useful for + clearing temporary markers) */ void txt_clear_markers(Text *text, int flags) { TextMarker *marker, *next; for (marker=text->markers.first; marker; marker=next) { next= marker->next; - if (marker->flags == flags) + if ((marker->flags & flags) == flags) BLI_freelinkN(&text->markers, marker); } } -/* Finds the marker at the specified line and cursor position with matching flags. - If flags is zero, all markers will be searched */ +/* Finds the marker at the specified line and cursor position with at least the + specified flags set. If flags is zero, all markers will be searched */ TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int flags) { TextMarker *marker; int lineno= txt_get_span(text->lines.first, line); for (marker=text->markers.first; marker; marker=marker->next) { - if (flags && marker->flags != flags) continue; + if ((marker->flags & flags) != flags) continue; else if (marker->lineno < lineno) continue; else if (marker->lineno > lineno) break; @@ -2749,8 +2765,8 @@ TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int flags) { return NULL; } -/* Finds the previous marker with matching flags. If no other marker is found, the - same one will be returned */ +/* Finds the previous marker with matching flags. If no other marker is found, + the same one will be returned */ TextMarker *txt_prev_marker(Text *text, TextMarker *marker) { TextMarker *tmp= marker; while (tmp) { @@ -2774,3 +2790,29 @@ TextMarker *txt_next_marker(Text *text, TextMarker *marker) { } return NULL; /* Only if marker==NULL */ } + +/* Finds the previous marker with matching colour. If no other marker is found, + the same one will be returned */ +TextMarker *txt_prev_marker_color(Text *text, TextMarker *marker) { + TextMarker *tmp= marker; + while (tmp) { + if (tmp->prev) tmp= tmp->prev; + else tmp= text->markers.last; + if (color_match(tmp, marker)) + return tmp; + } + return NULL; /* Only if marker==NULL */ +} + +/* Finds the next marker with matching colour. If no other marker is found, the + same one will be returned */ +TextMarker *txt_next_marker_color(Text *text, TextMarker *marker) { + TextMarker *tmp= marker; + while (tmp) { + if (tmp->next) tmp= tmp->next; + else tmp= text->markers.first; + if (color_match(tmp, marker)) + return tmp; + } + return NULL; /* Only if marker==NULL */ +} diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 5a96a2548d7..78ccbbfc1b6 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -878,9 +878,9 @@ static void draw_cursor(SpaceText *st) { if (vcurl==vsell) { y -= vcurl*st->lheight; if (vcurc < vselc) - glRecti(x+vcurc*spacetext_get_fontwidth(st), y, x+vselc*spacetext_get_fontwidth(st), y-st->lheight); + glRecti(x+vcurc*spacetext_get_fontwidth(st)-1, y, x+vselc*spacetext_get_fontwidth(st), y-st->lheight); else - glRecti(x+vselc*spacetext_get_fontwidth(st), y, x+vcurc*spacetext_get_fontwidth(st), y-st->lheight); + glRecti(x+vselc*spacetext_get_fontwidth(st)-1, y, x+vcurc*spacetext_get_fontwidth(st), y-st->lheight); } else { int froml, fromc, tol, toc; if (vcurl < vsell) { @@ -891,7 +891,7 @@ static void draw_cursor(SpaceText *st) { fromc= vselc; toc= vcurc; } y -= froml*st->lheight; - glRecti(x+fromc*spacetext_get_fontwidth(st), y, curarea->winx, y-st->lheight); y-=st->lheight; + glRecti(x+fromc*spacetext_get_fontwidth(st)-1, y, curarea->winx, y-st->lheight); y-=st->lheight; for (i=froml+1; iwinx, y-st->lheight), y-=st->lheight; glRecti(x-4, y, x+toc*spacetext_get_fontwidth(st), y-st->lheight); y-=st->lheight; @@ -1446,6 +1446,7 @@ void drawtextspace(ScrArea *sa, void *spacedata) tmp= text->lines.first; for (i= 0; itop && tmp; i++) { + if (st->showsyntax && !tmp->format) txt_format_line(st, tmp, 0); tmp= tmp->next; linecount++; } @@ -1504,7 +1505,7 @@ void pop_space_text (SpaceText *st) if(!st->text) return; if(!st->text->curl) return; - i= txt_get_span(st->text->lines.first, st->text->curl); + i= txt_get_span(st->text->lines.first, st->text->sell); if (st->top+st->viewlines <= i || st->top > i) { st->top= i - st->viewlines/2; } @@ -1512,7 +1513,7 @@ void pop_space_text (SpaceText *st) if (st->wordwrap) { st->left= 0; } else { - x= text_draw(st, st->text->curl->line, st->left, st->text->curc, 0, 0, 0, NULL); + x= text_draw(st, st->text->sell->line, st->left, st->text->selc, 0, 0, 0, NULL); if (x==0 || x>curarea->winx) { st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st); @@ -1962,7 +1963,7 @@ void txt_find_panel(SpaceText *st, int again, int flags) int first= 1; do { if (first && (flags & TXT_FIND_MARKALL)) - txt_clear_markers(text, TMARK_EDITALL | TMARK_GRP_FINDALL); + txt_clear_markers(text, TMARK_GRP_FINDALL); first= 0; /* Replace current */ @@ -1975,11 +1976,11 @@ void txt_find_panel(SpaceText *st, int again, int flags) } else { char clr[4]; BIF_GetThemeColor4ubv(TH_SHADE2, clr); - if (txt_find_marker(text, text->curl, text->selc, TMARK_EDITALL | TMARK_GRP_FINDALL)) { + if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL)) { if (tmp) MEM_freeN(tmp), tmp=NULL; break; } - txt_add_marker(text, text->curl, text->curc, text->selc, clr, TMARK_EDITALL | TMARK_GRP_FINDALL); + txt_add_marker(text, text->curl, text->curc, text->selc, clr, TMARK_GRP_FINDALL | TMARK_EDITALL); } } MEM_freeN(tmp); @@ -2256,10 +2257,33 @@ static short do_markers(SpaceText *st, char ascii, unsigned short evnt, short va int c, s, draw=0, swallow=0; text= st->text; - if (!text || text->curl != text->sell) return 0; + if (!text || text->id.lib || text->curl != text->sell) return 0; marker= txt_find_marker(text, text->curl, text->curc, 0); - if (!marker || text->id.lib) return 0; + if (!marker) { + /* Find the next temporary marker */ + if (evnt==TABKEY) { + int lineno= txt_get_span(text->lines.first, text->curl); + TextMarker *mrk= text->markers.first; + while (mrk) { + if (!marker && (mrk->flags & TMARK_TEMP)) marker= mrk; + if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno==lineno && mrk->end > text->curc))) { + marker= mrk; + break; + } + mrk= mrk->next; + } + if (marker) { + txt_move_to(text, marker->lineno, marker->start, 0); + txt_move_to(text, marker->lineno, marker->end, 1); + pop_space_text(st); + evnt= ascii= val= 0; + draw= 1; + swallow= 1; + } + } + if (!swallow) return 0; + } if (ascii) { if (marker->flags & TMARK_EDITALL) { @@ -2351,6 +2375,8 @@ static short do_markers(SpaceText *st, char ascii, unsigned short evnt, short va break; /* Events that should clear markers */ + case UKEY: if (!(G.qual & LR_ALTKEY)) break; + case ZKEY: if (evnt==ZKEY && !(G.qual & LR_CTRLKEY)) break; case RETKEY: case ESCKEY: if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) @@ -2809,14 +2835,8 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (st->showsyntax) txt_format_text(st); } } else { - TextMarker *mrk= txt_find_marker_region(text, text->curl, 0, text->curl->len, 0); - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } else { - txt_add_char(text, '\t'); - if (st->showsyntax) txt_format_line(st, text->curl, 1); - } + txt_add_char(text, '\t'); + if (st->showsyntax) txt_format_line(st, text->curl, 1); } } pop_space_text(st); @@ -2848,6 +2868,9 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) do_draw= 1; pop_space_text(st); break; + case ESCKEY: + txt_clear_markers(text, TMARK_TEMP); + break; case BACKSPACEKEY: if (text && text->id.lib) { error_libdata();