Moved stable tool tip concept into the BToolManager class.

* This removes the fVisibleToolTip member from BView, and fixes bug #5669;
  BToolTipManager::ShowTip() now gets the owner of the tool tip as an extra
  parameter.
* Removed the work-around to hide that bug.
* Improved ToolTipTest application to include more test cases like a view that
  periodically update its tool tip via SetToolTip(const char*), and one that
  sets a new tool tip every second.
* Furthermore, added a test that shows that inner views inherit the tool tip
  of their parents.
* Fixed another bug in BToolTipManager::ShowTip() that would release an
  extra reference to the tool tip currently shown.
This commit is contained in:
Axel Dörfler 2012-04-28 22:09:14 +02:00
parent f790fa299e
commit 2f2f3fa042
6 changed files with 116 additions and 48 deletions

View File

@ -700,9 +700,8 @@ private:
LayoutData* fLayoutData;
BToolTip* fToolTip;
BToolTip* fVisibleToolTip;
uint32 _reserved[5];
uint32 _reserved[6];
};

View File

@ -18,7 +18,8 @@ class BToolTipManager {
public:
static BToolTipManager* Manager();
void ShowTip(BToolTip* tip, BPoint point);
void ShowTip(BToolTip* tip, BPoint point,
void* owner);
void HideTip();
void SetShowDelay(bigtime_t time);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009, Haiku, Inc. All Rights Reserved.
* Copyright 2009-2012, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef TOOL_TIP_WINDOW_H
@ -11,13 +11,19 @@
namespace BPrivate {
class ToolTipWindow : public BWindow {
public:
ToolTipWindow(BToolTip* tip, BPoint where);
ToolTipWindow(BToolTip* tip, BPoint where,
void* owner);
virtual void MessageReceived(BMessage* message);
private:
void* fOwner;
};
} // namespace BPrivate

View File

@ -1,5 +1,5 @@
/*
* Copyright 2009-2010, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2009-2012, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2009, Stephan Aßmus <superstippi@gmx.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@ -285,12 +285,13 @@ ToolTipView::ResetWindowFrame(BPoint where)
// #pragma mark -
ToolTipWindow::ToolTipWindow(BToolTip* tip, BPoint where)
ToolTipWindow::ToolTipWindow(BToolTip* tip, BPoint where, void* owner)
:
BWindow(BRect(0, 0, 250, 10).OffsetBySelf(where), "tool tip",
B_BORDERED_WINDOW_LOOK, kMenuWindowFeel,
B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS
| B_AVOID_FRONT | B_AVOID_FOCUS)
| B_AVOID_FRONT | B_AVOID_FOCUS),
fOwner(owner)
{
SetLayout(new BGroupLayout(B_VERTICAL));
@ -323,6 +324,7 @@ ToolTipWindow::MessageReceived(BMessage* message)
BMessage reply(B_REPLY);
reply.AddPointer("current", tip);
reply.AddPointer("owner", fOwner);
if (message->SendReply(&reply) == B_OK)
tip->AcquireReference();
@ -363,36 +365,30 @@ BToolTipManager::Manager()
}
/*static*/ void
BToolTipManager::_InitSingleton()
{
sDefaultInstance = new BToolTipManager();
}
void
BToolTipManager::ShowTip(BToolTip* tip, BPoint point)
BToolTipManager::ShowTip(BToolTip* tip, BPoint point, void* owner)
{
BToolTip* current = NULL;
void* currentOwner = NULL;
BMessage reply;
if (fWindow.SendMessage(kMsgCurrentToolTip, &reply) == B_OK)
if (fWindow.SendMessage(kMsgCurrentToolTip, &reply) == B_OK) {
reply.FindPointer("current", (void**)&current);
reply.FindPointer("owner", &currentOwner);
}
// Release reference from the message
if (current != NULL)
current->ReleaseReference();
if (current == tip) {
if (current == tip || currentOwner == owner) {
fWindow.SendMessage(kMsgShowToolTip);
return;
}
fWindow.SendMessage(kMsgHideToolTip);
if (current != NULL)
current->ReleaseReference();
if (tip != NULL) {
BWindow* window = new BPrivate::ToolTipWindow(tip, point);
BWindow* window = new BPrivate::ToolTipWindow(tip, point, owner);
window->Show();
fWindow = BMessenger(window);
@ -459,3 +455,10 @@ BToolTipManager::BToolTipManager()
BToolTipManager::~BToolTipManager()
{
}
/*static*/ void
BToolTipManager::_InitSingleton()
{
sDefaultInstance = new BToolTipManager();
}

View File

@ -4817,10 +4817,6 @@ BView::DoLayout()
void
BView::SetToolTip(const char* text)
{
// TODO: temporary work-around for bug #5669
HideToolTip();
SetToolTip(static_cast<BToolTip*>(NULL));
if (text == NULL || text[0] == '\0')
return;
@ -4858,12 +4854,10 @@ BView::ShowToolTip(BToolTip* tip)
if (tip == NULL)
return;
fVisibleToolTip = tip;
BPoint where;
GetMouse(&where, NULL, false);
BToolTipManager::Manager()->ShowTip(tip, ConvertToScreen(where));
BToolTipManager::Manager()->ShowTip(tip, ConvertToScreen(where), this);
}
@ -4871,17 +4865,12 @@ void
BView::HideToolTip()
{
BToolTipManager::Manager()->HideTip();
fVisibleToolTip = NULL;
}
bool
BView::GetToolTipAt(BPoint point, BToolTip** _tip)
{
if (fVisibleToolTip != NULL) {
*_tip = fVisibleToolTip;
return true;
}
if (fToolTip != NULL) {
*_tip = fToolTip;
return true;
@ -5038,7 +5027,6 @@ BView::_InitData(BRect frame, const char* name, uint32 resizingMode,
fLayoutData = new LayoutData;
fToolTip = NULL;
fVisibleToolTip = NULL;
}

View File

@ -1,13 +1,15 @@
/*
* Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2009-2012, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include <Application.h>
#include <Box.h>
#include <GroupView.h>
#include <LayoutBuilder.h>
#include <MessageRunner.h>
#include <String.h>
#include <StringView.h>
#include <Window.h>
@ -18,9 +20,9 @@
class CustomToolTip : public BToolTip {
public:
CustomToolTip()
CustomToolTip(const char* text)
{
fView = new BStringView("", "Custom tool tip!");
fView = new BStringView("", text);
fView->SetFont(be_bold_font);
fView->SetHighColor(255, 0, 0);
}
@ -176,6 +178,52 @@ public:
};
class PulseStringView : public BStringView {
public:
PulseStringView(const char* name, const char* label)
:
BStringView(name, label, B_WILL_DRAW | B_PULSE_NEEDED)
{
}
virtual void Pulse()
{
char buffer[256];
time_t now = time(NULL);
strftime(buffer, sizeof(buffer), "%X", localtime(&now));
SetToolTip(buffer);
}
};
class PulseToolTipView : public BStringView {
public:
PulseToolTipView(const char* name, const char* label)
:
BStringView(name, label, B_WILL_DRAW | B_PULSE_NEEDED),
fToolTip(NULL),
fCounter(0)
{
}
virtual void Pulse()
{
if (fToolTip != NULL)
fToolTip->ReleaseReference();
BString text;
text.SetToFormat("New tool tip every second! (%d)", fCounter++);
fToolTip = new CustomToolTip(text.String());
SetToolTip(fToolTip);
}
private:
BToolTip* fToolTip;
int fCounter;
};
class Window : public BWindow {
public:
Window();
@ -204,22 +252,44 @@ Window::Window()
simple->SetToolTip("This is a really\nsimple tool tip!");
BView* custom = new BStringView("2", "Custom Tool Tip");
custom->SetToolTip(new CustomToolTip());
custom->SetToolTip(new CustomToolTip("Custom tool tip!"));
BView* changing = new BStringView("3", "Changing Tool Tip");
changing->SetToolTip(new ChangingToolTip());
BView* mouse = new BStringView("3", "Mouse Tool Tip (sticky)");
BView* mouse = new BStringView("4", "Mouse Tool Tip (sticky)");
mouse->SetToolTip(new MouseToolTip());
BView* immediate = new ImmediateView("3", "Immediate Tool Tip (sticky)");
BView* immediate = new ImmediateView("5", "Immediate Tool Tip (sticky)");
BLayoutBuilder::Group<>(this, B_VERTICAL)
.Add(simple)
.Add(custom)
.Add(changing)
.Add(mouse)
.Add(immediate);
BView* pulseString = new PulseStringView("pulseString",
"Periodically changing tool tip text");
BView* pulseToolTip = new PulseToolTipView("pulseToolTip",
"Periodically changing tool tip");
BGroupView* nested = new BGroupView();
nested->SetViewColor(50, 50, 90);
nested->GroupLayout()->SetInsets(30);
nested->SetToolTip("The outer view has a tool tip,\n"
"the inner one doesn't.");
nested->AddChild(new BGroupView("inner"));
BLayoutBuilder::Group<>(this, B_HORIZONTAL)
.SetInsets(B_USE_DEFAULT_SPACING)
.AddGroup(B_VERTICAL)
.Add(simple)
.Add(custom)
.Add(changing)
.Add(mouse)
.Add(immediate)
.End()
.AddGroup(B_VERTICAL)
.Add(pulseString)
.Add(pulseToolTip)
.Add(nested);
SetPulseRate(1000000LL);
}
@ -235,7 +305,8 @@ Window::QuitRequested()
Application::Application()
: BApplication("application/x-vnd.haiku-tooltiptest")
:
BApplication("application/x-vnd.haiku-tooltiptest")
{
}