From fd5768c40d1eb05b345577285ec72788d7b115a5 Mon Sep 17 00:00:00 2001 From: stippi Date: Tue, 2 Mar 2010 12:38:07 +0000 Subject: [PATCH] Imported Beam auto completion framework, converted license to MIT (with permission from Oliver) and applied Haiku coding style. The base classes have been named such that they could become official Haiku API in the future. git-svn-id: http://svn.haiku-os.org/webpositive/webkit/trunk@266 94f232f2-1747-11df-bad5-a5bfde151594 --- .../autocompletion/AutoCompleter.cpp | 212 ++++++++++ .../autocompletion/AutoCompleter.h | 154 +++++++ .../AutoCompleterDefaultImpl.cpp | 377 ++++++++++++++++++ .../autocompletion/AutoCompleterDefaultImpl.h | 92 +++++ .../autocompletion/TextControlCompleter.cpp | 118 ++++++ .../autocompletion/TextControlCompleter.h | 41 ++ 6 files changed, 994 insertions(+) create mode 100644 src/apps/webpositive/autocompletion/AutoCompleter.cpp create mode 100644 src/apps/webpositive/autocompletion/AutoCompleter.h create mode 100644 src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp create mode 100644 src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h create mode 100644 src/apps/webpositive/autocompletion/TextControlCompleter.cpp create mode 100644 src/apps/webpositive/autocompletion/TextControlCompleter.h diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.cpp b/src/apps/webpositive/autocompletion/AutoCompleter.cpp new file mode 100644 index 0000000000..c6583398f5 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleter.cpp @@ -0,0 +1,212 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "AutoCompleter.h" + +#include +#include + +#include "AutoCompleterDefaultImpl.h" + + +// #pragma mark - DefaultPatternSelector + + +class DefaultPatternSelector : public BAutoCompleter::PatternSelector { +public: + virtual void SelectPatternBounds(const BString& text, int32 caretPos, + int32* start, int32* length); +}; + + +void +DefaultPatternSelector::SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, int32* length) +{ + if (!start || !length) + return; + *start = 0; + *length = text.Length(); +} + + +// #pragma mark - CompletionStyle + + +BAutoCompleter::CompletionStyle::CompletionStyle(EditView* editView, + ChoiceModel* choiceModel, ChoiceView* choiceView, + PatternSelector* patternSelector) + : + fEditView(editView), + fPatternSelector(patternSelector ? patternSelector + : new DefaultPatternSelector()), + fChoiceModel(choiceModel), + fChoiceView(choiceView) +{ +} + + +BAutoCompleter::CompletionStyle::~CompletionStyle() +{ + delete fEditView; + delete fChoiceModel; + delete fChoiceView; + delete fPatternSelector; +} + + +void +BAutoCompleter::CompletionStyle::SetEditView(EditView* view) +{ + delete fEditView; + fEditView = view; +} + + +void +BAutoCompleter::CompletionStyle::SetPatternSelector( + PatternSelector* selector) +{ + delete fPatternSelector; + fPatternSelector = selector; +} + + +void +BAutoCompleter::CompletionStyle::SetChoiceModel(ChoiceModel* model) +{ + delete fChoiceModel; + fChoiceModel = model; +} + + +void +BAutoCompleter::CompletionStyle::SetChoiceView(ChoiceView* view) +{ + delete fChoiceView; + fChoiceView = view; +} + + +// #pragma mark - BAutoCompleter + + +BAutoCompleter::BAutoCompleter(CompletionStyle* completionStyle) + : + fCompletionStyle(completionStyle) +{ +} + + +BAutoCompleter::BAutoCompleter(EditView* editView, ChoiceModel* choiceModel, + ChoiceView* choiceView, PatternSelector* patternSelector) + : + fCompletionStyle(new BDefaultCompletionStyle(editView, choiceModel, + choiceView, patternSelector)) +{ +} + + +BAutoCompleter::~BAutoCompleter() +{ + delete fCompletionStyle; +} + + +bool +BAutoCompleter::Select(int32 index) +{ + if (fCompletionStyle) + return fCompletionStyle->Select(index); + else + return false; +} + + +bool +BAutoCompleter::SelectNext(bool wrap) +{ + if (fCompletionStyle) + return fCompletionStyle->SelectNext(wrap); + else + return false; +} + + +bool +BAutoCompleter::SelectPrevious(bool wrap) +{ + if (fCompletionStyle) + return fCompletionStyle->SelectPrevious(wrap); + else + return false; +} + + +void +BAutoCompleter::ApplyChoice(bool hideChoices) +{ + if (fCompletionStyle) + fCompletionStyle->ApplyChoice(hideChoices); +} + + +void +BAutoCompleter::CancelChoice() +{ + if (fCompletionStyle) + fCompletionStyle->CancelChoice(); +} + + +void +BAutoCompleter::EditViewStateChanged() +{ + if (fCompletionStyle) + fCompletionStyle->EditViewStateChanged(); +} + + +void +BAutoCompleter::SetEditView(EditView* view) +{ + if (fCompletionStyle) + fCompletionStyle->SetEditView(view); +} + + +void +BAutoCompleter::SetPatternSelector(PatternSelector* selector) +{ + if (fCompletionStyle) + fCompletionStyle->SetPatternSelector(selector); +} + + +void +BAutoCompleter::SetChoiceModel(ChoiceModel* model) +{ + if (fCompletionStyle) + fCompletionStyle->SetChoiceModel(model); +} + + +void +BAutoCompleter::SetChoiceView(ChoiceView* view) +{ + if (fCompletionStyle) + fCompletionStyle->SetChoiceView(view); +} + + +void +BAutoCompleter::SetCompletionStyle(CompletionStyle* style) +{ + delete fCompletionStyle; + fCompletionStyle = style; +} diff --git a/src/apps/webpositive/autocompletion/AutoCompleter.h b/src/apps/webpositive/autocompletion/AutoCompleter.h new file mode 100644 index 0000000000..443981f809 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleter.h @@ -0,0 +1,154 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#ifndef AUTO_COMPLETEER_H +#define AUTO_COMPLETEER_H + +#include + +#include +#include + +class BAutoCompleter { +public: + class Choice { + public: + Choice(const BString& choiceText, + const BString& displayText, int32 matchPos, + int32 matchLen) + : + fText(choiceText), + fDisplayText(displayText), + fMatchPos(matchPos), + fMatchLen(matchLen) + { + } + virtual ~Choice() {} + const BString& Text() const { return fText; } + const BString& DisplayText() const { return fDisplayText; } + int32 MatchPos() const { return fMatchPos; } + int32 MatchLen() const { return fMatchLen; } + + private: + BString fText; + BString fDisplayText; + int32 fMatchPos; + int32 fMatchLen; + }; + + class EditView { + public: + virtual ~EditView() {} + + virtual BRect GetAdjustmentFrame() = 0; + virtual void GetEditViewState(BString& text, + int32* caretPos) = 0; + virtual void SetEditViewState(const BString& text, + int32 caretPos, + int32 selectionLength = 0) = 0; + }; + + class PatternSelector { + public: + virtual ~PatternSelector() {} + + virtual void SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, + int32* length) = 0; + }; + + class ChoiceModel { + public: + + virtual ~ChoiceModel() {} + + virtual void FetchChoicesFor(const BString& pattern) = 0; + + virtual int32 CountChoices() const = 0; + virtual const Choice* ChoiceAt(int32 index) const = 0; + }; + + class CompletionStyle; + class ChoiceView { + public: + virtual ~ChoiceView() {} + + virtual void SelectChoiceAt(int32 index) = 0; + virtual void ShowChoices( + BAutoCompleter::CompletionStyle* completer) + = 0; + virtual void HideChoices() = 0; + virtual bool ChoicesAreShown() = 0; + }; + + class CompletionStyle { + public: + CompletionStyle(EditView* editView, + ChoiceModel* choiceModel, + ChoiceView* choiceView, + PatternSelector* patternSelector); + virtual ~CompletionStyle(); + + virtual bool Select(int32 index) = 0; + virtual bool SelectNext(bool wrap = false) = 0; + virtual bool SelectPrevious(bool wrap = false) = 0; + + virtual void ApplyChoice(bool hideChoices = true) = 0; + virtual void CancelChoice() = 0; + + virtual void EditViewStateChanged() = 0; + + void SetEditView(EditView* view); + void SetPatternSelector(PatternSelector* selector); + void SetChoiceModel(ChoiceModel* model); + void SetChoiceView(ChoiceView* view); + + EditView* GetEditView() { return fEditView; } + PatternSelector* GetPatternSelector() + { return fPatternSelector; } + ChoiceModel* GetChoiceModel() { return fChoiceModel; } + ChoiceView* GetChoiceView() { return fChoiceView; } + + protected: + EditView* fEditView; + PatternSelector* fPatternSelector; + ChoiceModel* fChoiceModel; + ChoiceView* fChoiceView; + }; + +protected: + BAutoCompleter( + CompletionStyle* completionStyle = NULL); + BAutoCompleter(EditView* editView, + ChoiceModel* choiceModel, + ChoiceView* choiceView, + PatternSelector* patternSelector); + virtual ~BAutoCompleter(); + + void EditViewStateChanged(); + + bool Select(int32 index); + bool SelectNext(bool wrap = false); + bool SelectPrevious(bool wrap = false); + + void ApplyChoice(bool hideChoices = true); + void CancelChoice(); + + void SetEditView(EditView* view); + void SetPatternSelector(PatternSelector* selector); + void SetChoiceModel(ChoiceModel* model); + void SetChoiceView(ChoiceView* view); + + void SetCompletionStyle(CompletionStyle* style); + +private: + CompletionStyle* fCompletionStyle; +}; + + +#endif // AUTO_COMPLETEER_H diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp new file mode 100644 index 0000000000..456a56f127 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.cpp @@ -0,0 +1,377 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "AutoCompleterDefaultImpl.h" + +#include +#include +#include + + +// #pragma mark - BDefaultPatternSelector + +void +BDefaultPatternSelector::SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, int32* length) +{ + if (!start || !length) + return; + *start = 0; + *length = text.Length(); +} + + +// #pragma mark - BDefaultCompletionStyle + + +BDefaultCompletionStyle::BDefaultCompletionStyle( + BAutoCompleter::EditView* editView, + BAutoCompleter::ChoiceModel* choiceModel, + BAutoCompleter::ChoiceView* choiceView, + BAutoCompleter::PatternSelector* patternSelector) + : + CompletionStyle(editView, choiceModel, choiceView, patternSelector), + fSelectedIndex(-1), + fPatternStartPos(0), + fPatternLength(0) +{ +} + + +BDefaultCompletionStyle::~BDefaultCompletionStyle() +{ +} + + +bool +BDefaultCompletionStyle::Select(int32 index) +{ + if (!fChoiceView || !fChoiceModel || index == fSelectedIndex + || index < -1 || index >= fChoiceModel->CountChoices()) { + return false; + } + + fSelectedIndex = index; + fChoiceView->SelectChoiceAt(index); + return true; +} + + +bool +BDefaultCompletionStyle::SelectNext(bool wrap) +{ + if (!fChoiceModel || fChoiceModel->CountChoices() == 0) + return false; + + int32 newIndex = fSelectedIndex + 1; + if (newIndex >= fChoiceModel->CountChoices()) { + if (wrap) + newIndex = 0; + else + newIndex = fSelectedIndex; + } + return Select(newIndex); +} + + +bool +BDefaultCompletionStyle::SelectPrevious(bool wrap) +{ + if (!fChoiceModel || fChoiceModel->CountChoices() == 0) + return false; + + int32 newIndex = fSelectedIndex - 1; + if (newIndex < 0) { + if (wrap) + newIndex = fChoiceModel->CountChoices() - 1; + else + newIndex = 0; + } + return Select(newIndex); +} + + +void +BDefaultCompletionStyle::ApplyChoice(bool hideChoices) +{ + if (!fChoiceModel || !fChoiceView || !fEditView || fSelectedIndex < 0) + return; + + BString completedText(fFullEnteredText); + completedText.Remove(fPatternStartPos, fPatternLength); + const BString& choiceStr = fChoiceModel->ChoiceAt(fSelectedIndex)->Text(); + completedText.Insert(choiceStr, fPatternStartPos); + + fFullEnteredText = completedText; + fPatternLength = choiceStr.Length(); + fEditView->SetEditViewState(completedText, + fPatternStartPos+choiceStr.Length()); + + if (hideChoices) + fChoiceView->HideChoices(); +} + + +void +BDefaultCompletionStyle::CancelChoice() +{ + if (!fChoiceView || !fEditView) + return; + if (fChoiceView->ChoicesAreShown()) { + fEditView->SetEditViewState(fFullEnteredText, + fPatternStartPos+fPatternLength); + fChoiceView->HideChoices(); + Select(-1); + } +} + +void +BDefaultCompletionStyle::EditViewStateChanged() +{ + if (!fChoiceModel || !fChoiceView || !fEditView) + return; + + BString text; + int32 caretPos; + fEditView->GetEditViewState(text, &caretPos); + if (fFullEnteredText == text) + return; + fFullEnteredText = text; + fPatternSelector->SelectPatternBounds(text, caretPos, &fPatternStartPos, + &fPatternLength); + BString pattern(text.String() + fPatternStartPos, fPatternLength); + fChoiceModel->FetchChoicesFor(pattern); + + Select(-1); + // show a single choice only if it doesn't match the pattern exactly: + if (fChoiceModel->CountChoices() > 1 || (fChoiceModel->CountChoices() == 1 + && pattern.ICompare(fChoiceModel->ChoiceAt(0)->Text())) != 0) { + fChoiceView->ShowChoices(this); + fChoiceView->SelectChoiceAt(fSelectedIndex); + } else + fChoiceView->HideChoices(); +} + + +// #pragma mark - BDefaultChoiceView::ListView + + +static const int32 BM_INVOKED = 'bmin'; + + +BDefaultChoiceView::ListView::ListView( + BAutoCompleter::CompletionStyle* completer) + : + BListView(BRect(0,0,100,100), "ChoiceViewList"), + fCompleter(completer) +{ + // we need to check if user clicks outside of window-bounds: + SetEventMask(B_POINTER_EVENTS); +} + + +void +BDefaultChoiceView::ListView::AttachedToWindow() +{ + SetTarget(this); + SetInvocationMessage(new BMessage(BM_INVOKED)); + BListView::AttachedToWindow(); +} + + +void +BDefaultChoiceView::ListView::SelectionChanged() +{ + fCompleter->Select(CurrentSelection(0)); +} + + +void +BDefaultChoiceView::ListView::MessageReceived(BMessage* message) +{ + switch(message->what) { + case BM_INVOKED: + fCompleter->ApplyChoice(); + break; + default: + BListView::MessageReceived(message); + } +} + + +void +BDefaultChoiceView::ListView::MouseDown(BPoint point) +{ + if (!Window()->Frame().Contains(ConvertToScreen(point))) + // click outside of window, so we close it: + Window()->Quit(); + else + BListView::MouseDown(point); +} + + +// #pragma mark - BDefaultChoiceView::ListItem + + +BDefaultChoiceView::ListItem::ListItem(const BAutoCompleter::Choice* choice) + : + BListItem() +{ + fPreText = choice->DisplayText(); + if (choice->MatchLen() > 0) { + fPreText.MoveInto(fMatchText, choice->MatchPos(), choice->MatchLen()); + fPreText.MoveInto(fPostText, choice->MatchPos(), fPreText.Length()); + } +} + + +void +BDefaultChoiceView::ListItem::DrawItem(BView* owner, BRect frame, + bool complete) +{ + rgb_color textCol, backCol, matchCol; + if (IsSelected()) { + textCol = ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR); + backCol = ui_color(B_MENU_SELECTED_BACKGROUND_COLOR); + } else { + textCol = ui_color(B_DOCUMENT_TEXT_COLOR); + backCol = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + } + matchCol = tint_color(backCol, B_LIGHTEN_2_TINT); + + BFont font; + font_height fontHeight; + owner->GetFont(&font); + font.GetHeight(&fontHeight); + float xPos = frame.left + 1; + float yPos = frame.top + fontHeight.ascent; + float w; + if (fPreText.Length()) { + w = owner->StringWidth(fPreText.String()); + owner->SetLowColor(backCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->SetHighColor(textCol); + owner->DrawString(fPreText.String(), BPoint(xPos, yPos)); + xPos += w; + } + if (fMatchText.Length()) { + w = owner->StringWidth(fMatchText.String()); + owner->SetLowColor(matchCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->DrawString(fMatchText.String(), BPoint(xPos, yPos)); + xPos += w; + } + if (fPostText.Length()) { + w = owner->StringWidth(fPostText.String()); + owner->SetLowColor(backCol); + owner->FillRect(BRect(xPos, frame.top, xPos + w - 1, frame.bottom), + B_SOLID_LOW); + owner->DrawString(fPostText.String(), BPoint(xPos, yPos)); + } +} + + +// #pragma mark - BDefaultChoiceView + + +BDefaultChoiceView::BDefaultChoiceView() + : + fWindow(NULL), + fListView(NULL) +{ + +} + + +BDefaultChoiceView::~BDefaultChoiceView() +{ + HideChoices(); +} + + +void +BDefaultChoiceView::SelectChoiceAt(int32 index) +{ + if (fListView && fListView->LockLooper()) { + if (index < 0) + fListView->DeselectAll(); + else { + fListView->Select(index); + fListView->ScrollToSelection(); + } + fListView->UnlockLooper(); + } +} + + +void +BDefaultChoiceView::ShowChoices(BAutoCompleter::CompletionStyle* completer) +{ + if (!completer) + return; + + HideChoices(); + + BAutoCompleter::ChoiceModel* choiceModel = completer->GetChoiceModel(); + BAutoCompleter::EditView* editView = completer->GetEditView(); + + if (!editView || !choiceModel || choiceModel->CountChoices() == 0) + return; + + fListView = new ListView(completer); + int32 count = choiceModel->CountChoices(); + for(int32 i=0; iAddItem( + new ListItem(choiceModel->ChoiceAt(i)) + ); + } + + fWindow = new BWindow(BRect(0, 0, 100, 100), "", B_BORDERED_WINDOW_LOOK, + B_NORMAL_WINDOW_FEEL, B_NOT_MOVABLE | B_WILL_ACCEPT_FIRST_CLICK + | B_AVOID_FOCUS | B_ASYNCHRONOUS_CONTROLS); + fWindow->AddChild(fListView); + + int32 visibleCount = min_c(count, 5); + float listHeight = fListView->ItemFrame(visibleCount - 1).bottom + 1; + + BRect pvRect = editView->GetAdjustmentFrame(); + BRect listRect = pvRect; + listRect.bottom = listRect.top + listHeight - 1; + BRect screenRect = BScreen().Frame(); + if (listRect.bottom + 1 + listHeight <= screenRect.bottom) + listRect.OffsetTo(pvRect.left, pvRect.bottom + 1); + else + listRect.OffsetTo(pvRect.left, pvRect.top - listHeight); + + fListView->MoveTo(0, 0); + fListView->ResizeTo(listRect.Width(), listRect.Height()); + fWindow->MoveTo(listRect.left, listRect.top); + fWindow->ResizeTo(listRect.Width(), listRect.Height()); + fWindow->Show(); +} + + +void +BDefaultChoiceView::HideChoices() +{ + if (fWindow && fWindow->Lock()) { + fWindow->Quit(); + fWindow = NULL; + fListView = NULL; + } +} + + +bool +BDefaultChoiceView::ChoicesAreShown() +{ + return (fWindow != NULL); +} + diff --git a/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h new file mode 100644 index 0000000000..f697330915 --- /dev/null +++ b/src/apps/webpositive/autocompletion/AutoCompleterDefaultImpl.h @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#ifndef AUTO_COMPLETER_DEFAULT_IMPL_H +#define AUTO_COMPLETER_DEFAULT_IMPL_H + +#include +#include + +#include "AutoCompleter.h" + +class BDefaultPatternSelector : public BAutoCompleter::PatternSelector { +public: + virtual void SelectPatternBounds(const BString& text, + int32 caretPos, int32* start, + int32* length); +}; + + +class BDefaultCompletionStyle : public BAutoCompleter::CompletionStyle { +public: + BDefaultCompletionStyle( + BAutoCompleter::EditView* editView, + BAutoCompleter::ChoiceModel* choiceModel, + BAutoCompleter::ChoiceView* choiceView, + BAutoCompleter::PatternSelector* + patternSelector); + virtual ~BDefaultCompletionStyle(); + + virtual bool Select(int32 index); + virtual bool SelectNext(bool wrap = false); + virtual bool SelectPrevious(bool wrap = false); + + virtual void ApplyChoice(bool hideChoices = true); + virtual void CancelChoice(); + + virtual void EditViewStateChanged(); + +private: + BString fFullEnteredText; + int32 fSelectedIndex; + int32 fPatternStartPos; + int32 fPatternLength; +}; + + +class BDefaultChoiceView : public BAutoCompleter::ChoiceView { +protected: + class ListView : public BListView { + public: + ListView( + BAutoCompleter::CompletionStyle* completer); + virtual void SelectionChanged(); + virtual void MessageReceived(BMessage* msg); + virtual void MouseDown(BPoint point); + virtual void AttachedToWindow(); + private: + BAutoCompleter::CompletionStyle* fCompleter; + }; + + class ListItem : public BListItem { + public: + ListItem(const BAutoCompleter::Choice* choice); + virtual void DrawItem(BView* owner, BRect frame, + bool complete = false); + private: + BString fPreText; + BString fMatchText; + BString fPostText; + }; + +public: + BDefaultChoiceView(); + virtual ~BDefaultChoiceView(); + + virtual void SelectChoiceAt(int32 index); + virtual void ShowChoices( + BAutoCompleter::CompletionStyle* completer); + virtual void HideChoices(); + virtual bool ChoicesAreShown(); + +private: + BWindow* fWindow; + ListView* fListView; +}; + +#endif // AUTO_COMPLETER_DEFAULT_IMPL_H diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.cpp b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp new file mode 100644 index 0000000000..e8e9cb0f52 --- /dev/null +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.cpp @@ -0,0 +1,118 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ + +#include "TextControlCompleter.h" + +#include +#include + +#include "AutoCompleterDefaultImpl.h" + + +// #pragma mark - TextControlWrapper + + +TextControlCompleter::TextControlWrapper::TextControlWrapper( + BTextControl* textControl) + : + fTextControl(textControl) +{ +} + + +void +TextControlCompleter::TextControlWrapper::GetEditViewState(BString& text, + int32* caretPos) +{ + if (fTextControl && fTextControl->LockLooper()) { + text = fTextControl->Text(); + if (caretPos) { + int32 end; + fTextControl->TextView()->GetSelection(caretPos, &end); + } + fTextControl->UnlockLooper(); + } +} + + +void +TextControlCompleter::TextControlWrapper::SetEditViewState(const BString& text, + int32 caretPos, int32 selectionLength) +{ + if (fTextControl && fTextControl->LockLooper()) { + fTextControl->TextView()->SetText(text.String(), text.Length()); + fTextControl->TextView()->Select(caretPos, caretPos + selectionLength); + fTextControl->TextView()->ScrollToSelection(); + fTextControl->UnlockLooper(); + } +} + + +BRect +TextControlCompleter::TextControlWrapper::GetAdjustmentFrame() +{ + BRect frame = fTextControl->TextView()->Bounds(); + frame = fTextControl->TextView()->ConvertToScreen(frame); + frame.InsetBy(-1, -3); + return frame; +} + + +TextControlCompleter::TextControlCompleter(BTextControl* textControl, + ChoiceModel* model, PatternSelector* patternSelector) + : + BAutoCompleter(new TextControlWrapper(textControl), model, + new BDefaultChoiceView(), patternSelector), + BMessageFilter(B_KEY_DOWN) +{ + textControl->TextView()->AddFilter(this); +} + + +TextControlCompleter::~TextControlCompleter() +{ +} + + +filter_result +TextControlCompleter::Filter(BMessage* message, BHandler** target) +{ + int32 rawChar, modifiers; + if (!target || message->FindInt32("raw_char", &rawChar) != B_OK + || message->FindInt32("modifiers", &modifiers) != B_OK) { + return B_DISPATCH_MESSAGE; + } + + switch (rawChar) { + case B_UP_ARROW: + SelectPrevious(); + return B_SKIP_MESSAGE; + case B_DOWN_ARROW: + SelectNext(); + return B_SKIP_MESSAGE; + case B_ESCAPE: + CancelChoice(); + return B_SKIP_MESSAGE; + case B_RETURN: + ApplyChoice(); + EditViewStateChanged(); + return B_SKIP_MESSAGE; + case B_TAB: { + // make sure that the choices-view is closed when tabbing out: + CancelChoice(); + 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; + } + return B_DISPATCH_MESSAGE; +} diff --git a/src/apps/webpositive/autocompletion/TextControlCompleter.h b/src/apps/webpositive/autocompletion/TextControlCompleter.h new file mode 100644 index 0000000000..66ae3558c3 --- /dev/null +++ b/src/apps/webpositive/autocompletion/TextControlCompleter.h @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). + * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Oliver Tappe + */ +#ifndef TEXT_CONTROL_COMPLETER_H +#define TEXT_CONTROL_COMPLETER_H + +#include + +#include "AutoCompleter.h" + + +class BTextControl; + +class TextControlCompleter : protected BAutoCompleter, public BMessageFilter { +public: + TextControlCompleter(BTextControl* textControl, + ChoiceModel* choiceModel = NULL, + PatternSelector* patternSelector = NULL); + virtual ~TextControlCompleter(); + +private: + virtual filter_result Filter(BMessage* message, BHandler** target); + + class TextControlWrapper : public EditView { + public: + TextControlWrapper(BTextControl* textControl); + virtual BRect GetAdjustmentFrame(); + virtual void GetEditViewState(BString& text, + int32* caretPos); + virtual void SetEditViewState(const BString& text, + int32 caretPos, int32 selectionLength = 0); + private: + BTextControl* fTextControl; + }; +}; + +#endif // TEXT_CONTROL_COMPLETER_H