diff --git a/src/apps/webpositive/BrowserWindow.cpp b/src/apps/webpositive/BrowserWindow.cpp index 3dc03d54de..8ffbfd8797 100644 --- a/src/apps/webpositive/BrowserWindow.cpp +++ b/src/apps/webpositive/BrowserWindow.cpp @@ -37,6 +37,7 @@ #include "BrowserApp.h" #include "BrowsingHistory.h" #include "IconButton.h" +#include "TextControlCompleter.h" #include "WebPage.h" #include "WebTabView.h" #include "WebView.h" @@ -93,6 +94,66 @@ layoutItemFor(BView* view) } +class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel { + virtual void FetchChoicesFor(const BString& pattern) + { + int32 count = CountChoices(); + for (int32 i = 0; i < count; i++) { + delete reinterpret_cast( + fChoices.ItemAtFast(i)); + } + fChoices.MakeEmpty(); + + // Search through BrowsingHistory for any matches. + BrowsingHistory* history = BrowsingHistory::defaultInstance(); + if (!history->Lock()) + return; + + count = history->countItems(); + for (int32 i = 0; i < count; i++) { + BrowsingHistoryItem item = history->historyItemAt(i); + const BString& choiceText = item.url(); + int32 matchPos = choiceText.IFindFirst(pattern); + if (matchPos < 0) + continue; + fChoices.AddItem(new BAutoCompleter::Choice(choiceText, + choiceText, matchPos, pattern.Length())); + } + + history->Unlock(); + } + + virtual int32 CountChoices() const + { + return fChoices.CountItems(); + } + + virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const + { + return reinterpret_cast( + fChoices.ItemAt(index)); + } + +private: + BList fChoices; +}; + + +class BrowsingHistoryPatternSelector : public BAutoCompleter::PatternSelector { + virtual void SelectPatternBounds(const BString& text, int32 caretPos, + int32* start, int32* length) + { + if (!start || !length) + return; + *start = 0; + *length = text.Length(); + } +}; + + +// #pragma mark - BrowserWindow + + BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, ToolbarPolicy toolbarPolicy) : BWebWindow(frame, kApplicationName, @@ -228,6 +289,10 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fURLTextControl->MakeFocus(true); + fURLAutoCompleter = new TextControlCompleter(fURLTextControl, + new BrowsingHistoryChoiceModel(), + new BrowsingHistoryPatternSelector()); + fFindGroup = layoutItemFor(findGroup); fTabGroup = layoutItemFor(fTabManager->TabGroup()); } else { @@ -236,6 +301,7 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, fStopButton = 0; fGoButton = 0; fURLTextControl = 0; + fURLAutoCompleter = 0; fStatusText = 0; fLoadingProgressBar = 0; @@ -275,6 +341,8 @@ BrowserWindow::BrowserWindow(BRect frame, const BMessenger& downloadListener, BrowserWindow::~BrowserWindow() { + delete fURLAutoCompleter; + delete fTabManager; } diff --git a/src/apps/webpositive/BrowserWindow.h b/src/apps/webpositive/BrowserWindow.h index 9ef4426942..a296727c41 100644 --- a/src/apps/webpositive/BrowserWindow.h +++ b/src/apps/webpositive/BrowserWindow.h @@ -43,6 +43,7 @@ class BStringView; class BTextControl; class IconButton; class TabManager; +class TextControlCompleter; class BWebView; enum ToolbarPolicy { @@ -125,6 +126,7 @@ private: IconButton* fStopButton; BButton* fGoButton; BTextControl* fURLTextControl; + TextControlCompleter* fURLAutoCompleter; BStringView* fStatusText; BStatusBar* fLoadingProgressBar; BLayoutItem* fFindGroup; diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index c6583398f5..98b659da40 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -148,6 +148,16 @@ BAutoCompleter::SelectPrevious(bool wrap) } +bool +BAutoCompleter::IsChoiceSelected() const +{ + if (fCompletionStyle) + return fCompletionStyle->IsChoiceSelected(); + else + return false; +} + + void BAutoCompleter::ApplyChoice(bool hideChoices) { @@ -210,3 +220,4 @@ BAutoCompleter::SetCompletionStyle(CompletionStyle* style) delete fCompletionStyle; fCompletionStyle = style; } + diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 443981f809..33cb8ceb77 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -97,6 +97,7 @@ public: virtual bool Select(int32 index) = 0; virtual bool SelectNext(bool wrap = false) = 0; virtual bool SelectPrevious(bool wrap = false) = 0; + virtual bool IsChoiceSelected() const = 0; virtual void ApplyChoice(bool hideChoices = true) = 0; virtual void CancelChoice() = 0; @@ -135,6 +136,7 @@ protected: bool Select(int32 index); bool SelectNext(bool wrap = false); bool SelectPrevious(bool wrap = false); + bool IsChoiceSelected() const; void ApplyChoice(bool hideChoices = true); void CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 456a56f127..6f41c235a0 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -96,6 +96,13 @@ BDefaultCompletionStyle::SelectPrevious(bool wrap) } +bool +BDefaultCompletionStyle::IsChoiceSelected() const +{ + return fSelectedIndex >= 0; +} + + void BDefaultCompletionStyle::ApplyChoice(bool hideChoices) { @@ -112,8 +119,10 @@ BDefaultCompletionStyle::ApplyChoice(bool hideChoices) fEditView->SetEditViewState(completedText, fPatternStartPos+choiceStr.Length()); - if (hideChoices) + if (hideChoices) { fChoiceView->HideChoices(); + Select(-1); + } } diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index f697330915..81bca0fd1e 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -35,6 +35,7 @@ public: virtual bool Select(int32 index); virtual bool SelectNext(bool wrap = false); virtual bool SelectPrevious(bool wrap = false); + virtual bool IsChoiceSelected() const; virtual void ApplyChoice(bool hideChoices = true); virtual void CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp index e8e9cb0f52..6b3c257602 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -10,6 +10,7 @@ #include #include +#include #include "AutoCompleterDefaultImpl.h" @@ -58,7 +59,7 @@ TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() { BRect frame = fTextControl->TextView()->Bounds(); frame = fTextControl->TextView()->ConvertToScreen(frame); - frame.InsetBy(-1, -3); + frame.InsetBy(0, -3); return frame; } @@ -68,14 +69,16 @@ TextControlCompleter::TextControlCompleter(BTextControl* textControl, : BAutoCompleter(new TextControlWrapper(textControl), model, new BDefaultChoiceView(), patternSelector), - BMessageFilter(B_KEY_DOWN) + BMessageFilter(B_KEY_DOWN), + fTextControl(textControl) { - textControl->TextView()->AddFilter(this); + fTextControl->TextView()->AddFilter(this); } TextControlCompleter::~TextControlCompleter() { + fTextControl->TextView()->RemoveFilter(this); } @@ -99,9 +102,12 @@ TextControlCompleter::Filter(BMessage* message, BHandler** target) CancelChoice(); return B_SKIP_MESSAGE; case B_RETURN: - ApplyChoice(); - EditViewStateChanged(); - return B_SKIP_MESSAGE; + if (IsChoiceSelected()) { + ApplyChoice(); + EditViewStateChanged(); + } else + CancelChoice(); + return B_DISPATCH_MESSAGE; case B_TAB: { // make sure that the choices-view is closed when tabbing out: CancelChoice(); diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextControlCompleter.h index 66ae3558c3..89c5125f2e 100644 --- a/src/apps/webpositive/autocompletion/TextControlCompleter.h +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.h @@ -36,6 +36,8 @@ private: private: BTextControl* fTextControl; }; +private: + BTextControl* fTextControl; }; #endif // TEXT_CONTROL_COMPLETER_H