Patch [#23443] Change outliner filter into search
authorJoshua Leung <aligorith@gmail.com>
Fri, 9 Sep 2011 12:46:07 +0000 (12:46 +0000)
committerJoshua Leung <aligorith@gmail.com>
Fri, 9 Sep 2011 12:46:07 +0000 (12:46 +0000)
Shane Ambler (sambler) for this 12-month vintage!

From description:
One thing with the outliner filter box is it only filters items that
are currently visible. To find what you want you need to manually
expand a few levels so that what you want to find is visible.

This small patch expands items when filtering is done - effectively
turning it into a search.

Currently this does not alter the datablocks view as expanding all
entries takes waaaay tooooo long.
I prevent the expansion of RNA entries for userprefs which prevents
infinite recursion but the datablocks list is just too big for this
approach. I think it would need a custom outliner_build_tree for a
full search.

source/blender/editors/space_outliner/outliner_draw.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/outliner_intern.h
source/blender/editors/space_outliner/outliner_select.c
source/blender/editors/space_outliner/outliner_tools.c
source/blender/editors/space_outliner/outliner_tree.c
source/blender/makesdna/DNA_outliner_types.h
source/blender/makesdna/DNA_space_types.h

index 95a315272b97b0155624a17e18639505418e90db..e77bb979d47b1654c7ed5fe516cabeedc69e31a7 100644 (file)
@@ -97,7 +97,7 @@ static void outliner_height(SpaceOops *soops, ListBase *lb, int *h)
        TreeElement *te= lb->first;
        while(te) {
                TreeStoreElem *tselem= TREESTORE(te);
-               if((tselem->flag & TSE_CLOSED)==0) 
+               if(TSELEM_OPEN(tselem,soops))
                        outliner_height(soops, &te->subtree, h);
                (*h) += UI_UNIT_Y;
                te= te->next;
@@ -112,7 +112,7 @@ static void outliner_width(SpaceOops *soops, ListBase *lb, int *w)
 //             TreeStoreElem *tselem= TREESTORE(te);
                
                // XXX fixme... te->xend is not set yet
-               if(tselem->flag & TSE_CLOSED) {
+               if(!TSELEM_OPEN(tselem,soops)) {
                        if (te->xend > *w)
                                *w = te->xend;
                }
@@ -135,7 +135,7 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start
                if(startx+100 > *w)
                        *w = startx+100;
 
-               if((tselem->flag & TSE_CLOSED)==0)
+               if(TSELEM_OPEN(tselem,soops))
                        outliner_rna_width(soops, &te->subtree, w, startx+UI_UNIT_X);
                te= te->next;
        }
@@ -519,7 +519,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
                        }
                }
                
-               if((tselem->flag & TSE_CLOSED)==0) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
+               if(TSELEM_OPEN(tselem,soops)) outliner_draw_restrictbuts(block, scene, ar, soops, &te->subtree);
        }
 }
 
@@ -560,7 +560,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
                                ptr= &te->rnaptr;
                                prop= te->directdata;
                                
-                               if(!(RNA_property_type(prop) == PROP_POINTER && (tselem->flag & TSE_CLOSED)==0))
+                               if(!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem,soops))) )
                                        uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y-1);
                        }
                        else if(tselem->type == TSE_RNA_ARRAY_ELEM) {
@@ -571,7 +571,7 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa
                        }
                }
                
-               if((tselem->flag & TSE_CLOSED)==0) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
+               if(TSELEM_OPEN(tselem,soops)) outliner_draw_rnabuts(block, scene, ar, soops, sizex, &te->subtree);
        }
 }
 
@@ -828,7 +828,7 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo
                        }
                }
                
-               if((tselem->flag & TSE_CLOSED)==0) outliner_draw_keymapbuts(block, ar, soops, &te->subtree);
+               if(TSELEM_OPEN(tselem,soops)) outliner_draw_keymapbuts(block, ar, soops, &te->subtree);
        }
 }
 
