1/* 2 * Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam). 3 * All rights reserved. Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Oliver Tappe <beam@hirschkaefer.de> 7 */ 8 9#include "TextViewCompleter.h" 10 11#include <Looper.h> 12#include <TextControl.h> 13#include <stdio.h> 14 15#include "AutoCompleterDefaultImpl.h" 16 17 18// #pragma mark - TextViewWrapper 19 20 21TextViewCompleter::TextViewWrapper::TextViewWrapper(BTextView* textView) 22 : 23 fTextView(textView) 24{ 25} 26 27 28void 29TextViewCompleter::TextViewWrapper::GetEditViewState(BString& text, 30 int32* caretPos) 31{ 32 if (fTextView && fTextView->LockLooper()) { 33 text = fTextView->Text(); 34 if (caretPos) { 35 int32 end; 36 fTextView->GetSelection(caretPos, &end); 37 } 38 fTextView->UnlockLooper(); 39 } 40} 41 42 43void 44TextViewCompleter::TextViewWrapper::SetEditViewState(const BString& text, 45 int32 caretPos, int32 selectionLength) 46{ 47 if (fTextView && fTextView->LockLooper()) { 48 fTextView->SetText(text.String(), text.Length()); 49 fTextView->Select(caretPos, caretPos + selectionLength); 50 fTextView->ScrollToSelection(); 51 fTextView->UnlockLooper(); 52 } 53} 54 55 56BRect 57TextViewCompleter::TextViewWrapper::GetAdjustmentFrame() 58{ 59 BRect frame = fTextView->Bounds(); 60 frame = fTextView->ConvertToScreen(frame); 61 frame.InsetBy(0, -3); 62 return frame; 63} 64 65 66// #pragma mark - 67 68 69TextViewCompleter::TextViewCompleter(BTextView* textView, ChoiceModel* model, 70 PatternSelector* patternSelector) 71 : 72 BAutoCompleter(new TextViewWrapper(textView), model, 73 new BDefaultChoiceView(), patternSelector), 74 BMessageFilter(B_KEY_DOWN), 75 fTextView(textView), 76 fModificationsReported(false) 77{ 78 fTextView->AddFilter(this); 79} 80 81 82TextViewCompleter::~TextViewCompleter() 83{ 84 fTextView->RemoveFilter(this); 85} 86 87 88void 89TextViewCompleter::SetModificationsReported(bool reported) 90{ 91 fModificationsReported = reported; 92} 93 94 95void 96TextViewCompleter::TextModified(bool updateChoices) 97{ 98 EditViewStateChanged(updateChoices); 99} 100 101 102filter_result 103TextViewCompleter::Filter(BMessage* message, BHandler** target) 104{ 105 const char* bytes; 106 int32 modifiers; 107 if ((!target || message->FindString("bytes", &bytes) != B_OK 108 || message->FindInt32("modifiers", &modifiers) != B_OK) 109 || (modifiers & (B_CONTROL_KEY | B_COMMAND_KEY | B_OPTION_KEY 110 | B_SHIFT_KEY)) != 0) { 111 return B_DISPATCH_MESSAGE; 112 } 113 114 switch (bytes[0]) { 115 case B_UP_ARROW: 116 SelectPrevious(); 117 // Insert the current choice into the text view, so the user can 118 // continue typing. This will not trigger another evaluation, since 119 // we don't invoke EditViewStateChanged(). 120 ApplyChoice(false); 121 return B_SKIP_MESSAGE; 122 case B_DOWN_ARROW: 123 SelectNext(); 124 // See above. 125 ApplyChoice(false); 126 return B_SKIP_MESSAGE; 127 case B_PAGE_UP: 128 { 129 int32 index = SelectedChoiceIndex() - CountVisibleChoices(); 130 index = max_c(index, 0); 131 Select(index); 132 ApplyChoice(false); 133 return B_SKIP_MESSAGE; 134 } 135 case B_PAGE_DOWN: 136 { 137 int32 index = SelectedChoiceIndex() + CountVisibleChoices(); 138 index = min_c(index, CountChoices() - 1); 139 Select(index); 140 ApplyChoice(false); 141 return B_SKIP_MESSAGE; 142 } 143 144 case B_ESCAPE: 145 CancelChoice(); 146 return B_DISPATCH_MESSAGE; 147 case B_RETURN: 148 if (IsChoiceSelected()) { 149 ApplyChoice(); 150 EditViewStateChanged(); 151 } else 152 CancelChoice(); 153 return B_DISPATCH_MESSAGE; 154 case B_TAB: { 155 // make sure that the choices-view is closed when tabbing out: 156 CancelChoice(); 157 return B_DISPATCH_MESSAGE; 158 } 159 default: 160 if (!fModificationsReported) { 161 // dispatch message to textview manually... 162 Looper()->DispatchMessage(message, *target); 163 // ...and propagate the new state to the auto-completer: 164 EditViewStateChanged(); 165 return B_SKIP_MESSAGE; 166 } 167 return B_DISPATCH_MESSAGE; 168 } 169} 170