From 90a69c8e1d42bbe82b16a9caadad3fefca92f655 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 18 May 2010 16:59:34 +0000 Subject: [PATCH] The mechanism with which the TextViewCompleter detected changes (attaching a BMessageFilter to the BTextView to pre-process key down events) missed changes to the BTextView via other means, for example by pasting, or simply when SetText() is invoked on the BTextView. -> Introduced an alternative method of making the TextViewCompleter aware of changes, by invoking new method TextModified(). To bypass the old method, one has to call SetModificationsReported(true). URLInput::URLTextView now uses the new method in InsertText() and DeleteText(), which catches any and all changes to the text. Since the BAutoCompleter framework also controls the editor view contents, it needs to protect against re-entering some methods when the editor view reports the changes (fIgnoreEditViewStateChanges). Since we want the BAutoCompleter to always be aware of the current editor view contents, but not necessarily also running the choice mechanism (i.e. when you enter "www.google.com", you don't want the auto-completion kick back in when it is programmatically changed to "http://www.google.com" later on), the EditViewStateChange() method gets a boolean now "updateChoices". All programmatic changes to the URL will then not trigger displaying the choice pop-up, but the BAutoCompleter is always aware of the current editor view contents. All this fixes numerous issues and inconsistencies with entering text in the URL text view. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@500 94f232f2-1747-11df-bad5-a5bfde151594 --- src/apps/webpositive/URLInputGroup.cpp | 32 +++++++++++++++-- .../autocompletion/AutoCompleter.cpp | 4 +-- .../autocompletion/AutoCompleter.h | 5 +-- .../AutoCompleterDefaultImpl.cpp | 29 ++++++++++++---- .../autocompletion/AutoCompleterDefaultImpl.h | 3 +- .../autocompletion/TextViewCompleter.cpp | 34 +++++++++++++++---- .../autocompletion/TextViewCompleter.h | 5 +++ 7 files changed, 92 insertions(+), 20 deletions(-) diff --git a/src/apps/webpositive/URLInputGroup.cpp b/src/apps/webpositive/URLInputGroup.cpp index 7fec10caaf..e5d5c9ecb3 100644 --- a/src/apps/webpositive/URLInputGroup.cpp +++ b/src/apps/webpositive/URLInputGroup.cpp @@ -148,10 +148,14 @@ public: virtual BSize MinSize(); virtual BSize MaxSize(); + void SetUpdateAutoCompleterChoices(bool update); + protected: virtual void InsertText(const char* inText, int32 inLength, int32 inOffset, const text_run_array* inRuns); + virtual void DeleteText(int32 fromOffset, int32 toOffset); + private: void _AlignTextRect(); @@ -159,6 +163,7 @@ private: URLInputGroup* fURLInputGroup; TextViewCompleter* fURLAutoCompleter; BString fPreviousText; + bool fUpdateAutoCompleterChoices; }; @@ -168,10 +173,12 @@ URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent) fURLInputGroup(parent), fURLAutoCompleter(new TextViewCompleter(this, new BrowsingHistoryChoiceModel())), - fPreviousText("") + fPreviousText(""), + fUpdateAutoCompleterChoices(true) { MakeResizable(true); SetStylable(true); + fURLAutoCompleter->SetModificationsReported(true); } @@ -318,6 +325,13 @@ URLInputGroup::URLTextView::MaxSize() } +void +URLInputGroup::URLTextView::SetUpdateAutoCompleterChoices(bool update) +{ + fUpdateAutoCompleterChoices = update; +} + + void URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, int32 inOffset, const text_run_array* inRuns) @@ -360,6 +374,17 @@ URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength, font.SetFace(B_REGULAR_FACE); SetFontAndColor(baseUrlEnd, TextLength(), &font, B_FONT_ALL, &gray); } + + fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices); +} + + +void +URLInputGroup::URLTextView::DeleteText(int32 fromOffset, int32 toOffset) +{ + BTextView::DeleteText(fromOffset, toOffset); + + fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices); } @@ -599,8 +624,11 @@ URLInputGroup::TextView() const void URLInputGroup::SetText(const char* text) { - if (!text || !Text() || strcmp(Text(), text) != 0) + if (!text || !Text() || strcmp(Text(), text) != 0) { + fTextView->SetUpdateAutoCompleterChoices(false); fTextView->SetText(text); + fTextView->SetUpdateAutoCompleterChoices(true); + } } diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp index 98b659da40..2e5d45e164 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -175,10 +175,10 @@ BAutoCompleter::CancelChoice() void -BAutoCompleter::EditViewStateChanged() +BAutoCompleter::EditViewStateChanged(bool updateChoices) { if (fCompletionStyle) - fCompletionStyle->EditViewStateChanged(); + fCompletionStyle->EditViewStateChanged(updateChoices); } diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h index 8b5cb7be37..16a94559b4 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleter.h +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -101,7 +101,7 @@ public: virtual void ApplyChoice(bool hideChoices = true) = 0; virtual void CancelChoice() = 0; - virtual void EditViewStateChanged() = 0; + virtual void EditViewStateChanged(bool updateChoices) = 0; void SetEditView(EditView* view); void SetPatternSelector(PatternSelector* selector); @@ -130,7 +130,8 @@ protected: PatternSelector* patternSelector); virtual ~BAutoCompleter(); - void EditViewStateChanged(); + void EditViewStateChanged( + bool updateChoices = true); bool Select(int32 index); bool SelectNext(bool wrap = false); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp index 95ce32c7a0..5760852400 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -15,6 +15,7 @@ // #pragma mark - BDefaultPatternSelector + void BDefaultPatternSelector::SelectPatternBounds(const BString& text, int32 caretPos, int32* start, int32* length) @@ -38,7 +39,8 @@ BDefaultCompletionStyle::BDefaultCompletionStyle( CompletionStyle(editView, choiceModel, choiceView, patternSelector), fSelectedIndex(-1), fPatternStartPos(0), - fPatternLength(0) + fPatternLength(0), + fIgnoreEditViewStateChanges(false) { } @@ -114,15 +116,19 @@ BDefaultCompletionStyle::ApplyChoice(bool hideChoices) const BString& choiceStr = fChoiceModel->ChoiceAt(fSelectedIndex)->Text(); completedText.Insert(choiceStr, fPatternStartPos); + fIgnoreEditViewStateChanges = true; + fFullEnteredText = completedText; fPatternLength = choiceStr.Length(); fEditView->SetEditViewState(completedText, - fPatternStartPos+choiceStr.Length()); + fPatternStartPos + choiceStr.Length()); if (hideChoices) { fChoiceView->HideChoices(); Select(-1); } + + fIgnoreEditViewStateChanges = false; } @@ -132,25 +138,36 @@ BDefaultCompletionStyle::CancelChoice() if (!fChoiceView || !fEditView) return; if (fChoiceView->ChoicesAreShown()) { - fEditView->SetEditViewState(fFullEnteredText, - fPatternStartPos+fPatternLength); + fIgnoreEditViewStateChanges = true; + + fEditView->SetEditViewState(fFullEnteredText, + fPatternStartPos + fPatternLength); fChoiceView->HideChoices(); Select(-1); + + fIgnoreEditViewStateChanges = false; } } void -BDefaultCompletionStyle::EditViewStateChanged() +BDefaultCompletionStyle::EditViewStateChanged(bool updateChoices) { - if (!fChoiceModel || !fChoiceView || !fEditView) + if (fIgnoreEditViewStateChanges || !fChoiceModel || !fChoiceView + || !fEditView) { return; + } BString text; int32 caretPos; fEditView->GetEditViewState(text, &caretPos); if (fFullEnteredText == text) return; + fFullEnteredText = text; + + if (!updateChoices) + return; + fPatternSelector->SelectPatternBounds(text, caretPos, &fPatternStartPos, &fPatternLength); BString pattern(text.String() + fPatternStartPos, fPatternLength); diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h index cf01dbbad1..216a2d7f78 100644 --- a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -39,13 +39,14 @@ public: virtual void ApplyChoice(bool hideChoices = true); virtual void CancelChoice(); - virtual void EditViewStateChanged(); + virtual void EditViewStateChanged(bool updateChoices); private: BString fFullEnteredText; int32 fSelectedIndex; int32 fPatternStartPos; int32 fPatternLength; + bool fIgnoreEditViewStateChanges; }; diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp index 9f0a90b065..3f83e884d8 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.cpp +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.cpp @@ -63,13 +63,17 @@ TextViewCompleter::TextViewWrapper::GetAdjustmentFrame() } +// #pragma mark - + + TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, PatternSelector* patternSelector) : BAutoCompleter(new TextViewWrapper(textView), model, new BDefaultChoiceView(), patternSelector), BMessageFilter(B_KEY_DOWN), - fTextView(textView) + fTextView(textView), + fModificationsReported(false) { fTextView->AddFilter(this); } @@ -81,6 +85,20 @@ TextViewCompleter::~TextViewCompleter() } +void +TextViewCompleter::SetModificationsReported(bool reported) +{ + fModificationsReported = reported; +} + + +void +TextViewCompleter::TextModified(bool updateChoices) +{ + EditViewStateChanged(updateChoices); +} + + filter_result TextViewCompleter::Filter(BMessage* message, BHandler** target) { @@ -120,11 +138,13 @@ TextViewCompleter::Filter(BMessage* message, BHandler** target) return B_DISPATCH_MESSAGE; } default: - // dispatch message to textview manually... - Looper()->DispatchMessage(message, *target); - // ...and propagate the new state to the auto-completer: - EditViewStateChanged(); - return B_SKIP_MESSAGE; + if (!fModificationsReported) { + // dispatch message to textview manually... + Looper()->DispatchMessage(message, *target); + // ...and propagate the new state to the auto-completer: + EditViewStateChanged(); + return B_SKIP_MESSAGE; + } + return B_DISPATCH_MESSAGE; } - return B_DISPATCH_MESSAGE; } diff --git a/src/apps/webpositive/autocompletion/TextViewCompleter.h b/src/apps/webpositive/autocompletion/TextViewCompleter.h index a325603309..1a2955f6d7 100644 --- a/src/apps/webpositive/autocompletion/TextViewCompleter.h +++ b/src/apps/webpositive/autocompletion/TextViewCompleter.h @@ -22,6 +22,9 @@ public: PatternSelector* patternSelector = NULL); virtual ~TextViewCompleter(); + void SetModificationsReported(bool reported); + void TextModified(bool updateChoices); + private: virtual filter_result Filter(BMessage* message, BHandler** target); @@ -36,8 +39,10 @@ private: private: BTextView* fTextView; }; + private: BTextView* fTextView; + bool fModificationsReported; }; #endif // TEXT_CONTROL_COMPLETER_H