[haiku-commits] r35339 - haiku/trunk/src/kits/tracker

  • From: mmlr@xxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 30 Jan 2010 09:08:58 +0100 (CET)

Author: mmlr
Date: 2010-01-30 09:08:58 +0100 (Sat, 30 Jan 2010)
New Revision: 35339
Changeset: http://dev.haiku-os.org/changeset/35339/haiku

Modified:
   haiku/trunk/src/kits/tracker/Commands.h
   haiku/trunk/src/kits/tracker/CountView.cpp
   haiku/trunk/src/kits/tracker/CountView.h
   haiku/trunk/src/kits/tracker/Pose.cpp
   haiku/trunk/src/kits/tracker/Pose.h
   haiku/trunk/src/kits/tracker/PoseView.cpp
   haiku/trunk/src/kits/tracker/PoseView.h
   haiku/trunk/src/kits/tracker/SettingsViews.cpp
   haiku/trunk/src/kits/tracker/SettingsViews.h
   haiku/trunk/src/kits/tracker/TextWidget.cpp
   haiku/trunk/src/kits/tracker/TextWidget.h
   haiku/trunk/src/kits/tracker/TrackerSettings.cpp
   haiku/trunk/src/kits/tracker/TrackerSettings.h
Log:
Implement type ahead filtering (this time for real and without abusing the
vertically sorted pose list). When enabled typing will filter based on the
currently visible attribute columns. Using shift-space as a delimiter
independent filtering strings can be typed, so you can filter based on multiple
attributes at once to refine results while you type. Filtering stays active
until you cancel it using the escape key. While the filtered result is displayed
all normal file operations can be used. Using the return key while filtering
auto-selects and opens the first filter result, allowing for fast traversal
through directories and directly opening the topmost result.

* Introduces fFilteredPoseList which stores the active filter result. The list
  is only used when filtering is currently active, so no syncing is required
  otherwise.
* Some minor adjustments to leave out invalidations where non-visible poses are
  updated.
* Account for the now possible multiple lists throughout BPoseView.
* Add filter string output to the CountView and made that one a bit wider.
* Added all the settings-cruft for type ahead filtering (defaults to off).


Modified: haiku/trunk/src/kits/tracker/Commands.h
===================================================================
--- haiku/trunk/src/kits/tracker/Commands.h     2010-01-30 01:37:04 UTC (rev 
35338)
+++ haiku/trunk/src/kits/tracker/Commands.h     2010-01-30 08:08:58 UTC (rev 
35339)
@@ -125,6 +125,7 @@
 const uint32 kShowSelectionWhenInactiveChanged = 'Sswi';
 const uint32 kTransparentSelectionChanged = 'Trse';
 const uint32 kSortFolderNamesFirstChanged = 'Sfnf';
+const uint32 kTypeAheadFilteringChanged = 'Tafc';
 
 const uint32 kDesktopFilePanelRootChanged = 'Dfpr';
 const uint32 kFavoriteCountChanged = 'Fvct';

Modified: haiku/trunk/src/kits/tracker/CountView.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/CountView.cpp  2010-01-30 01:37:04 UTC (rev 
35338)
+++ haiku/trunk/src/kits/tracker/CountView.cpp  2010-01-30 08:08:58 UTC (rev 
35339)
@@ -59,7 +59,8 @@
        fBarberPoleMap(NULL),
        fLastBarberPoleOffset(5),
        fStartSpinningAfter(0),
-       fTypeAheadString("")
+       fTypeAheadString(""),
+       fFilterString("")
 {
        GetTrackerResources()->GetBitmapResource(B_MESSAGE_TYPE,
                R_BarberPoleBitmap, &fBarberPoleMap);
@@ -186,6 +187,7 @@
                fLastCount = fPoseView->CountItems();
                Invalidate(TextInvalRect());
        }
+
        // invalidate barber pole area if necessary
        TrySpinningBarberPole();
 }
@@ -209,20 +211,26 @@
        }
 
        BString itemString;
-       if (!IsTypingAhead()) {
+       if (IsTypingAhead())
+               itemString << TypeAhead();
+       else if (IsFiltering()) {
+               itemString << fLastCount << " " << Filter();
+       } else {
                if (fLastCount == 0) 
                        itemString << "no items";
                else if (fLastCount == 1) 
                        itemString << "1 item";
                else 
                        itemString << fLastCount << " items";
-       } else
-               itemString << TypeAhead();
+       }
+               
 
        BString string(itemString);
        BRect textRect(TextInvalRect());
 
