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 21 TextViewCompleter::TextViewWrapper::TextViewWrapper(BTextView* textView) 22 : 23 fTextView(textView) 24 { 25 } 26 27 28 void 29 TextViewCompleter::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 43 void 44 TextViewCompleter::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 56 BRect 57 TextViewCompleter::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 69 TextViewCompleter::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 82 TextViewCompleter::~TextViewCompleter() 83 { 84 fTextView->RemoveFilter(this); 85 } 86 87 88 void 89 TextViewCompleter::SetModificationsReported(bool reported) 90 { 91 fModificationsReported = reported; 92 } 93 94 95 void 96 TextViewCompleter::TextModified(bool updateChoices) 97 { 98 EditViewStateChanged(updateChoices); 99 } 100 101 102 filter_result 103 TextViewCompleter::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