1 /* 2 * Copyright 2006-2009, Stephan Aßmus <superstippi@gmx.de>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 #include "InputTextView.h" 7 8 #include <stdio.h> 9 #include <stdlib.h> 10 11 #include <String.h> 12 13 // constructor 14 InputTextView::InputTextView(BRect frame, const char* name, 15 BRect textRect, 16 uint32 resizingMode, 17 uint32 flags) 18 : BTextView(frame, name, textRect, resizingMode, flags), 19 fWasFocus(false) 20 { 21 SetWordWrap(false); 22 } 23 24 // destructor 25 InputTextView::~InputTextView() 26 { 27 } 28 29 // MouseDown 30 void 31 InputTextView::MouseDown(BPoint where) 32 { 33 // enforce the behaviour of a typical BTextControl 34 // only let the BTextView handle mouse up/down when 35 // it already had focus 36 fWasFocus = IsFocus(); 37 if (fWasFocus) { 38 BTextView::MouseDown(where); 39 } else { 40 // forward click 41 if (BView* view = Parent()) { 42 view->MouseDown(ConvertToParent(where)); 43 } 44 } 45 } 46 47 // MouseUp 48 void 49 InputTextView::MouseUp(BPoint where) 50 { 51 // enforce the behaviour of a typical BTextControl 52 // only let the BTextView handle mouse up/down when 53 // it already had focus 54 if (fWasFocus) 55 BTextView::MouseUp(where); 56 } 57 58 // KeyDown 59 void 60 InputTextView::KeyDown(const char* bytes, int32 numBytes) 61 { 62 bool handled = true; 63 if (numBytes > 0) { 64 switch (bytes[0]) { 65 case B_ESCAPE: 66 // revert any typing changes 67 RevertChanges(); 68 fTextBeforeFocus = Text(); 69 break; 70 case B_RETURN: 71 ApplyChanges(); 72 fTextBeforeFocus = Text(); 73 break; 74 default: 75 handled = false; 76 break; 77 } 78 } 79 if (!handled) 80 BTextView::KeyDown(bytes, numBytes); 81 } 82 83 // MakeFocus 84 void 85 InputTextView::MakeFocus(bool focus) 86 { 87 if (focus == IsFocus()) 88 return; 89 90 if (BView* view = Parent()) 91 view->Invalidate(); 92 BTextView::MakeFocus(focus); 93 if (focus) { 94 SelectAll(); 95 fTextBeforeFocus = Text(); 96 } else { 97 // Only pressing ESC is supposed to revert to the previous 98 // value and not invoke, but in that case, the text will already 99 // be the previous value when we lose focus here. 100 if (fTextBeforeFocus != Text()) 101 Invoke(); 102 } 103 } 104 105 // Invoke 106 status_t 107 InputTextView::Invoke(BMessage* message) 108 { 109 if (!message) 110 message = Message(); 111 112 if (message) { 113 BMessage copy(*message); 114 copy.AddInt64("when", system_time()); 115 copy.AddPointer("source", (BView*)this); 116 return BInvoker::Invoke(©); 117 } 118 return B_BAD_VALUE; 119 } 120 121 // #pragma mark - 122 123 // Select 124 void 125 InputTextView::Select(int32 start, int32 finish) 126 { 127 BTextView::Select(start, finish); 128 129 _CheckTextRect(); 130 } 131 132 // InsertText 133 void 134 InputTextView::InsertText(const char* inText, int32 inLength, int32 inOffset, 135 const text_run_array* inRuns) 136 { 137 BTextView::InsertText(inText, inLength, inOffset, inRuns); 138 139 _CheckTextRect(); 140 } 141 142 // DeleteText 143 void 144 InputTextView::DeleteText(int32 fromOffset, int32 toOffset) 145 { 146 BTextView::DeleteText(fromOffset, toOffset); 147 148 _CheckTextRect(); 149 } 150 151 // #pragma mark - 152 153 // _CheckTextRect 154 void 155 InputTextView::_CheckTextRect() 156 { 157 // update text rect and make sure 158 // the cursor/selection is in view 159 BRect textRect(TextRect()); 160 float width = ceilf(StringWidth(Text()) + 2.0); 161 if (textRect.Width() != width) { 162 textRect.right = textRect.left + width; 163 SetTextRect(textRect); 164 ScrollToSelection(); 165 } 166 } 167