2002-02-06 17:15:28 +00:00
|
|
|
/*
|
|
|
|
* \file Tooltips.C
|
|
|
|
* Copyright 2002 the LyX Team
|
|
|
|
* Read the file COPYING
|
|
|
|
*
|
|
|
|
* \author Angus Leeming, a.leeming@ic.ac.uk
|
|
|
|
*
|
|
|
|
* Tooltips for xforms. xforms 0.89 supports them directly, but 0.88 needs
|
|
|
|
* a bit of jiggery pokery. This class wraps it all up in a neat interface.
|
|
|
|
* Based on code originally in Toolbar_pimpl.C that appears to have been
|
|
|
|
* written by Matthias Ettrich and Jean-Marc Lasgouttes.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#ifdef __GNUG__
|
|
|
|
#pragma implementation
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "Tooltips.h"
|
2002-03-11 09:54:42 +00:00
|
|
|
#include "Dialogs.h"
|
|
|
|
#include "xforms_helpers.h" // formatted
|
|
|
|
#include "gettext.h"
|
|
|
|
#include "support/lstrings.h"
|
2002-02-06 17:15:28 +00:00
|
|
|
#include "support/LAssert.h"
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
using SigC::slot;
|
2002-02-06 17:15:28 +00:00
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
|
|
|
|
bool Tooltips::enabled_ = false;
|
|
|
|
|
|
|
|
SigC::Signal0<void> Tooltips::tooltipsToggled;
|
|
|
|
|
|
|
|
|
|
|
|
#if FL_REVISION >= 89
|
|
|
|
|
|
|
|
Tooltips::Tooltips()
|
|
|
|
{
|
|
|
|
static bool first = true;
|
|
|
|
if (first) {
|
|
|
|
first = false;
|
|
|
|
Dialogs::toggleTooltips.connect(slot(&Tooltips::toggleEnabled));
|
|
|
|
}
|
|
|
|
tooltipsToggled.connect(slot(this, &Tooltips::toggleTooltips));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tooltips::toggleEnabled()
|
|
|
|
{
|
|
|
|
enabled_ = !enabled_;
|
|
|
|
tooltipsToggled();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tooltips::toggleTooltips()
|
|
|
|
{
|
|
|
|
if (tooltipsMap.empty())
|
|
|
|
// There are no objects with tooltips in this dialog, so
|
|
|
|
// just go away. Don't change the cursor to a question mark.
|
|
|
|
return;
|
|
|
|
|
|
|
|
TooltipsMap::iterator it = tooltipsMap.begin();
|
|
|
|
TooltipsMap::iterator end = tooltipsMap.end();
|
|
|
|
for (; it != end; ++it) {
|
|
|
|
FL_OBJECT * const ob = it->first;
|
|
|
|
char const * const c_str = enabled_ ? it->second.c_str() : 0;
|
|
|
|
fl_set_object_helper(ob, c_str);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the cursor to a question mark or back to the default.
|
|
|
|
FL_OBJECT * const ob = tooltipsMap.begin()->first;
|
|
|
|
int const cursor = enabled_ ? XC_question_arrow : FL_DEFAULT_CURSOR;
|
|
|
|
fl_set_cursor(FL_ObjWin(ob), cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tooltips::initTooltip(FL_OBJECT * ob, string const & tip)
|
2002-02-06 17:15:28 +00:00
|
|
|
{
|
|
|
|
lyx::Assert(ob);
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
// Paranoia check!
|
|
|
|
TooltipsMap::const_iterator it = tooltipsMap.find(ob);
|
|
|
|
if (it != tooltipsMap.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
string const str = strip(frontStrip(tip));
|
|
|
|
if (str.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Store the tooltip string
|
|
|
|
tooltipsMap[ob] = formatted(_(str), 400);
|
|
|
|
|
|
|
|
// Set the initial state of the tooltips
|
|
|
|
char const * const c_str = enabled_ ? str.c_str() : 0;
|
|
|
|
fl_set_object_helper(ob, c_str);
|
2002-02-06 17:15:28 +00:00
|
|
|
}
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
|
|
|
|
#else // if FL_REVISION < 89
|
2002-02-06 17:15:28 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
int TooltipHandler(FL_OBJECT *ob, int event);
|
|
|
|
|
|
|
|
void TooltipTimerCB(FL_OBJECT * timer, long data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
static int C_TooltipHandler(FL_OBJECT * ob, int event,
|
|
|
|
FL_Coord, FL_Coord, int, void *)
|
|
|
|
{
|
|
|
|
return TooltipHandler(ob, event);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void C_TooltipTimerCB(FL_OBJECT * ob, long data)
|
|
|
|
{
|
|
|
|
TooltipTimerCB(ob, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
Tooltips::Tooltips()
|
|
|
|
: tooltip_timer_(0)
|
|
|
|
{
|
|
|
|
static bool first = true;
|
|
|
|
if (first) {
|
|
|
|
first = false;
|
|
|
|
Dialogs::toggleTooltips.connect(slot(&Tooltips::toggleEnabled));
|
|
|
|
}
|
|
|
|
tooltipsToggled.connect(slot(this, &Tooltips::toggleTooltips));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tooltips::toggleEnabled()
|
|
|
|
{
|
|
|
|
enabled_ = !enabled_;
|
|
|
|
tooltipsToggled();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tooltips::toggleTooltips()
|
|
|
|
{
|
|
|
|
if (tooltipsMap.empty())
|
|
|
|
// There are no objects with tooltips in this dialog, so
|
|
|
|
// just go away. Don't change the cursor to a question mark.
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Set the cursor to a question mark or back to the default.
|
|
|
|
FL_OBJECT * const ob = tooltipsMap.begin()->first;
|
|
|
|
int const cursor = enabled_ ? XC_question_arrow : FL_DEFAULT_CURSOR;
|
|
|
|
fl_set_cursor(FL_ObjWin(ob), cursor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Tooltips::initTooltip(FL_OBJECT * ob, string const & tip)
|
2002-02-06 17:15:28 +00:00
|
|
|
{
|
|
|
|
lyx::Assert(ob);
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
// Paranoia check!
|
|
|
|
TooltipsMap::const_iterator it = tooltipsMap.find(ob);
|
|
|
|
if (it != tooltipsMap.end())
|
|
|
|
return;
|
|
|
|
|
|
|
|
string const str = strip(frontStrip(tip));
|
|
|
|
if (str.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Store the tooltip string
|
|
|
|
tooltipsMap[ob] = formatted(_(str), 400);
|
|
|
|
|
2002-02-06 17:15:28 +00:00
|
|
|
if (!tooltip_timer_) {
|
|
|
|
lyx::Assert(ob->form);
|
2002-03-11 09:54:42 +00:00
|
|
|
if (fl_current_form && ob->form != fl_current_form)
|
|
|
|
fl_end_form();
|
|
|
|
|
|
|
|
bool const open_form = !fl_current_form;
|
|
|
|
if (open_form)
|
|
|
|
fl_addto_form(ob->form);
|
|
|
|
|
2002-02-06 17:15:28 +00:00
|
|
|
tooltip_timer_ = fl_add_timer(FL_HIDDEN_TIMER, 0, 0, 0, 0, "");
|
2002-03-11 09:54:42 +00:00
|
|
|
|
|
|
|
if (open_form)
|
|
|
|
fl_end_form();
|
2002-02-06 17:15:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fl_set_object_posthandler(ob, C_TooltipHandler);
|
|
|
|
ob->u_cdata = reinterpret_cast<char *>(tooltip_timer_);
|
|
|
|
tooltip_timer_->u_vdata = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
string const Tooltips::getTooltip(FL_OBJECT * ob) const
|
|
|
|
{
|
|
|
|
TooltipsMap::const_iterator it = tooltipsMap.find(ob);
|
|
|
|
if (it == tooltipsMap.end())
|
|
|
|
return string();
|
|
|
|
return it->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-02-06 17:15:28 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
void TooltipTimerCB(FL_OBJECT * timer, long data)
|
|
|
|
{
|
|
|
|
FL_OBJECT * ob = reinterpret_cast<FL_OBJECT*>(data);
|
|
|
|
lyx::Assert(ob && ob->form && timer && timer->u_vdata);
|
|
|
|
FL_FORM * form = ob->form;
|
|
|
|
Tooltips * tooltip = static_cast<Tooltips *>(timer->u_vdata);
|
|
|
|
|
|
|
|
string const help = tooltip->getTooltip(ob);
|
|
|
|
if (help.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
fl_show_oneliner(help.c_str(),
|
|
|
|
form->x + ob->x, form->y + ob->y + ob->h);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
// post_handler for tooltip help
|
|
|
|
int TooltipHandler(FL_OBJECT * ob, int event)
|
2002-02-06 17:15:28 +00:00
|
|
|
{
|
2002-03-11 09:54:42 +00:00
|
|
|
if (!Tooltips::enabled())
|
|
|
|
return 0;
|
|
|
|
|
2002-02-06 17:15:28 +00:00
|
|
|
lyx::Assert(ob);
|
|
|
|
FL_OBJECT * timer = reinterpret_cast<FL_OBJECT *>(ob->u_cdata);
|
|
|
|
lyx::Assert(timer);
|
|
|
|
|
|
|
|
// We do not test for empty help here, since this can never happen
|
2002-02-16 15:59:55 +00:00
|
|
|
if (event == FL_ENTER) {
|
2002-02-06 17:15:28 +00:00
|
|
|
fl_set_object_callback(timer,
|
|
|
|
C_TooltipTimerCB,
|
|
|
|
reinterpret_cast<long>(ob));
|
|
|
|
fl_set_timer(timer, 1);
|
|
|
|
}
|
2002-02-16 15:59:55 +00:00
|
|
|
else if (event != FL_MOTION) {
|
2002-02-06 17:15:28 +00:00
|
|
|
fl_set_timer(timer, 0);
|
|
|
|
fl_hide_oneliner();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace anon
|
|
|
|
|
2002-03-11 09:54:42 +00:00
|
|
|
#endif // FL_REVISION >= 89
|