1/*
2 * Copyright 2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan Aßmus <superstippi@gmx.de>
7 */
8
9#include "NummericalTextView.h"
10
11#include <stdio.h>
12#include <stdlib.h>
13
14#include <String.h>
15
16// constructor
17NummericalTextView::NummericalTextView(BRect frame, const char* name,
18									   BRect textRect,
19									   uint32 resizingMode,
20									   uint32 flags)
21	: InputTextView(frame, name, textRect, resizingMode, flags)
22{
23	for (uint32 i = 0; i < '0'; i++) {
24		DisallowChar(i);
25	}
26	for (uint32 i = '9' + 1; i < 255; i++) {
27		DisallowChar(i);
28	}
29	AllowChar('-');
30}
31
32// destructor
33NummericalTextView::~NummericalTextView()
34{
35}
36
37// Invoke
38status_t
39NummericalTextView::Invoke(BMessage* message)
40{
41	if (!message)
42		message = Message();
43
44	if (message) {
45		BMessage copy(*message);
46		copy.AddInt32("be:value", IntValue());
47		copy.AddFloat("float value", FloatValue());
48		return InputTextView::Invoke(&copy);
49	}
50	return B_BAD_VALUE;
51}
52
53// RevertChanges
54void
55NummericalTextView::RevertChanges()
56{
57	if (fFloatMode)
58		SetValue(fFloatValueCache);
59	else
60		SetValue(fIntValueCache);
61}
62
63// ApplyChanges
64void
65NummericalTextView::ApplyChanges()
66{
67	int32 i = atoi(Text());
68	float f = atof(Text());
69
70	if ((fFloatMode && f != fFloatValueCache) ||
71		(!fFloatMode && i != fIntValueCache)) {
72		Invoke();
73	}
74}
75
76// SetFloatMode
77void
78NummericalTextView::SetFloatMode(bool floatingPoint)
79{
80	fFloatMode = floatingPoint;
81	if (floatingPoint)
82		AllowChar('.');
83	else
84		DisallowChar('.');
85}
86
87// SetValue
88void
89NummericalTextView::SetValue(int32 value)
90{
91	BString helper;
92	helper << value;
93	SetText(helper.String());
94
95	// update caches
96	IntValue();
97	FloatValue();
98
99	if (IsFocus())
100		SelectAll();
101}
102
103// SetValue
104void
105NummericalTextView::SetValue(float value)
106{
107	BString helper;
108	helper << value;
109	SetText(helper.String());
110
111	// update caches
112	IntValue();
113	FloatValue();
114
115	if (IsFocus())
116		SelectAll();
117}
118
119// IntValue
120int32
121NummericalTextView::IntValue() const
122{
123	fIntValueCache = atoi(Text());
124	return fIntValueCache;
125}
126
127// FloatValue
128float
129NummericalTextView::FloatValue() const
130{
131	fFloatValueCache = atof(Text());
132	return fFloatValueCache;
133}
134
135// #pragma mark -
136
137// Select
138void
139NummericalTextView::Select(int32 start, int32 finish)
140{
141	InputTextView::Select(start, finish);
142
143	_CheckMinusAllowed();
144	_CheckDotAllowed();
145}
146
147// InsertText
148void
149NummericalTextView::InsertText(const char* inText, int32 inLength, int32 inOffset,
150							   const text_run_array* inRuns)
151{
152	InputTextView::InsertText(inText, inLength, inOffset, inRuns);
153
154	_CheckMinusAllowed();
155	_CheckDotAllowed();
156}
157
158// DeleteText
159void
160NummericalTextView::DeleteText(int32 fromOffset, int32 toOffset)
161{
162	InputTextView::DeleteText(fromOffset, toOffset);
163
164	_CheckMinusAllowed();
165	_CheckDotAllowed();
166}
167
168// #pragma mark -
169
170// _ToggleAllowChar
171void
172NummericalTextView::_ToggleAllowChar(char c)
173{
174	const char* text = Text();
175	if (text) {
176		bool found = false;
177		int32 selectionStart;
178		int32 selectionEnd;
179		GetSelection(&selectionStart, &selectionEnd);
180		int32 pos = 0;
181		while (text[pos]) {
182			// skip selection
183			if (selectionStart < selectionEnd
184				&& pos == selectionStart) {
185				pos = selectionEnd;
186			}
187			if (text[pos] == c) {
188				found = true;
189				break;
190			}
191			pos++;
192		}
193		if (found)
194			DisallowChar(c);
195		else
196			AllowChar(c);
197	}
198}
199
200// _CheckMinusAllowed
201void
202NummericalTextView::_CheckMinusAllowed()
203{
204	_ToggleAllowChar('-');
205}
206
207// _CheckDotAllowed
208void
209NummericalTextView::_CheckDotAllowed()
210{
211	if (fFloatMode) {
212		_ToggleAllowChar('.');
213	}
214}
215
216
217
218
219