@@ -871,7 +871,7 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa
                        }
                }
                
-               if((tselem->flag & TSE_CLOSED)==0) outliner_buttons(C, block, ar, soops, &te->subtree);
+               if(TSELEM_OPEN(tselem,soops)) outliner_buttons(C, block, ar, soops, &te->subtree);
        }
 }
 
@@ -1237,6 +1237,18 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
                
                glEnable(GL_BLEND);
 
+               /* start by highlighting search matches 
+                *      we don't expand items when searching in the datablocks but we 
+                *      still want to highlight any filter matches. 
+                */
+               if ( (SEARCHING_OUTLINER(soops) || (soops->outlinevis==SO_DATABLOCKS && soops->search_string[0]!=0)) && 
+                        (tselem->flag & TSE_SEARCHMATCH)) 
+               {
+                       /* TODO - add search highlight colour to theme? */
+                       glColor4f(0.2f, 0.5f, 0.2f, 0.3f);
+                       glRecti(startx, *starty+1, ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1);
+               }
+
                /* colors for active/selected data */
                if(tselem->type==0) {
                        if(te->idcode==ID_SCE) {
@@ -1317,10 +1329,10 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
                                icon_x = startx+5*ufac;
                        
                                // icons a bit higher
-                       if(tselem->flag & TSE_CLOSED) 
-                               UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT);
-                       else
+                       if(TSELEM_OPEN(tselem,soops)) 
                                UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_DOWN);
+                       else
+                               UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT);
                }
                offsx+= UI_UNIT_X;
                
@@ -1356,7 +1368,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
                offsx+= (int)(UI_UNIT_X + UI_GetStringWidth(te->name));
                
                /* closed item, we draw the icons, not when it's a scene, or master-server list though */
-               if(tselem->flag & TSE_CLOSED) {
+               if(!TSELEM_OPEN(tselem,soops)) {
                        if(te->subtree.first) {
                                if(tselem->type==0 && te->idcode==ID_SCE);
                                else if(tselem->type!=TSE_R_LAYER) { /* this tree element always has same amount of branches, so dont draw */
@@ -1382,7 +1394,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene
        te->ys= (float)*starty;
        te->xend= startx+offsx;
                
-       if((tselem->flag & TSE_CLOSED)==0) {
+       if(TSELEM_OPEN(tselem,soops)) {
                *starty-= UI_UNIT_Y;
                
                for(ten= te->subtree.first; ten; ten= ten->next)
@@ -1415,7 +1427,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx,
                        
                *starty-= UI_UNIT_Y;
                
-               if((tselem->flag & TSE_CLOSED)==0)
+               if(TSELEM_OPEN(tselem,soops))
                        outliner_draw_hierarchy(soops, &te->subtree, startx+UI_UNIT_X, starty);
        }
        
@@ -1439,12 +1451,12 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
                tselem= TREESTORE(te);
                
                /* selection status */
-               if((tselem->flag & TSE_CLOSED)==0)
+               if(TSELEM_OPEN(tselem,soops))
                        if(tselem->type == TSE_RNA_STRUCT)
                                glRecti(0, *starty+1, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, *starty+UI_UNIT_Y-1);
 
                *starty-= UI_UNIT_Y;
-               if((tselem->flag & TSE_CLOSED)==0) {
+               if(TSELEM_OPEN(tselem,soops)) {
                        outliner_draw_struct_marks(ar, soops, &te->subtree, starty);
                        if(tselem->type == TSE_RNA_STRUCT)
                                fdrawline(0, (float)*starty+UI_UNIT_Y, ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, (float)*starty+UI_UNIT_Y);
@@ -1465,7 +1477,7 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb,
                        glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1);
                }
                *starty-= UI_UNIT_Y;
-               if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(ar, soops, &te->subtree, starty);
+               if(TSELEM_OPEN(tselem,soops)) outliner_draw_selection(ar, soops, &te->subtree, starty);
        }
 }
 
index 2b451a487489b26ec7fe024b10a0cb1e26b254de..05eace0d4efb53fc1051ff43d98cbf00869872bd 100644 (file)
@@ -687,7 +687,7 @@ static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te,
        te->ys= (float)(*starty);
        *starty-= UI_UNIT_Y;
        
-       if((tselem->flag & TSE_CLOSED)==0) {
+       if(TSELEM_OPEN(tselem,soops)) {
                TreeElement *ten;
                for(ten= te->subtree.first; ten; ten= ten->next) {
                        outliner_set_coordinates_element(soops, ten, startx+UI_UNIT_X, starty);
@@ -910,7 +910,7 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase
                }
                else tselem->flag |= TSE_CLOSED;
                
-               if(tselem->flag & TSE_CLOSED); else tree_element_show_hierarchy(scene, soops, &te->subtree);
+               if(TSELEM_OPEN(tselem,soops)) tree_element_show_hierarchy(scene, soops, &te->subtree);
        }
 }
 
@@ -1175,7 +1175,7 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportL
                }
                
                /* go over sub-tree */
-               if ((tselem->flag & TSE_CLOSED)==0)
+               if (TSELEM_OPEN(tselem,soops))
                        do_outliner_drivers_editop(soops, &te->subtree, reports, mode);
        }
 }
