xref: /haiku/src/apps/icon-o-matic/generic/gui/InputTextView.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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(&copy);
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