-       TruncateString(&string, B_TRUNCATE_END, textRect.Width());
+       TruncateString(&string, IsTypingAhead() ? B_TRUNCATE_BEGINNING
+                       : IsFiltering() ? B_TRUNCATE_MIDDLE : B_TRUNCATE_END,
+               textRect.Width());
 
        if (IsTypingAhead()) {
                // use a muted gray for the typeahead
@@ -347,6 +355,44 @@
 
 
 void
+BCountView::AddFilter(const char *string)
+{
+       fFilterString += string;
+       Invalidate();
+}
+
+
+void
+BCountView::RemoveFilter()
+{
+       fFilterString.Truncate(fFilterString.Length() - 1);
+       Invalidate();
+}
+
+
+void
+BCountView::CancelFilter()
+{
+       fFilterString.Truncate(0);
+       Invalidate();
+}
+
+
+const char *
+BCountView::Filter() const
+{
+       return fFilterString.String();
+}
+
+
+bool
+BCountView::IsFiltering() const
+{
+       return fFilterString.Length() > 0;
+}
+
+
+void
 BCountView::SetBorderHighlighted(bool highlighted)
 {
        if (fBorderHighlighted == highlighted)

Modified: haiku/trunk/src/kits/tracker/CountView.h
===================================================================
--- haiku/trunk/src/kits/tracker/CountView.h    2010-01-30 01:37:04 UTC (rev 
35338)
+++ haiku/trunk/src/kits/tracker/CountView.h    2010-01-30 08:08:58 UTC (rev 
35339)
@@ -63,6 +63,12 @@
        const char *TypeAhead() const;
        bool IsTypingAhead() const;
 
+       void AddFilter(const char *string);
+       void RemoveFilter();
+       void CancelFilter();
+       const char *Filter() const;
+       bool IsFiltering() const;
+
        void SetBorderHighlighted(bool highlighted);
 
 private:
@@ -80,6 +86,7 @@
        float fLastBarberPoleOffset;
        bigtime_t fStartSpinningAfter;
        BString fTypeAheadString;
+       BString fFilterString;
 };
 
 } // namespace BPrivate

Modified: haiku/trunk/src/kits/tracker/Pose.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/Pose.cpp       2010-01-30 01:37:04 UTC (rev 
35338)
+++ haiku/trunk/src/kits/tracker/Pose.cpp       2010-01-30 08:08:58 UTC (rev 
35339)
@@ -216,7 +216,7 @@
 OneCheckAndUpdate(BTextWidget *widget, BPose *, BPoseView *poseView,
        BColumn *column, BPoint poseLoc)
 {
-       widget->CheckAndUpdate(poseLoc, column, poseView);
+       widget->CheckAndUpdate(poseLoc, column, poseView, true);
 }
 
 
@@ -233,7 +233,7 @@
 
 void
 BPose::UpdateWidgetAndModel(Model *resolvedModel, const char *attrName,
-       uint32 attrType, int32, BPoint poseLoc, BPoseView *poseView)
+       uint32 attrType, int32, BPoint poseLoc, BPoseView *poseView, bool 
visible)
 {
        if (poseView->ViewMode() != kListMode)
                poseLoc = Location(poseView);
@@ -242,7 +242,7 @@
 
        if (attrName) {
                // pick up new attributes and find out if icon needs updating
-               if (resolvedModel->AttrChanged(attrName))
+               if (resolvedModel->AttrChanged(attrName) && visible)
                        UpdateIcon(poseLoc, poseView);
 
                // ToDo: the following code is wrong, because this sort of 
hashing
@@ -252,7 +252,7 @@
                if (widget) {
                        BColumn *column = poseView->ColumnFor(attrHash);
                        if (column) 
-                               widget->CheckAndUpdate(poseLoc, column, 
poseView);
+                               widget->CheckAndUpdate(poseLoc, column, 
poseView, visible);
                } else if (attrType == 0) {
                        // attribute got likely removed, so let's search the
                        // column for the matching attribute name
@@ -261,7 +261,7 @@
                                BTextWidget *widget = fWidgetList.ItemAt(i);
                                BColumn *column = 
poseView->ColumnFor(widget->AttrHash());
                                if (column != NULL && 
!strcmp(column->AttrName(), attrName)) {
-                                       widget->CheckAndUpdate(poseLoc, column, 
poseView);
+                                       widget->CheckAndUpdate(poseLoc, column, 
poseView, visible);
                                        break;
                                }
                        }
@@ -274,7 +274,8 @@
                        if (resolvedModel->InitCheck() != B_OK)
                                return;
 
-                       UpdateIcon(poseLoc, poseView);
+                       if (visible)
+                               UpdateIcon(poseLoc, poseView);
                }
 
                // distribute stat changes
@@ -286,7 +287,7 @@
                        if (column->StatField()) {
                                BTextWidget *widget = 
WidgetFor(column->AttrHash());
                                if (widget) 
-                                       widget->CheckAndUpdate(poseLoc, column, 
poseView);
+                                       widget->CheckAndUpdate(poseLoc, column, 
poseView, visible);
                        }
                }
        }

Modified: haiku/trunk/src/kits/tracker/Pose.h
===================================================================
--- haiku/trunk/src/kits/tracker/Pose.h 2010-01-30 01:37:04 UTC (rev 35338)
+++ haiku/trunk/src/kits/tracker/Pose.h 2010-01-30 08:08:58 UTC (rev 35339)
@@ -97,7 +97,8 @@
                BRect CalcRect(const BPoseView *) const;
                void UpdateAllWidgets(int32 poseIndex, BPoint poseLoc, 
BPoseView *);
                void UpdateWidgetAndModel(Model *resolvedModel, const char 
*attrName,
-                               uint32 attrType, int32 poseIndex, BPoint 
poseLoc, BPoseView *view);
+                               uint32 attrType, int32 poseIndex, BPoint 
poseLoc,
+                               BPoseView *view, bool visible);
                bool UpdateVolumeSpaceBar(BVolume *volume);
                void UpdateIcon(BPoint poseLoc, BPoseView *);
 

