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// TipManagerImpl.h
33// e.moon 13may99
34//
35// HISTORY
36//   13may99	e.moon		moved TipManager internals here
37
38#ifndef __TIPMANAGERIMPL_H__
39#define __TIPMANAGERIMPL_H__
40
41#include <set>
42#include <list>
43#include <utility>
44
45#include <Debug.h>
46#include <SupportDefs.h>
47#include <Font.h>
48#include <Point.h>
49#include <Rect.h>
50#include <GraphicsDefs.h>
51#include <String.h>
52#include <View.h>
53
54class BWindow;
55class BMessageRunner;
56
57#include "cortex_defs.h"
58__BEGIN_CORTEX_NAMESPACE
59
60// -------------------------------------------------------- //
61// tip_entry
62// -------------------------------------------------------- //
63
64class tip_entry {
65public:													// *** interface
66	// if rect is invalid, the entry represents the view's entire
67	// frame area
68	tip_entry(
69		BRect												_rect,
70		const char*									_text,
71		TipManager::offset_mode_t		_offsetMode,
72		BPoint											_offset,
73		uint32											_flags) :
74
75		rect(_rect),
76		text(_text),
77		offsetMode(_offsetMode),
78		offset(_offset),
79		flags(_flags) {}
80
81	// useful for comparisons
82	tip_entry(
83		BRect												_rect) :
84		rect(_rect) {}
85
86	// give the compiler some slack:
87	tip_entry() {}
88
89	void dump(int indent) {
90		BString s;
91		s.SetTo('\t', indent);
92		PRINT((
93			"%stip_entry '%s'\n",
94			s.String(),
95			text.String()));
96	}
97
98	// +++++ copy ctors and other treats for lame compilers go here +++++
99
100	// members
101	BRect													rect;
102	BString												text;
103
104	TipManager::offset_mode_t			offsetMode;
105	BPoint 												offset;
106
107	uint32 												flags;
108};
109
110// ordering criteria: by top-left corner of the rect,
111//                    invalid rects last (unsorted)
112// [13may99: inverted -- which I suppose causes elements to
113//           be stored in increasing 'order', and therefore
114//           position]
115
116// [e.moon 13oct99] tip_entry instances now stored and compared
117// by pointer
118
119class tip_entry_ptr_less_fn {		public:
120	bool operator()(
121		const tip_entry*						a,
122		const tip_entry*						b) const {
123		if(a->rect.IsValid())
124			if(b->rect.IsValid()) {
125				if(a->rect.left == b->rect.left)
126					return a->rect.top > b->rect.top;
127				return a->rect.left > b->rect.left;
128			}
129			else
130				return true;
131		else
132			return false;
133	}
134};
135
136typedef std::set<tip_entry*, tip_entry_ptr_less_fn > tip_entry_set;
137
138// -------------------------------------------------------- //
139// _ViewEntry
140// -------------------------------------------------------- //
141
142class _ViewEntry {
143public:													// *** interface
144
145	virtual ~_ViewEntry();
146	_ViewEntry() {}
147	_ViewEntry(
148		BView*											target,
149		_ViewEntry*									parent) :
150		m_target(target),
151		m_parent(parent) {}
152
153	// +++++ copy ctors and other treats for lame compilers go here +++++
154
155	// add the given entry for the designated view
156	// (which may be the target view or a child.)
157	// returns B_OK on success, B_ERROR if:
158	// - the given view is NOT a child of the target view
159	// - or if tips can't be added to this view due to it,
160	//   or one of its parents, having a full-frame tip.
161
162	status_t add(
163		BView*											view,
164		const tip_entry&						entry);
165
166	// remove tip matching the given rect's upper-left corner or
167	// all tips if rect is invalid.
168	// returns B_ERROR on failure -- if there are no entries for
169	// the given view -- or B_OK otherwise.
170
171	status_t remove(
172		BView*											view,
173		const BRect&								rect);
174
175	// match the given point (in target's view coordinates)
176	// against tips in this view and child views.
177
178	std::pair<BView*, const tip_entry*> match(
179		BPoint											point,
180		BPoint											screenPoint);
181
182	// retrieve current frame rect (in parent view's coordinates)
183	BRect Frame();
184
185	BView* target() const { return m_target; }
186	_ViewEntry* parent() const { return m_parent; }
187
188	size_t countTips() const;
189
190	void dump(int indent);
191
192private:
193	// returns pointer to sole entry in the set if it's
194	// a full-frame tip, or 0 if there's no full-frame tip
195	const tip_entry* fullFrameTip() const;
196
197	// members
198	BView*												m_target;
199	_ViewEntry*										m_parent;
200
201	// [e.moon 13oct99] child view list now stores pointers
202	std::list<_ViewEntry*>							m_childViews;
203	tip_entry_set									m_tips;
204};
205
206// -------------------------------------------------------- //
207// _WindowEntry
208// -------------------------------------------------------- //
209
210class _WindowEntry {
211public:													// *** interface
212
213	virtual ~_WindowEntry();
214	_WindowEntry() {}
215	_WindowEntry(
216		BWindow*										target) :
217		m_target(target) {}
218
219	// add the given entry for the designated view (which must
220	// be attached to the target window)
221	// returns B_OK on success, B_ERROR if:
222	// - the given view is NOT attached to the target window, or
223	// - tips can't be added to this view due to it, or one of its
224	//   parents, having a full-frame tip.
225
226	status_t add(
227		BView*											view,
228		const tip_entry&						entry);
229
230	// remove tip matching the given rect's upper-left corner or
231	// all tips if rect is invalid.
232	// returns B_ERROR on failure -- if there are no entries for
233	// the given view -- or B_OK otherwise.
234
235	status_t remove(
236		BView*											view,
237		const BRect&								rect);
238
239	// match the given point (in screen coordinates)
240	// against tips in this view and child views.
241
242	std::pair<BView*, const tip_entry*> match(
243		BPoint											screenPoint);
244
245	BWindow* target() const { return m_target; }
246
247	size_t countViews() const { return m_views.size(); }
248
249	void dump(int indent);
250
251private:
252	// the target window
253	BWindow*											m_target;
254
255	// view subtrees with tip entries
256	std::list<_ViewEntry*>							m_views;
257};
258
259// -------------------------------------------------------- //
260// _TipManagerView
261// -------------------------------------------------------- //
262
263class _TipManagerView :
264	public	BView {
265	typedef	BView _inherited;
266
267public:													// *** messages
268	enum message_t {
269		// sent
270		M_TIME_PASSED
271	};
272
273public:													// *** ctor/dtor
274	virtual ~_TipManagerView();
275	_TipManagerView(
276		TipWindow*									tipWindow,
277		TipManager*									manager,
278		bigtime_t										updatePeriod,
279		bigtime_t										idlePeriod);
280
281public:													// *** operations
282
283	// Prepare a 'one-off' tip: this interrupts normal mouse-watching
284	// behavior while the mouse remains in the given screen rectangle.
285	// If it idles long enough, the tip window is displayed.
286
287	status_t armTip(
288		const BRect&								screenRect,
289		const char*									text,
290		TipManager::offset_mode_t		offsetMode,
291		BPoint											offset,
292		uint32 											flags);
293
294	// Hide tip corresponding to the given screenRect, if any.
295	// [e.moon 29nov99] Cancel 'one-off' tip for the given rect if any.
296
297	status_t hideTip(
298		const BRect&								screenRect);
299
300	// Add/replace a tip in the window/view-entry tree
301
302	status_t setTip(
303		const BRect&								rect,
304		const char*									text,
305		BView*											view,
306		TipManager::offset_mode_t		offsetMode,
307		BPoint											offset,
308		uint32 											flags);
309
310	// Remove a given tip from a particular view in the entry tree
311	// (if the rect is invalid, removes all tips for that view.)
312
313	status_t removeTip(
314		const BRect&								rect,
315		BView*											view);
316
317	// Remove all tips for the given window from the entry tree.
318
319	status_t removeAll(
320		BWindow*										window);
321
322public:													// *** BView
323
324	void AttachedToWindow();
325
326	void KeyDown(
327		const char*									bytes,
328		int32												count);
329
330	void MouseDown(
331		BPoint											point);
332
333	void MouseMoved(
334		BPoint											point,
335		uint32											orientation,
336		const BMessage*							dragMessage);
337
338public:													// *** BHandler
339
340	void MessageReceived(
341		BMessage*										message);
342
343private:												// implementation
344
345	// the tip window to be displayed
346	TipWindow*										m_tipWindow;
347
348	// owner
349	TipManager*										m_manager;
350
351	// set of window entries containing one or more bound tip rectangles
352	std::list<_WindowEntry*>						m_windows;
353
354	// update message source
355	BMessageRunner*								m_messageRunner;
356
357	// window state
358	enum tip_window_state_t {
359		TIP_WINDOW_HIDDEN,
360		TIP_WINDOW_VISIBLE,
361		TIP_WINDOW_ARMED
362	};
363	tip_window_state_t						m_tipWindowState;
364
365	// how often to check for mouse idleness
366	bigtime_t											m_updatePeriod;
367
368	// how long it takes a tip to fire
369	bigtime_t											m_idlePeriod;
370
371	// mouse-watching state
372	BPoint												m_lastMousePoint;
373	bigtime_t											m_lastEventTime;
374	bool													m_triggered;
375
376	// once a tip has been shown, it remains visible while the
377	// mouse stays within this screen rect
378	BRect													m_visibleTipRect;
379
380	// armTip() state
381	tip_entry*										m_armedTip;
382
383private:
384
385	inline void _timePassed();
386
387	inline void _showTip(
388		const tip_entry*						entry);
389
390	inline void _hideTip();
391};
392
393__END_CORTEX_NAMESPACE
394#endif /* __TIPMANAGERIMPL_H__ */
395