@@ -1343,7 +1343,7 @@ static void do_outliner_keyingset_editop(SpaceOops *soops, KeyingSet *ks, ListBa
                }
                
                /* go over sub-tree */
-               if ((tselem->flag & TSE_CLOSED)==0)
+               if (TSELEM_OPEN(tselem,soops))
                        do_outliner_keyingset_editop(soops, ks, &te->subtree, mode);
        }
 }
index 61507d1ffe588d47a7a5aebaedf493b99e9f0cbb..215ab508ab6aaddcd0b3f02d833bc00bcd4ad1ab 100644 (file)
@@ -126,6 +126,27 @@ typedef struct TreeElement {
 #define OL_RNA_COL_SPACEX      (UI_UNIT_X*2.5f)
 
 
+/* Outliner Searching --
+
+   Are we looking for something in the outliner?
+   If so finding matches in child items makes it more useful
+
+        - We want to flag parents to act as being open to filter child matches 
+        - and also flag matches so we can highlight them
+        - Flags are stored in TreeStoreElem->flag
+        - Flag options defined in DNA_outliner_types.h
+        - SO_SEARCH_RECURSIVE defined in DNA_space_types.h
+        
+        - NOT in datablocks view - searching all datablocks takes way too long 
+               to be useful
+        - not searching into RNA items helps but isn't the complete solution
+       */
+
+#define SEARCHING_OUTLINER(sov)   (sov->search_flags & SO_SEARCH_RECURSIVE)
+
+/* is the currrent element open? if so we also show children */
+#define TSELEM_OPEN(telm,sv)   ( (telm->flag & TSE_CLOSED)==0 || (SEARCHING_OUTLINER(sv) && (telm->flag & TSE_CHILDSEARCH)) )
+
 /* outliner_tree.c ----------------------------------------------- */
 
 void outliner_free_tree(ListBase *lb);
index 2c0a8c34747b77b94c60808a01393030bc14a25d..a88625aad0dc73518934113515e7ee5533150008 100644 (file)
@@ -134,7 +134,7 @@ static int outliner_select(SpaceOops *soops, ListBase *lb, int *index, short *se
                                change |= 1;
                        }
                }