Modified: haiku/trunk/src/kits/tracker/PoseView.cpp
===================================================================
--- haiku/trunk/src/kits/tracker/PoseView.cpp   2010-01-30 01:37:04 UTC (rev 
35338)
+++ haiku/trunk/src/kits/tracker/PoseView.cpp   2010-01-30 08:08:58 UTC (rev 
35339)
@@ -98,7 +98,7 @@
 
 
 const float kDoubleClickTresh = 6;
-const float kCountViewWidth = 62;
+const float kCountViewWidth = 76;
 
 const uint32 kAddNewPoses = 'Tanp';
 const uint32 kAddPosesCompleted = 'Tapc';
@@ -187,6 +187,7 @@
        fActivePose(NULL),
        fExtent(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN),
        fPoseList(new PoseList(40, true)),
+       fFilteredPoseList(new PoseList()),
        fVSPoseList(new PoseList()),
        fSelectionList(new PoseList()),
        fMimeTypesInSelectionCache(20, true),
@@ -229,6 +230,10 @@
        fIsWatchingDateFormatChange(false),
        fHasPosesInClipboard(false),
        fCursorCheck(false),
+       fFiltering(false),
+       fFilterStrings(4, true),
+       fLastFilterStringCount(1),
+       fLastFilterStringLength(0),
        fLastKeyTime(0),
        fLastDeskbarFrameCheckTime(LONGLONG_MIN),
        fDeskbarFrame(0, 0, -1, -1)
@@ -236,12 +241,14 @@
        fViewState->SetViewMode(viewMode);
        fShowSelectionWhenInactive = 
TrackerSettings().ShowSelectionWhenInactive();
        fTransparentSelection = TrackerSettings().TransparentSelection();
+       fFilterStrings.AddItem(new BString(""));
 }
 
 
 BPoseView::~BPoseView()
 {
        delete fPoseList;
+       delete fFilteredPoseList;
        delete fVSPoseList;
        delete fColumnList;
        delete fSelectionList;
@@ -829,6 +836,7 @@
                app->StopWatching(this, kShowSelectionWhenInactiveChanged);
                app->StopWatching(this, kTransparentSelectionChanged);
                app->StopWatching(this, kSortFolderNamesFirstChanged);
+               app->StopWatching(this, kTypeAheadFilteringChanged);
                app->Unlock();
        }
 
@@ -905,7 +913,7 @@
                // add Option-Return as a shortcut filter because AddShortcut 
doesn't allow
                // us to have shortcuts without Command yet
        AddFilter(new ShortcutFilter(B_ESCAPE, 0, B_CANCEL, this));
-               // Escape key, currently used only to abort an on-going 
clipboard cut
+               // Escape key, used to abort an on-going clipboard cut or 
filtering
        AddFilter(new ShortcutFilter(B_ESCAPE, B_SHIFT_KEY, 
kCancelSelectionToClipboard, this));
                // Escape + SHIFT will remove current selection from clipboard, 
or all poses from current folder if 0 selected
 
@@ -926,6 +934,7 @@
                app->StartWatching(this, kShowSelectionWhenInactiveChanged);
                app->StartWatching(this, kTransparentSelectionChanged);
                app->StartWatching(this, kSortFolderNamesFirstChanged);
+               app->StartWatching(this, kTypeAheadFilteringChanged);
                app->Unlock();
        }
 
@@ -1538,7 +1547,9 @@
        // above the top of the view (leaving you with an empty window)
        if (ViewMode() == kListMode) {
                BRect bounds(Bounds());
-               float lastItemTop = (fPoseList->CountItems() - 1) * 
fListElemHeight;
+               float lastItemTop
+                       = ((fFiltering ? fFilteredPoseList : 
fPoseList)->CountItems() - 1)
+                               * fListElemHeight;
                if (bounds.top > lastItemTop)
                        BView::ScrollTo(bounds.left, max_c(lastItemTop, 0));
        }
@@ -1621,6 +1632,91 @@
 
 
 void
