BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / cortex / TipManager / TipManager.cpp
blobbd70a9f4a49f73b50d89379f8b84392cea952fb8
1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
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.
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.
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.
32 // TipManager.cpp
33 // e.moon 12may99
35 #include "TipManager.h"
36 #include "TipManagerImpl.h"
37 #include "TipWindow.h"
39 #include <Autolock.h>
40 #include <Message.h>
41 #include <MessageFilter.h>
42 #include <Region.h>
43 #include <float.h>
45 #include "debug_tools.h"
47 __USE_CORTEX_NAMESPACE
49 // -------------------------------------------------------- //
50 // constants
51 // -------------------------------------------------------- //
53 // static instance (created on first call to TipManager::Instance().)
54 TipManager* TipManager::s_instance = 0;
55 BLocker TipManager::s_instanceLock("TipManager::s_instanceLock");
57 // special point value set to highly improbable position
58 const BPoint TipManager::s_useDefaultOffset(FLT_MIN, FLT_MIN);
60 // default tip position
61 const BPoint TipManager::s_defaultOffset(8.0, 8.0);
63 const bigtime_t TipManager::s_defIdleTime = 750000LL;
64 const bigtime_t TipManager::s_sleepPeriod = 250000LL;
66 // -------------------------------------------------------- //
67 // *** message filter
68 // -------------------------------------------------------- //
70 filter_result ignore_quit_key(
71 BMessage* message,
72 BHandler** target,
73 BMessageFilter* filter)
75 switch(message->what)
77 // filter command-Q
78 case B_KEY_DOWN:
80 if((modifiers() & B_COMMAND_KEY))
82 int8 key;
83 message->FindInt8("byte", &key);
84 if(key == 'q')
85 return B_SKIP_MESSAGE;
87 break;
90 return B_DISPATCH_MESSAGE;
93 // -------------------------------------------------------- //
94 // *** dtor
95 // -------------------------------------------------------- //
97 TipManager::~TipManager() {}
99 // -------------------------------------------------------- //
100 // *** singleton access
101 // -------------------------------------------------------- //
103 /*static*/
104 TipManager* TipManager::Instance() {
105 BAutolock _l(s_instanceLock);
106 if(!s_instance)
107 s_instance = new TipManager();
109 return s_instance;
112 // kill current instance if any
113 /*static*/
114 void TipManager::QuitInstance() {
115 BAutolock _l(s_instanceLock);
116 if(s_instance) {
117 s_instance->Lock();
118 s_instance->Quit();
119 s_instance = 0;
123 // -------------------------------------------------------- //
124 // hidden constructor (use Instance() to access
125 // a single instance)
126 // -------------------------------------------------------- //
128 TipManager::TipManager() :
130 BWindow(
131 BRect(-100,-100,-100,-100),
132 "TipManager",
133 B_NO_BORDER_WINDOW_LOOK,
134 B_FLOATING_ALL_WINDOW_FEEL,
135 B_ASYNCHRONOUS_CONTROLS | B_AVOID_FOCUS),
136 m_view(0) {
138 AddCommonFilter(
139 new BMessageFilter(
140 B_PROGRAMMED_DELIVERY,
141 B_ANY_SOURCE,
142 &ignore_quit_key));
144 m_view = new _TipManagerView(
145 new TipWindow(),
146 this,
147 s_sleepPeriod,
148 s_defIdleTime);
149 AddChild(m_view);
151 // start the window thread
152 Show();
156 // -------------------------------------------------------- //
157 // add and remove tips
158 // -------------------------------------------------------- //
160 // add or modify a tip:
162 status_t TipManager::setTip(
163 const BRect& rect,
164 const char* text,
165 BView* view,
166 offset_mode_t offsetMode /*=LEFT_OFFSET_FROM_RECT*/,
167 BPoint offset /*=s_useDefaultOffset*/,
168 uint32 flags /*=NONE*/) {
170 ASSERT(text);
171 ASSERT(m_view);
173 BAutolock _l(this);
174 return m_view->setTip(
175 rect, text, view, offsetMode, offset, flags);
179 status_t TipManager::setTip(
180 const char* text,
181 BView* view,
182 offset_mode_t offsetMode /*=LEFT_OFFSET_FROM_RECT*/,
183 BPoint offset /*=s_useDefaultOffset*/,
184 uint32 flags /*=NONE*/) {
186 return setTip(
187 BRect(), text, view, offsetMode, offset, flags);
190 // Remove all tips matching the given rectangle and/or child
191 // view. Returns the number of tips removed.
193 status_t TipManager::removeTip(
194 const BRect& rect,
195 BView* view) {
197 ASSERT(view);
198 ASSERT(m_view);
200 BAutolock _l(this);
201 return m_view->removeTip(rect, view);
204 // If more than one tip is mapped to pChild, all are removed:
206 status_t TipManager::removeAll(
207 BView* view) {
209 return removeTip(BRect(), view);
212 status_t TipManager::removeAll(
213 BWindow* window) {
215 // PRINT((
216 // "### TipManager::removeAll(): %p, %p\n", this, m_view->Looper()));
218 ASSERT(window);
219 ASSERT(m_view);
220 ASSERT(m_view->Looper() == this); // +++++
222 BAutolock _l(this);
223 return m_view->removeAll(window);
226 // -------------------------------------------------------- //
227 // *** manual tip arming
228 // -------------------------------------------------------- //
230 // [e.moon 19oct99]
231 // Call when the mouse has entered a particular region of
232 // the screen for which you want a tip to be displayed.
233 // The tip will be displayed if the mouse stops moving
234 // for idleTime microseconds within the rectangle screenRect.
236 status_t TipManager::showTip(
237 const char* text,
238 BRect screenRect,
239 offset_mode_t offsetMode /*=LEFT_OFFSET_FROM_RECT*/,
240 BPoint offset /*=s_useDefaultOffset*/,
241 uint32 flags /*=NONE*/) {
243 ASSERT(text);
244 ASSERT(m_view);
246 BAutolock _l(this);
247 return m_view->armTip(
248 screenRect, text, offsetMode, offset, flags);
251 // [e.moon 22oct99]
252 // Call to immediately hide a visible tip. You need to know
253 // the screen rectangle for which the tip was shown (which is easy
254 // if was displayed due to a showTip() call -- pass the same
255 // screenRect argument.)
256 // If the tip was found & hidden, returns B_OK; if there's
257 // no visible tip or it was triggered by a different rectangle,
258 // returns B_BAD_VALUE.
260 status_t TipManager::hideTip(
261 BRect screenRect) {
263 ASSERT(m_view);
265 BAutolock _l(this);
266 return m_view->hideTip(screenRect);
270 // -------------------------------------------------------- //
271 // *** BWindow
272 // -------------------------------------------------------- //
274 // -------------------------------------------------------- //
275 // *** BLooper
276 // -------------------------------------------------------- //
278 bool TipManager::QuitRequested() {
279 // ignored, since I receive key events bound for other apps
280 return false;
283 // -------------------------------------------------------- //
284 // *** BHandler
285 // -------------------------------------------------------- //
287 void TipManager::MessageReceived(
288 BMessage* message) {
290 switch(message->what) {
291 default:
292 _inherited::MessageReceived(message);
296 //// -------------------------------------------------------- //
297 //// BasicThread impl.
298 //// -------------------------------------------------------- //
300 //// +++++
301 //// 12aug99: a locking bug seems to cause occasional
302 //// crashes on shutdown after the looper's been deleted.
303 //// +++++
304 //// 23sep99: probably fixed; the TipManager needs to be manually
305 //// killed before the window is deleted.
307 //void TipManager::run() {
309 // BPoint point, lastPoint, screenPoint;
310 // bigtime_t curTime, lastTime;
311 // uint32 buttons;
313 // bool bTipVisible = false;
314 // BRect tipScreenRect;
316 // lastTime = 0;
317 // curTime = 0;
319 // // [e.moon 27sep99]
320 // // store whether the tip has fired at the current point
321 // bool fired = false;
323 // ASSERT(m_tree);
324 // BView* pOwningView = m_tree->target();
326 // while(!stopping()) {
327 // snooze(s_sleepPeriod);
328 // if(stopping())
329 // break;
331 // // wait for the view to show up
332 // if(!pOwningView->Parent() || !pOwningView->Window())
333 // continue;
335 // // get current mouse position
336 // pOwningView->LockLooper();
338 // pOwningView->GetMouse(&point, &buttons, false);
339 // screenPoint = pOwningView->ConvertToScreen(point);
341 // pOwningView->UnlockLooper();
343 // // has it been sitting in one place long enough?
344 // bool bMoved = (point != lastPoint);
346 // if(bMoved) {
347 // lastTime = curTime;
348 // fired = false;
349 // }
350 // else if(fired) {
351 // // [27sep99 e.moon] the tip has already fired, and
352 // // the mouse hasn't moved; bail out now
353 // continue;
354 // }
356 // curTime = system_time();
357 // bool bIdle = !bMoved && lastTime && (curTime - lastTime) > m_idleTime;
358 // lastPoint = point;
360 // if(bTipVisible) {
361 // // hide tip once mouse moves outside its rectangle
362 // if(!tipScreenRect.Contains(screenPoint)) {
363 // m_tipWindow->Lock();
364 // if(!m_tipWindow->IsHidden()) // tip may hide itself [7sep99]
365 // m_tipWindow->Hide();
366 // bTipVisible = false;
367 // m_tipWindow->Unlock();
368 // }
369 // } else if(bIdle) {
371 // // mouse has idled at a given point long enough;
372 // // look for a tip at that position and display one if found:
374 // fired = true;
376 // pOwningView->LockLooper();
378 // // make sure this part of the view is actually visible
379 // if(!pOwningView->Window()->Frame().Contains(screenPoint)) {
380 // pOwningView->UnlockLooper();
381 // continue;
382 // }
384 // // look for a tip under the mouse
385 // m_tipWindow->Lock();
386 // pair<BView*, const tip_entry*> found =
387 // m_tree->match(point, screenPoint);
389 // if(!found.second) {
390 // // none found; move on
391 // pOwningView->UnlockLooper();
392 // m_tipWindow->Unlock();
393 // continue;
394 // }
396 // BView* pTipTarget = found.first;
397 // const tip_entry& entry = *found.second;
399 // // test the screen point against the view's clipping region;
400 // // if no match, the given point is likely covered by another
401 // // window (so stop recursing)
403 // BRegion clipRegion;
404 // pTipTarget->GetClippingRegion(&clipRegion);
405 // if(!clipRegion.Contains(
406 // pTipTarget->ConvertFromScreen(screenPoint))) {
407 // // move on
408 // pOwningView->UnlockLooper();
409 // m_tipWindow->Unlock();
410 // continue;
411 // }
413 // // found one; set up the tip window:
414 // BRect entryFrame = pTipTarget->ConvertToScreen(entry.rect);
416 // // set text (this has the side effect of resizing the
417 // // window)
419 // ASSERT(m_tipWindow);
420 // m_tipWindow->setText(entry.text.String());
422 // // figure out where to display it:
424 // BPoint offset = (entry.offset == s_useDefaultOffset) ?
425 // s_defaultOffset :
426 // entry.offset;
428 // BPoint p;
429 // switch(entry.offsetMode) {
430 // case LEFT_OFFSET_FROM_RECT:
431 // p = entryFrame.RightTop() + offset;
432 // break;
433 // case LEFT_OFFSET_FROM_POINTER:
434 // p = screenPoint + offset;
435 // break;
436 // case RIGHT_OFFSET_FROM_RECT:
437 // p = entryFrame.LeftTop();
438 // p.x -= offset.x;
439 // p.y += offset.y;
440 // p.x -= m_tipWindow->Frame().Width();
441 // break;
442 // case RIGHT_OFFSET_FROM_POINTER:
443 // p = screenPoint;
444 // p.x -= offset.x;
445 // p.y += offset.y;
446 // p.x -= m_tipWindow->Frame().Width();
447 // break;
448 // default:
449 // ASSERT(!"bad offset mode");
450 // }
452 // // do it:
454 // m_tipWindow->MoveTo(p);
455 // m_tipWindow->Show();
457 // bTipVisible = true;
458 // tipScreenRect = entryFrame;
460 // m_tipWindow->Unlock();
461 // pOwningView->UnlockLooper();
463 // } // if(bIdle ...
464 // } // while(!stopping ...
467 // END -- TipManager.cpp --