-               else if ((tselem->flag & TSE_CLOSED)==0) {
+               else if (TSELEM_OPEN(tselem,soops)) {
                        /* Only try selecting sub-elements if we haven't hit the right element yet
                         *
                         * Hack warning:
index b3170f9cd1e34e1fc8fcf7d58666d4a632ad282e..b2fdd34aab207a67e3acaaa13d3cbbe77f4fd5e5 100644 (file)
@@ -145,7 +145,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
                                }
                        }
                }
-               if((tselem->flag & TSE_CLOSED)==0) {
+               if(TSELEM_OPEN(tselem,soops)) {
                        set_operation_types(soops, &te->subtree,
                                                                scenelevel, objectlevel, idlevel, datalevel);
                }
@@ -250,7 +250,7 @@ static void outliner_do_libdata_operation(bContext *C, Scene *scene, SpaceOops *
                                operation_cb(C, scene, te, tsep, tselem);
                        }
                }
-               if((tselem->flag & TSE_CLOSED)==0) {
+               if(TSELEM_OPEN(tselem,soops)) {
                        outliner_do_libdata_operation(C, scene, soops, &te->subtree, operation_cb);
                }
        }
@@ -397,7 +397,7 @@ void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soop
                                operation_cb(C, scene_owner ? scene_owner : scene_act, te, NULL, tselem);
                        }
                }
-               if((tselem->flag & TSE_CLOSED)==0) {
+               if(TSELEM_OPEN(tselem,soops)) {
                        outliner_do_object_operation(C, scene_act, soops, &te->subtree, operation_cb);
                }
        }
@@ -504,7 +504,7 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li
                                operation_cb(event, te, tselem);
                        }
                }
-               if((tselem->flag & TSE_CLOSED)==0) {
+               if(TSELEM_OPEN(tselem,soops)) {
                        outliner_do_data_operation(soops, type, event, &te->subtree, operation_cb);
                }
        }
@@ -857,7 +857,7 @@ static void outliner_do_id_set_operation(SpaceOops *soops, int type, ListBase *l
                                operation_cb(te, tselem, tsep, newid);
                        }
                }
-               if ((tselem->flag & TSE_CLOSED)==0) {
+               if (TSELEM_OPEN(tselem,soops)) {
                        outliner_do_id_set_operation(soops, type, &te->subtree, newid, operation_cb);
                }
        }
index 8904dcc360fc53e7b5da808879e2f8347e24bcc5..7e9eabc08dbdb08fb4c05f9acb8dd76e557c5fab 100644 (file)
@@ -827,6 +827,10 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
        check_persistant(soops, te, id, type, index);
        tselem= TREESTORE(te);  
        
+       /* if we are searching for something expand to see child elements */
+       if(SEARCHING_OUTLINER(soops))
+               tselem->flag |= TSE_CHILDSEARCH;
+       
        te->parent= parent;
        te->index= index;       // for data arays
        if(ELEM3(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP));
@@ -981,6 +985,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        else
                                te->name= (char*)RNA_struct_ui_name(ptr->type);
 
+                       /* If searching don't expand RNA entries */
+                       if(SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA",te->name)==0) tselem->flag &= ~TSE_CHILDSEARCH;
+
                        iterprop= RNA_struct_iterator_property(ptr->type);
                        tot= RNA_property_collection_length(ptr, iterprop);
 
@@ -989,7 +996,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                                if(!tselem->used)
                                        tselem->flag &= ~TSE_CLOSED;
 
-                       if(!(tselem->flag & TSE_CLOSED)) {
+                       if(TSELEM_OPEN(tselem,soops)) {
                                for(a=0; a<tot; a++)
                                        outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_PROPERTY, a);
                        }
@@ -1010,11 +1017,14 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        te->directdata= prop;
                        te->rnaptr= *ptr;
 
+                       /* If searching don't expand RNA entries */
+                       if(SEARCHING_OUTLINER(soops) && BLI_strcasecmp("RNA",te->name)==0) tselem->flag &= ~TSE_CHILDSEARCH;
+
                        if(proptype == PROP_POINTER) {
                                pptr= RNA_property_pointer_get(ptr, prop);
 
                                if(pptr.data) {
-                                       if(!(tselem->flag & TSE_CLOSED))
+                                       if(TSELEM_OPEN(tselem,soops))
                                                outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, -1);
                                        else
                                                te->flag |= TE_LAZY_CLOSED;
@@ -1023,7 +1033,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        else if(proptype == PROP_COLLECTION) {
                                tot= RNA_property_collection_length(ptr, prop);
 
-                               if(!(tselem->flag & TSE_CLOSED)) {
+                               if(TSELEM_OPEN(tselem,soops)) {
                                        for(a=0; a<tot; a++) {
                                                RNA_property_collection_lookup_int(ptr, prop, a, &pptr);
                                                outliner_add_element(soops, &te->subtree, (void*)&pptr, te, TSE_RNA_STRUCT, a);
@@ -1035,7 +1045,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                        else if(ELEM3(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
                                tot= RNA_property_array_length(ptr, prop);
 
-                               if(!(tselem->flag & TSE_CLOSED)) {
+                               if(TSELEM_OPEN(tselem,soops)) {
                                        for(a=0; a<tot; a++)
                                                outliner_add_element(soops, &te->subtree, (void*)ptr, te, TSE_RNA_ARRAY_ELEM, a);
                                }
@@ -1068,7 +1078,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
                te->directdata= idv;
                te->name= km->idname;
                
-               if(!(tselem->flag & TSE_CLOSED)) {
+               if(TSELEM_OPEN(tselem,soops)) {
                        a= 0;
                        
                        for (kmi= km->items.first; kmi; kmi= kmi->next, a++) {
@@ -1368,7 +1378,10 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
                         */
                        tselem= TREESTORE(te);
                        
-                       if ((tselem->flag & TSE_CLOSED) || outliner_filter_tree(soops, &te->subtree)==0) { 
+                       /* flag as not a found item */
+                       tselem->flag &= ~TSE_SEARCHMATCH;
+                       
+                       if ((!TSELEM_OPEN(tselem,soops)) || outliner_filter_tree(soops, &te->subtree)==0) { 
                                outliner_free_tree(&te->subtree);
                                BLI_remlink(lb, te);
                                
@@ -1377,6 +1390,11 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
                        }
                }
                else {
+                       tselem= TREESTORE(te);
+                       
+                       /* flag as a found item - we can then highlight it */
+                       tselem->flag |= TSE_SEARCHMATCH;
+                       
                        /* filter subtree too */
                        outliner_filter_tree(soops, &te->subtree);
                }
@@ -1399,6 +1417,14 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
        TreeStoreElem *tselem;
        int show_opened= (soops->treestore==NULL); /* on first view, we open scenes */
 
+       /* Are we looking for something - we want to tag parents to filter child matches
+        - NOT in datablocks view - searching all datablocks takes way too long to be useful
+        - this variable is only set once per tree build */
+       if(soops->search_string[0]!=0 && soops->outlinevis!=SO_DATABLOCKS)
+               soops->search_flags |= SO_SEARCH_RECURSIVE;
+       else
+               soops->search_flags &= ~SO_SEARCH_RECURSIVE;
+
        if(soops->tree.first && (soops->storeflag & SO_TREESTORE_REDRAW))
                return;
 
index c44f10efde870e4f3d5346c4de14974c9620be4e..af19aa490ae4c29b2a5ec66692bdae7bb3b26117 100644 (file)
@@ -51,6 +51,8 @@ typedef struct TreeStore {
 #define TSE_CLOSED             1
 #define TSE_SELECTED   2
 #define TSE_TEXTBUT            4
+#define TSE_CHILDSEARCH 8
+#define TSE_SEARCHMATCH 16
 
 /* TreeStoreElem types in BIF_outliner.h */
 
index 66b10bcbf2162edbe794b0858b93e26161fd3898..1627d4d2acb3bd6445af58307d47ad9374741cbc 100644 (file)
@@ -861,6 +861,7 @@ enum {
 /* outliner search flags (SpaceOops->search_flags) */
 #define SO_FIND_CASE_SENSITIVE         (1<<0)
 #define SO_FIND_COMPLETE                       (1<<1)
+#define SO_SEARCH_RECURSIVE            (1<<2)
 
 /* headerbuttons: 450-499 */