+BPoseView::AddPoseToList(PoseList *list, bool visibleList, bool insertionSort,
+       BPose *pose, BRect &viewBounds, float &listViewScrollBy, bool forceDraw)
+{
+       int32 poseIndex = list->CountItems();
+
+       BRect poseBounds;
+       bool havePoseBounds = false;
+       bool addedItem = false;
+       bool needToDraw = true;
+
+       if (insertionSort && list->CountItems()) {
+               int32 orientation = BSearchList(list, pose, &poseIndex);
+
+               if (orientation == kInsertAfter)
+                       poseIndex++;
+
+               if (visibleList) {
+                       // we only care about the positions if this is a 
visible list
+                       poseBounds = CalcPoseRectList(pose, poseIndex);
+                       havePoseBounds = true;
+
+                       BRect srcRect(Extent());
+                       srcRect.top = poseBounds.top;
+                       srcRect = srcRect & viewBounds;
+                       BRect destRect(srcRect);
+                       destRect.OffsetBy(0, fListElemHeight);
+
+                       // special case the addition of a pose that scrolls
+                       // the extent into the view for the first time:
+                       if (destRect.bottom > viewBounds.top
+                               && destRect.top > destRect.bottom) {
+                               // make destRect valid
+                               destRect.top = viewBounds.top;
+                       }
+
+                       if (srcRect.Intersects(viewBounds)
+                               || destRect.Intersects(viewBounds)) {
+                               // The visual area is affected by the insertion.
+                               // If items have been added above the visual 
area,
+                               // delay the scrolling. srcRect.bottom holds the
+                               // current Extent(). So if the bottom is still 
above
+                               // the viewBounds top, it means the view is 
scrolled
+                               // to show the area below the items that have 
already
+                               // been added.
+                               if (srcRect.top == viewBounds.top
+                                       && srcRect.bottom >= viewBounds.top) {
+                                       // if new pose above current view 
bounds, cache up
+                                       // the draw and do it later
+                                       listViewScrollBy += fListElemHeight;
+                                       needToDraw = false;
+                               } else {
+                                       FinishPendingScroll(listViewScrollBy, 
viewBounds);
+                                       list->AddItem(pose, poseIndex);
+
+                                       fMimeTypeListIsDirty = true;
+                                       addedItem = true;
+                                       if (srcRect.IsValid()) {
+                                               CopyBits(srcRect, destRect);
+                                               srcRect.bottom = destRect.top;
+                                               SynchronousUpdate(srcRect);
+                                       } else {
+                                               SynchronousUpdate(destRect);
+                                       }
+                                       needToDraw = false;
+                               }
+                       }
+               }
+       }
+
+       if (!addedItem) {
+               list->AddItem(pose, poseIndex);
+               fMimeTypeListIsDirty = true;
+       }
+
+       if (visibleList && needToDraw && forceDraw) {
+               if (!havePoseBounds)
+                       poseBounds = CalcPoseRectList(pose, poseIndex);
+               if (viewBounds.Intersects(poseBounds))
+                       SynchronousUpdate(poseBounds);
+       }
+}
+
+
+
+void
 BPoseView::CreatePoses(Model **models, PoseInfo *poseInfoArray, int32 count,
        BPose **resultingPoses, bool insertionSort,     int32 *lastPoseIndexPtr,
        BRect *boundsPtr, bool forceDraw)
@@ -1676,75 +1772,14 @@
                switch (ViewMode()) {
                        case kListMode:
                        {
-                               poseIndex = fPoseList->CountItems();
+                               AddPoseToList(fPoseList, !fFiltering, 
insertionSort, pose,
+                                       viewBounds, listViewScrollBy, 
forceDraw);
 
-                               bool havePoseBounds = false;
-                               bool addedItem = false;
-                               bool needToDraw = true;
-
-                               if (insertionSort && fPoseList->CountItems()) {
-                                       int32 orientation = BSearchList(pose, 
&poseIndex);
-
-                                       if (orientation == kInsertAfter)
-                                               poseIndex++;
-
-                                       poseBounds = CalcPoseRectList(pose, 
poseIndex);
-                                       havePoseBounds = true;
-                                       BRect srcRect(Extent());
-                                       srcRect.top = poseBounds.top;
-                                       srcRect = srcRect & viewBounds;
-                                       BRect destRect(srcRect);
-                                       destRect.OffsetBy(0, fListElemHeight);
-                                       // special case the addition of a pose 
that scrolls
-                                       // the extent into the view for the 
first time:
-                                       if (destRect.bottom > viewBounds.top
-                                               && destRect.top > 
destRect.bottom) {
-                                               // make destRect valid
-                                               destRect.top = viewBounds.top;
-                                       }
-
-                                       if (srcRect.Intersects(viewBounds)
-                                               || 
destRect.Intersects(viewBounds)) {
-                                               // The visual area is affected 
by the insertion.
-                                               // If items have been added 
above the visual area,
-                                               // delay the scrolling. 
srcRect.bottom holds the
-                                               // current Extent(). So if the 
bottom is still above
-                                               // the viewBounds top, it means 
the view is scrolled
-                                               // to show the area below the 
items that have already
-                                               // been added.
-                                               if (srcRect.top == 
viewBounds.top
-                                                       && srcRect.bottom >= 
viewBounds.top) {
-                                                       // if new pose above 
current view bounds, cache up
-                                                       // the draw and do it 
later
-                                                       listViewScrollBy += 
fListElemHeight;
-                                                       needToDraw = false;
-                                               } else {
-                                                       
FinishPendingScroll(listViewScrollBy, viewBounds);
-                                                       
fPoseList->AddItem(pose, poseIndex);
-                                                       fMimeTypeListIsDirty = 
true;
-                                                       addedItem = true;
-                                                       if (srcRect.IsValid()) {
-                                                               
CopyBits(srcRect, destRect);
-                                                               srcRect.bottom 
= destRect.top;
-                                                               
SynchronousUpdate(srcRect);
-                                                       } else {
-                                                               
SynchronousUpdate(destRect);
-                                                       }
-                                                       needToDraw = false;
-                                               }
-                                       }
+                               if (fFiltering && FilterPose(pose)) {
+                                       AddPoseToList(fFilteredPoseList, true, 
insertionSort, pose,
+                                               viewBounds, listViewScrollBy, 
forceDraw);
                                }
-                               if (!addedItem) {
-                                       fPoseList->AddItem(pose, poseIndex);
-                                       fMimeTypeListIsDirty = true;
-                               }
 
-                               if (needToDraw && forceDraw) {
-                                       if (!havePoseBounds)
-                                               poseBounds = 
CalcPoseRectList(pose, poseIndex);
-                                       if (viewBounds.Intersects(poseBounds))
-                                               SynchronousUpdate(poseBounds);
-                               }
                                break;
                        }
 
@@ -2149,10 +2184,14 @@
                case B_CANCEL:
                        if (FSClipboardHasRefs())
                                FSClipboardClear();
+                       else if (fFiltering)
+                               CancelFiltering();
                        break;
 
                case kCancelSelectionToClipboard:
-                       FSClipboardRemovePoses(TargetModel()->NodeRef(), 
(fSelectionList->CountItems() > 0 ? fSelectionList : fPoseList));
+                       FSClipboardRemovePoses(TargetModel()->NodeRef(),
+                               (fSelectionList->CountItems() > 0
+                                       ? fSelectionList : fPoseList));
                        break;
 
                case kFSClipboardChanges:
@@ -2264,7 +2303,8 @@
                        BPose *pose = fSelectionList->FirstItem();
                        if (pose) {
                                pose->EditFirstWidget(BPoint(0,
-                                       fPoseList->IndexOf(pose) * 
fListElemHeight), this);
+                                       (fFiltering ? fFilteredPoseList : 
fPoseList)->IndexOf(pose)
+                                       * fListElemHeight), this);
                        }
                        break;
                }
