1/*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions, and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions, and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * 3. The name of the author may not be used to endorse or promote products
17 *    derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32// ValControlSegment.cpp
33// e.moon 20jan99
34
35
36#include "ValControlSegment.h"
37#include "ValControl.h"
38
39#include <Debug.h>
40
41#include <cstdio>
42
43__USE_CORTEX_NAMESPACE
44
45
46ValControlSegment::ValControlSegment(underline_style underlineStyle)
47	:BView(BRect(), "ValControlSegment", B_FOLLOW_LEFT|B_FOLLOW_TOP,
48		B_WILL_DRAW|B_FRAME_EVENTS),
49	fDragScaleFactor(fDefDragScaleFactor),
50	fLastClickTime(0LL),
51	fUnderlineStyle(underlineStyle),
52	fXUnderlineLeft(0.0),
53	fXUnderlineRight(0.0)
54{
55	_Init();
56}
57
58
59ValControlSegment::~ValControlSegment()
60{
61}
62
63
64void
65ValControlSegment::_Init()
66{
67	//m_pLeft = 0;
68}
69
70
71const double ValControlSegment::fDefDragScaleFactor = 4;
72
73
74// get parent
75ValControl*
76ValControlSegment::parent() const
77{
78	return dynamic_cast<ValControl*>(Parent());
79}
80
81
82//
83//// send message -> segment to my left
84//void ValControlSegment::sendMessageLeft(BMessage* pMsg) {
85//	if(!m_pLeft)
86//		return;
87//	BMessenger m(m_pLeft);
88//	if(!m.IsValid())
89//		return;
90//	m.SendMessage(pMsg);
91//	delete pMsg;
92//}
93
94
95// init mouse tracking
96void
97ValControlSegment::trackMouse(BPoint point, track_flags flags)
98{
99	fTrackFlags = flags;
100	fPrevPoint = point;
101	setTracking(true);
102	SetMouseEventMask(B_POINTER_EVENTS,
103		B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
104}
105
106
107void
108ValControlSegment::setTracking(bool tracking)
109{
110	fTracking = tracking;
111}
112
113
114bool
115ValControlSegment::isTracking() const
116{
117	return fTracking;
118}
119
120
121double
122ValControlSegment::dragScaleFactor() const
123{
124	return fDragScaleFactor;
125}
126
127
128// -------------------------------------------------------- //
129// default hook implementations
130// -------------------------------------------------------- //
131
132void
133ValControlSegment::sizeUnderline(float* outLeft, float* outRight)
134{
135	*outLeft = 0.0;
136	*outRight = Bounds().right;
137}
138
139
140void
141ValControlSegment::AttachedToWindow()
142{
143//	if(parent()->backBuffer())
144//		SetViewColor(B_TRANSPARENT_COLOR);
145
146	// adopt parent's view color
147	SetViewColor(parent()->ViewColor());
148}
149
150
151void
152ValControlSegment::Draw(BRect updateRect)
153{
154	if (fUnderlineStyle == NO_UNDERLINE)
155		return;
156
157	// +++++ move to layout function
158	float fY = parent()->baselineOffset() + 1;
159
160	rgb_color white = {255,255,255,255};
161	rgb_color blue = {0,0,255,255};
162	rgb_color gray = {140,140,140,255};
163	rgb_color old = HighColor();
164
165	SetLowColor(white);
166	if(parent()->IsEnabled() && parent()->IsFocus())
167		SetHighColor(blue);
168	else
169		SetHighColor(gray);
170
171	if (fXUnderlineRight <= fXUnderlineLeft)
172		sizeUnderline(&fXUnderlineLeft, &fXUnderlineRight);
173
174//	PRINT((
175//		"### ValControlSegment::Draw(): underline spans %.1f, %.1f\n",
176//		fXUnderlineLeft, fXUnderlineRight));
177//
178	StrokeLine(BPoint(fXUnderlineLeft, fY),
179		BPoint(fXUnderlineRight, fY),
180		(fUnderlineStyle == DOTTED_UNDERLINE) ? B_MIXED_COLORS :
181			B_SOLID_HIGH);
182	SetHighColor(old);
183}
184
185
186void
187ValControlSegment::FrameResized(float width, float height)
188{
189	_Inherited::FrameResized(width, height);
190
191//	PRINT((
192//		"### ValControlSegment::FrameResized(%.1f,%.1f)\n",
193//		fWidth, fHeight));
194	sizeUnderline(&fXUnderlineLeft, &fXUnderlineRight);
195}
196
197
198void
199ValControlSegment::MouseDown(BPoint point)
200{
201	if (!parent()->IsEnabled())
202		return;
203
204	parent()->MakeFocus();
205
206	// not left button?
207	uint32 nButton;
208	GetMouse(&point, &nButton);
209	if (!(nButton & B_PRIMARY_MOUSE_BUTTON))
210		return;
211
212	// double click?
213	bigtime_t doubleClickInterval;
214	if (get_click_speed(&doubleClickInterval) < B_OK) {
215		PRINT(("* ValControlSegment::MouseDown():\n"
216			"  get_click_speed() failed."));
217		return;
218	}
219
220	bigtime_t now = system_time();
221	if (now - fLastClickTime < doubleClickInterval) {
222		if(isTracking()) {
223			setTracking(false);
224			mouseReleased();
225		}
226
227		// hand off to parent control
228		parent()->showEditField();
229		fLastClickTime = 0LL;
230		return;
231	}
232	else
233		fLastClickTime = now;
234
235
236	// engage tracking
237	trackMouse(point, TRACK_VERTICAL);
238}
239
240
241void
242ValControlSegment::MouseMoved(BPoint point, uint32 transit,
243	const BMessage* dragMessage)
244{
245	if (!parent()->IsEnabled())
246		return;
247
248	if (!isTracking() || fPrevPoint == point)
249		return;
250
251	// float fXDelta = fTrackFlags & TRACK_HORIZONTAL ?
252	// point.x - fPrevPoint.x : 0.0;
253	float fYDelta = fTrackFlags & TRACK_VERTICAL ?
254		point.y - fPrevPoint.y : 0.0;
255
256	// printf("MouseMoved(): %2f,%2f\n",
257	// fXDelta, fYDelta);
258
259
260	// hand off
261	// +++++ config'able x/y response would be nice...
262	float fRemaining = handleDragUpdate(fYDelta);
263
264	fPrevPoint = point;
265	fPrevPoint.y -= fRemaining;
266}
267
268
269void
270ValControlSegment::MouseUp(BPoint point)
271{
272	if (isTracking()) {
273		setTracking(false);
274		mouseReleased();
275	}
276}
277
278
279void
280ValControlSegment::MessageReceived(BMessage* message)
281{
282	switch(message->what) {
283		default:
284			_Inherited::MessageReceived(message);
285	}
286}
287
288
289// -------------------------------------------------------- //
290// archiving/instantiation
291// -------------------------------------------------------- //
292
293ValControlSegment::ValControlSegment(BMessage* archive)
294	: BView(archive)
295{
296	_Init();
297	archive->FindInt32("ulStyle", (int32*)&fUnderlineStyle);
298}
299
300
301status_t
302ValControlSegment::Archive(BMessage* archive, bool deep) const
303{
304	_Inherited::Archive(archive, deep);
305
306	archive->AddInt32("ulStyle", fUnderlineStyle);
307	return B_OK;
308}
309