@@ -2436,6 +2476,18 @@
                                                        Invalidate();
                                                }
                                                break;
+
+                                       case kTypeAheadFilteringChanged:
+                                       {
+                                               TrackerSettings settings;
+                                               bool typeAheadFiltering;
+                                               if 
(message->FindBool("TypeAheadFiltering", &typeAheadFiltering) == B_OK)
+                                                       
settings.SetTypeAheadFiltering(typeAheadFiltering);
+
+                                               if (fFiltering && 
!typeAheadFiltering)
+                                                       CancelFiltering();
+                                               break;
+                                       }
                                }
                        }
                        break;
@@ -2537,12 +2589,13 @@
        BRect rect(Bounds());
 
        // add widget for all visible poses
-       int32 count = fPoseList->CountItems();
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       int32 count = poseList->CountItems();
        int32 startIndex = (int32)(rect.top / fListElemHeight);
        BPoint loc(0, startIndex * fListElemHeight);
 
        for (int32 index = startIndex; index < count; index++) {
-               BPose *pose = fPoseList->ItemAt(index);
+               BPose *pose = poseList->ItemAt(index);
                if (!pose->WidgetFor(newColumn->AttrHash()))
                        pose->AddWidget(this, newColumn);
 
@@ -2806,6 +2859,9 @@
        // toggle view layout between listmode and non-listmode, if necessary
        BContainerWindow *window = ContainerWindow();
        if (oldMode == kListMode) {
+               if (fFiltering)
+                       CancelFiltering();
+
                fTitleView->RemoveSelf();
 
                if (window)
@@ -2953,11 +3009,13 @@
 void
 BPoseView::SetPosesClipboardMode(uint32 clipboardMode)
 {
-       int32 count = fPoseList->CountItems();
        if (ViewMode() == kListMode) {
+               PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+               int32 count = poseList->CountItems();
+
                BPoint loc(0,0);
                for (int32 index = 0; index < count; index++) {
-                       BPose *pose = fPoseList->ItemAt(index);
+                       BPose *pose = poseList->ItemAt(index);
                        if (pose->ClipboardMode() != clipboardMode) {
                                pose->SetClipboardMode(clipboardMode);
                                Invalidate(pose->CalcRect(loc, this, false));
@@ -2965,6 +3023,7 @@
                        loc.y += fListElemHeight;
                }
        } else {
+               int32 count = fPoseList->CountItems();
                for (int32 index = 0; index < count; index++) {
                        BPose *pose = fPoseList->ItemAt(index);
                        if (pose->ClipboardMode() != clipboardMode) {
@@ -3024,9 +3083,16 @@
 
                        if (!fullInvalidateNeeded) {
                                if (ViewMode() == kListMode) {
-                                       loc.y = foundNodeIndex * 
fListElemHeight;
-                                       if (loc.y <= bounds.bottom && loc.y >= 
bounds.top)
-                                               Invalidate(pose->CalcRect(loc, 
this, false));
+                                       if (fFiltering) {
+                                               pose = 
fFilteredPoseList->FindPose(&clipNode->node,
+                                                       &foundNodeIndex);
+                                       }
+
+                                       if (pose != NULL) {
+                                               loc.y = foundNodeIndex * 
fListElemHeight;
+                                               if (loc.y <= bounds.bottom && 
loc.y >= bounds.top)
+                                                       
Invalidate(pose->CalcRect(loc, this, false));
+                                       }
                                } else {
                                        BRect poseRect(pose->CalcRect(this));
                                        if (bounds.Contains(poseRect.LeftTop())
@@ -3629,9 +3695,10 @@
        BPoint loc(0, start * fListElemHeight);
        BRect bounds(Bounds());
 
-       int32 count = fPoseList->CountItems();
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       int32 count = poseList->CountItems();
        for (int32 index = start; index < end && index < count; index++) {
-               BPose *pose = fPoseList->ItemAt(index);
+               BPose *pose = poseList->ItemAt(index);
                fSelectionList->AddItem(pose);
                if (index == start)
                        fSelectionPivotPose = pose;
@@ -3724,10 +3791,11 @@
        if (ViewMode() == kListMode) {
                // TODO: need a simple call to CalcRect that works both in 
listView and
                // icon view modes without the need for an index/pos
-               int32 count = fPoseList->CountItems();
+               PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+               int32 count = poseList->CountItems();
                BPoint loc(0, 0);
                for (int32 index = 0; index < count; index++) {
-                       if (pose == fPoseList->ItemAt(index)) {
+                       if (pose == poseList->ItemAt(index)) {
                                Invalidate(pose->CalcRect(loc, this));
                                break;
                        }
@@ -5187,7 +5255,11 @@
                        if (pose->TargetModel()->OpenNode() == B_OK) {
                                pose->UpdateAllWidgets(index, loc, this);
                                pose->TargetModel()->CloseNode();
-                               CheckPoseSortOrder(pose, index);
+                               _CheckPoseSortOrder(fPoseList, pose, index);
+                               if (fFiltering
+                                       && 
fFilteredPoseList->FindPose(&itemNode, &index) != NULL) {
+                                       _CheckPoseSortOrder(fFilteredPoseList, 
pose, index);
+                               }
                        }
                } else {
                        // also must watch for renames on zombies
@@ -5239,6 +5311,11 @@
        attr_info info;
        memset(&info, 0, sizeof(attr_info));
        if (pose) {
+               int32 poseListIndex = index;
+               bool visible = true;
+               if (fFiltering)
+                       visible = fFilteredPoseList->DeepFindPose(&itemNode, 
&index) != NULL;
+
                BPoint loc(0, index * fListElemHeight);
 
                Model *model = pose->TargetModel();
@@ -5263,9 +5340,12 @@
                        if (attrName && model->Node()) {
                                        // the call below might fail if the 
attribute has been removed
                                model->Node()->GetAttrInfo(attrName, &info);
-                               pose->UpdateWidgetAndModel(model, attrName, 
info.type, index, loc, this);
-                       } else
-                               pose->UpdateWidgetAndModel(model, 0, 0, index, 
loc, this);
+                               pose->UpdateWidgetAndModel(model, attrName, 
info.type, index,
+                                       loc, this, visible);
+                       } else {
+                               pose->UpdateWidgetAndModel(model, 0, 0, index, 
loc, this,
+                                       visible);
+                       }
 
                        model->CloseNode();
                } else {
@@ -5283,8 +5363,13 @@
                        // may overlap and we get aliasing
                        attrHash = AttrHashString(attrName, info.type);
                }
-               if (!attrName || attrHash == PrimarySort() || attrHash == 
SecondarySort())
-                       CheckPoseSortOrder(pose, index);
+
+               if (!attrName || attrHash == PrimarySort()
+                       || attrHash == SecondarySort()) {
+                       _CheckPoseSortOrder(fPoseList, pose, poseListIndex);
+                       if (fFiltering)
+                               _CheckPoseSortOrder(fFilteredPoseList, pose, 
index);
+               }
        } else {
                // we received an attr changed notification for a zombie model, 
it means
                // that although we couldn't open the node the first time, it 
seems
@@ -5310,13 +5395,19 @@
        BPoint location;
        if (ViewMode() == kListMode) {
                // need to find the index of the pose in the pose list
-               int32 count = fPoseList->CountItems();
+               bool found = false;
+               PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+               int32 count = poseList->CountItems();
                for (int32 index = 0; index < count; index++) {
-                       if (fPoseList->ItemAt(index) == pose) {
+                       if (poseList->ItemAt(index) == pose) {
                                location.Set(0, index * fListElemHeight);
+                               found = true;
                                break;
                        }
                }
+
+               if (!found)
+                       return;
        }
 
        pose->UpdateIcon(location, this);
@@ -5732,9 +5823,10 @@
 
        bool iconMode = ViewMode() != kListMode;
 
-       int32 count = fPoseList->CountItems();
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       int32 count = poseList->CountItems();
        for (int32 index = startIndex; index < count; index++) {
-               BPose *pose = fPoseList->ItemAt(index);
+               BPose *pose = poseList->ItemAt(index);
                fSelectionList->AddItem(pose);
                if (index == startIndex)
                        fSelectionPivotPose = pose;
@@ -5780,9 +5872,10 @@
 
        bool iconMode = ViewMode() != kListMode;
 
-       int32 count = fPoseList->CountItems();
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       int32 count = poseList->CountItems();
        for (int32 index = startIndex; index < count; index++) {
-               BPose *pose = fPoseList->ItemAt(index);
+               BPose *pose = poseList->ItemAt(index);
 
                if (pose->IsSelected()) {
                        fSelectionList->RemoveItem(pose);
@@ -5832,7 +5925,8 @@
 
        expression = expressionPointer;
 
-       int32 count = fPoseList->CountItems();
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       int32 count = poseList->CountItems();
        TrackerString name;
 
        RegExp regExpression;
@@ -5857,7 +5951,7 @@
        // TrackerString::CompileRegExp and reuse the expression. However, then 
we
        // have to take care of the case sensitivity ourselves.
        for (int32 index = 0; index < count; index++) {
-               BPose *pose = fPoseList->ItemAt(index);
+               BPose *pose = poseList->ItemAt(index);
                name = pose->TargetModel()->Name();
                if (name.Matches(expression.String(), !ignoreCase, 
expressionType) ^ invertSelection) {
                        matchCount++;
@@ -5910,6 +6004,9 @@
                }
 
                case B_RETURN:
+                       if (fFiltering && fSelectionList->CountItems() == 0)
+                               SelectPose(fFilteredPoseList->FirstItem(), 0);
+
                        OpenSelection();
                        break;
 
@@ -5917,14 +6014,15 @@
                        // select the first entry (if in listview mode), and
                        // scroll to the top of the view
                        if (ViewMode() == kListMode) {
+                               PoseList *poseList = fFiltering ? 
fFilteredPoseList : fPoseList;
                                BPose *pose = fSelectionList->LastItem();
 
                                if (pose != NULL && fMultipleSelection && 
(modifiers() & B_SHIFT_KEY) != 0) {
-                                       int32 index = fPoseList->IndexOf(pose);
+                                       int32 index = poseList->IndexOf(pose);
 
                                        // select all items from the current 
one till the top
                                        for (int32 i = index; i-- > 0; ) {
-                                               pose = fPoseList->ItemAt(i);
+                                               pose = poseList->ItemAt(i);
                                                if (pose == NULL)
                                                        continue;
 
@@ -5932,7 +6030,8 @@
                                                        
AddPoseToSelection(pose, i, i == 0);
                                        }
                                } else
-                                       SelectPose(fPoseList->FirstItem(), 0);
+                                       SelectPose(poseList->FirstItem(), 0);
+
                        } else if (fVScrollBar)
                                fVScrollBar->SetValue(0);
                        break;
@@ -5941,15 +6040,16 @@
                        // select the last entry (if in listview mode), and
                        // scroll to the bottom of the view
                        if (ViewMode() == kListMode) {
+                               PoseList *poseList = fFiltering ? 
fFilteredPoseList : fPoseList;
                                BPose *pose = fSelectionList->FirstItem();
 
                                if (pose != NULL && fMultipleSelection && 
(modifiers() & B_SHIFT_KEY) != 0) {
-                                       int32 index = fPoseList->IndexOf(pose);
-                                       int32 count = fPoseList->CountItems() - 
1;
+                                       int32 index = poseList->IndexOf(pose);
+                                       int32 count = poseList->CountItems() - 
1;
 
                                        // select all items from the current 
one to the bottom
                                        for (int32 i = index; i <= count; i++) {
-                                               pose = fPoseList->ItemAt(i);
+                                               pose = poseList->ItemAt(i);
                                                if (pose == NULL)
                                                        continue;
 
@@ -5957,7 +6057,8 @@
                                                        
AddPoseToSelection(pose, i, i == count);
                                        }
                                } else
-                                       SelectPose(fPoseList->LastItem(), 
fPoseList->CountItems() - 1);
+                                       SelectPose(poseList->LastItem(), 
poseList->CountItems() - 1);
+
                        } else if (fVScrollBar) {
                                float max, min;
                                fVScrollBar->GetRange(&min, &max);
@@ -5985,6 +6086,9 @@
                        if (IsFilePanel())
                                _inherited::KeyDown(bytes, count);
                        else {
+                               if (TrackerSettings().TypeAheadFiltering())
+                                       break;
+
                                if (fSelectionList->IsEmpty())
                                        sMatchString[0] = '\0';
                                else {
@@ -6029,6 +6133,22 @@
 
                case B_BACKSPACE:
                {
+                       if (TrackerSettings().TypeAheadFiltering()) {
+                               BString *lastString = fFilterStrings.LastItem();
+                               if (lastString->Length() == 0) {
+                                       int32 stringCount = 
fFilterStrings.CountItems();
+                                       if (stringCount > 1)
+                                               delete 
fFilterStrings.RemoveItemAt(stringCount - 1);
+                                       else
+                                               break;
+                               } else
+                                       
lastString->Truncate(lastString->Length() - 1);
+
+                               fCountView->RemoveFilter();
+                               FilterChanged();
+                               break;
+                       }
+
                        if (strlen(sMatchString) == 0)
                                break;
 
@@ -6056,6 +6176,22 @@
                        // create a null-terminated version of typed char
                        char searchChar[4] = { key, 0 };
 
+                       if (TrackerSettings().TypeAheadFiltering()) {
+                               if (key == ' ' && modifiers() & B_SHIFT_KEY) {
+                                       if (fFilterStrings.LastItem()->Length() 
== 0)
+                                               break;
+
+                                       fFilterStrings.AddItem(new BString());
+                                       fCountView->AddFilter("|");
+                                       break;
+                               }
+
+                               fFilterStrings.LastItem()->Append(searchChar);
+                               fCountView->AddFilter(searchChar);
+                               FilterChanged();
+                               break;
+                       }
+
                        bigtime_t doubleClickSpeed;
                        get_click_speed(&doubleClickSpeed);
 
@@ -6199,34 +6335,36 @@
        BPose *selectedPose = fSelectionList->LastItem();
 
        if (ViewMode() == kListMode) {
+               PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+
                switch (arrowKey) {
                        case B_UP_ARROW:
                        case B_LEFT_ARROW:
                                if (selectedPose) {
-                                       resultingIndex = 
fPoseList->IndexOf(selectedPose) - 1;
-                                       poseToSelect = 
fPoseList->ItemAt(resultingIndex);
+                                       resultingIndex = 
poseList->IndexOf(selectedPose) - 1;
+                                       poseToSelect = 
poseList->ItemAt(resultingIndex);
                                        if (!poseToSelect && arrowKey == 
B_LEFT_ARROW) {
-                                               resultingIndex = 
fPoseList->CountItems() - 1;
-                                               poseToSelect = 
fPoseList->LastItem();
+                                               resultingIndex = 
poseList->CountItems() - 1;
+                                               poseToSelect = 
poseList->LastItem();
                                        }
                                } else {
-                                       resultingIndex = 
fPoseList->CountItems() - 1;
-                                       poseToSelect = fPoseList->LastItem();
+                                       resultingIndex = poseList->CountItems() 
- 1;
+                                       poseToSelect = poseList->LastItem();
                                }
                                break;
 
                        case B_DOWN_ARROW:
                        case B_RIGHT_ARROW:
                                if (selectedPose) {
-                                       resultingIndex = 
fPoseList->IndexOf(selectedPose) + 1;
-                                       poseToSelect = 
fPoseList->ItemAt(resultingIndex);
+                                       resultingIndex = 
poseList->IndexOf(selectedPose) + 1;
+                                       poseToSelect = 
poseList->ItemAt(resultingIndex);
                                        if (!poseToSelect && arrowKey == 
B_RIGHT_ARROW) {
                                                resultingIndex = 0;
-                                               poseToSelect = 
fPoseList->FirstItem();
+                                               poseToSelect = 
poseList->FirstItem();
                                        }
                                } else {
                                        resultingIndex = 0;
-                                       poseToSelect = fPoseList->FirstItem();
+                                       poseToSelect = poseList->FirstItem();
                                }
                                break;
                }
@@ -6632,7 +6770,8 @@
        BPoint tempLoc;
        GetMouse(&tempLoc, &button);
        if (button) {
-               int32 index = fPoseList->IndexOf(pose);
+               int32 index
+                       = (fFiltering ? fFilteredPoseList : 
fPoseList)->IndexOf(pose);
                message.AddInt32("buttons", (int32)button);
                BRect dragRect(GetDragRect(index));
                BBitmap *dragBitmap = NULL;
@@ -6721,14 +6860,15 @@
 
        BRect bounds(Bounds());
 
-       BPose *pose = fPoseList->ItemAt(clickedPoseIndex);
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       BPose *pose = poseList->ItemAt(clickedPoseIndex);
        if (ViewMode() == kListMode) {
-               int32 count = fPoseList->CountItems();
+               int32 count = poseList->CountItems();
                int32 startIndex = (int32)(bounds.top / fListElemHeight);
                BPoint loc(0, startIndex * fListElemHeight);
 
                for (int32 index = startIndex; index < count; index++) {
-                       pose = fPoseList->ItemAt(index);
+                       pose = poseList->ItemAt(index);
                        if (pose->IsSelected()) {
                                BRect poseRect(pose->CalcRect(loc, this, true));
                                if (poseRect.Intersects(inner)) {
@@ -6791,18 +6931,19 @@
        BRect result;
        BRect bounds(Bounds());
 
-       BPose *pose = fPoseList->ItemAt(clickedPoseIndex);
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       BPose *pose = poseList->ItemAt(clickedPoseIndex);
        if (ViewMode() == kListMode) {
                // get starting rect of clicked pose
                result = CalcPoseRectList(pose, clickedPoseIndex, true);
 
                // add rects for visible poses only
-               int32 count = fPoseList->CountItems();
+               int32 count = poseList->CountItems();
                int32 startIndex = (int32)(bounds.top / fListElemHeight);
                BPoint loc(0, startIndex * fListElemHeight);
 
                for (int32 index = startIndex; index < count; index++) {
-                       pose = fPoseList->ItemAt(index);
+                       pose = poseList->ItemAt(index);
                        if (pose->IsSelected())
                                result = result | pose->CalcRect(loc, this, 
true);
 
@@ -6994,9 +7135,10 @@
 
        BPoint loc(0, startIndex * fListElemHeight);
 
-       int32 count = fPoseList->CountItems();
+       PoseList *poseList = fFiltering ? fFilteredPoseList : fPoseList;
+       int32 count = poseList->CountItems();
        for (int32 index = startIndex; index < count; index++) {
-               BPose *pose = fPoseList->ItemAt(index);
+               BPose *pose = poseList->ItemAt(index);
                BRect poseRect(pose->CalcRect(loc, this));
 
                if (selectionRect.Intersects(poseRect)) {
@@ -7026,7 +7168,7 @@
                int32 oldIndex = (int32)(*oldList)->ItemAt(index);
 
                if (!newList->HasItem((void *)oldIndex)) {
-                       BPose *pose = fPoseList->ItemAt(oldIndex);
+                       BPose *pose = poseList->ItemAt(oldIndex);
                        pose->Select(!pose->IsSelected());
                        loc.Set(0, oldIndex * fListElemHeight);
                        BRect poseRect(pose->CalcRect(loc, this));
@@ -7128,8 +7270,9 @@
                }
 
                if (ViewMode() == kListMode) {
-                       int32 currSelIndex = fPoseList->IndexOf(pose);
-                       int32 lastSelIndex = 
fPoseList->IndexOf(fSelectionPivotPose);
+                       PoseList *poseList = fFiltering ? fFilteredPoseList : 
fPoseList;
+                       int32 currSelIndex = poseList->IndexOf(pose);
+                       int32 lastSelIndex = 
poseList->IndexOf(fSelectionPivotPose);
 
                        int32 startRange;

[... truncated: 849 lines follow ...]

Other related posts:

  • » [haiku-commits] r35339 - haiku/trunk/src/kits/tracker - mmlr