|
|
|
/*
|
|
|
|
Copyright (c) 2006 Gábor Lehel <illissius@gmail.com>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqcursor.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqsimplerichtext.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
|
|
|
|
#include "debug.h"
|
|
|
|
#include "tooltip.h"
|
|
|
|
|
|
|
|
class Amarok::ToolTip::Manager: public TQObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Manager( TQObject *parent ): TQObject( parent ) { tqApp->installEventFilter( this ); }
|
|
|
|
virtual ~Manager()
|
|
|
|
{
|
|
|
|
for( int n = Amarok::ToolTip::s_tooltips.count() - 1; n >= 0; --n )
|
|
|
|
delete Amarok::ToolTip::s_tooltips[n];
|
|
|
|
}
|
|
|
|
|
|
|
|
bool eventFilter( TQObject*, TQEvent *e )
|
|
|
|
{
|
|
|
|
switch ( e->type() )
|
|
|
|
{
|
|
|
|
case TQEvent::KeyPress:
|
|
|
|
case TQEvent::KeyRelease:
|
|
|
|
case TQEvent::MouseButtonPress:
|
|
|
|
case TQEvent::MouseButtonRelease:
|
|
|
|
//case TQEvent::MouseMove:
|
|
|
|
case TQEvent::Wheel:
|
|
|
|
ToolTip::hideTips();
|
|
|
|
break;
|
|
|
|
case TQEvent::FocusIn:
|
|
|
|
case TQEvent::Enter:
|
|
|
|
case TQEvent::Leave:
|
|
|
|
case TQEvent::FocusOut:
|
|
|
|
if( !dynamic_cast<Amarok::ToolTip*>( tqApp->widgetAt( TQCursor::pos(), true ) ) )
|
|
|
|
Amarok::ToolTip::hideTips();
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Amarok::ToolTip::Manager* Amarok::ToolTip::s_manager = 0;
|
|
|
|
TQPoint Amarok::ToolTip::s_pos;
|
|
|
|
TQRect Amarok::ToolTip::s_rect;
|
|
|
|
TQString Amarok::ToolTip::s_text;
|
|
|
|
TQValueList<Amarok::ToolTip*> Amarok::ToolTip::s_tooltips;
|
|
|
|
int Amarok::ToolTip::s_hack = 0;
|
|
|
|
|
|
|
|
void Amarok::ToolTip::add( ToolTipClient *client, TQWidget *parent ) //static
|
|
|
|
{
|
|
|
|
if( !s_manager )
|
|
|
|
s_manager = new Amarok::ToolTip::Manager( TQT_TQOBJECT(tqApp) );
|
|
|
|
new ToolTip( client, parent );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::remove( TQWidget *widget ) //static
|
|
|
|
{
|
|
|
|
for( int i = s_tooltips.count() - 1; i >= 0; --i )
|
|
|
|
if( s_tooltips[i]->TQToolTip::parentWidget() == widget )
|
|
|
|
delete s_tooltips[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::hideTips() //static
|
|
|
|
{
|
|
|
|
for( int i = 0, n = s_tooltips.count(); i < n; ++i )
|
|
|
|
s_tooltips[i]->hideTip();
|
|
|
|
TQToolTip::hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString Amarok::ToolTip::textFor( TQWidget *widget, const TQPoint &pos ) //static
|
|
|
|
{
|
|
|
|
for( int i = 0, n = s_tooltips.count(); i < n; ++i )
|
|
|
|
if( s_tooltips[i]->TQToolTip::parentWidget() == widget )
|
|
|
|
return s_tooltips[i]->m_client->toolTipText( widget, pos ).first;
|
|
|
|
return TQToolTip::textFor( widget, pos );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::updateTip() //static
|
|
|
|
{
|
|
|
|
for( int i = 0, n = s_tooltips.count(); i < n; ++i )
|
|
|
|
if( s_tooltips[i]->isVisible() )
|
|
|
|
{
|
|
|
|
TQWidget* const w = s_tooltips[i]->TQToolTip::parentWidget();
|
|
|
|
TQPair<TQString, TQRect> p = s_tooltips[i]->m_client->toolTipText( w, w->mapFromGlobal( s_pos ) );
|
|
|
|
TQString prev = s_text;
|
|
|
|
if( prev != p.first )
|
|
|
|
{
|
|
|
|
s_text = p.first;
|
|
|
|
s_rect = p.second;
|
|
|
|
s_tooltips[i]->showTip();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Amarok::ToolTip::ToolTip( ToolTipClient *client, TQWidget *parent )
|
|
|
|
: TQFrame( 0, 0, WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WStyle_StaysOnTop | WX11BypassWM | WNoAutoErase ),
|
|
|
|
TQToolTip( parent ),
|
|
|
|
m_client( client )
|
|
|
|
{
|
|
|
|
s_tooltips.append( this );
|
|
|
|
TQFrame::setPalette( TQToolTip::palette() );
|
|
|
|
connect( &m_timer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( hideTip() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
Amarok::ToolTip::~ToolTip()
|
|
|
|
{
|
|
|
|
s_tooltips.remove( this );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::maybeTip( const TQPoint &pos )
|
|
|
|
{
|
|
|
|
s_pos = TQToolTip::parentWidget()->mapToGlobal( pos );
|
|
|
|
TQString prev = s_text;
|
|
|
|
TQPair<TQString, TQRect> p = m_client->toolTipText( TQToolTip::parentWidget(), pos );
|
|
|
|
s_text = p.first;
|
|
|
|
s_rect = p.second;
|
|
|
|
if( TQToolTip::parentWidget() && !s_text.isEmpty() )
|
|
|
|
{
|
|
|
|
if( s_text != prev )
|
|
|
|
hideTips();
|
|
|
|
showTip();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
hideTips();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::showTip()
|
|
|
|
{
|
|
|
|
m_timer.start( 15000, true );
|
|
|
|
if( !isVisible() || sizeHint() != size() )
|
|
|
|
{
|
|
|
|
resize( sizeHint() );
|
|
|
|
position();
|
|
|
|
}
|
|
|
|
if( !isVisible() )
|
|
|
|
show();
|
|
|
|
else
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::hideTip()
|
|
|
|
{
|
|
|
|
if( !isVisible() )
|
|
|
|
return;
|
|
|
|
TQFrame::hide();
|
|
|
|
TQToolTip::parentWidget()->update();
|
|
|
|
m_timer.stop();
|
|
|
|
s_hack = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::drawContents( TQPainter *painter )
|
|
|
|
{
|
|
|
|
TQPixmap buf( width(), height() );
|
|
|
|
TQPainter p( &buf );
|
|
|
|
buf.fill( colorGroup().background() );
|
|
|
|
|
|
|
|
p.setPen( colorGroup().foreground() );
|
|
|
|
p.drawRect( buf.rect() );
|
|
|
|
|
|
|
|
TQSimpleRichText text( s_text, TQToolTip::parentWidget()->font() );
|
|
|
|
text.setWidth( width() );
|
|
|
|
p.translate( 0, height() / 2 - text.height() / 2);
|
|
|
|
TQPoint pos = s_rect.isNull() ? TQPoint(2, -1)
|
|
|
|
: s_hack == 1 ? TQPoint(4, -2)
|
|
|
|
: TQPoint(2, -2); //HACK positioning
|
|
|
|
p.setFont( TQToolTip::parentWidget()->font() );
|
|
|
|
text.draw( &p, pos.x(), pos.y(), rect(), colorGroup() );
|
|
|
|
|
|
|
|
painter->drawPixmap( 0, 0, buf );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQSize Amarok::ToolTip::sizeHint() const
|
|
|
|
{
|
|
|
|
if( !s_rect.isNull() )
|
|
|
|
return s_rect.size();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQSimpleRichText text( s_text, TQToolTip::parentWidget()->font() );
|
|
|
|
text.setWidth( 500 ); //is this reasonable?
|
|
|
|
return TQSize( text.widthUsed() - 2, text.height() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Amarok::ToolTip::position()
|
|
|
|
{
|
|
|
|
const TQRect drect = TQApplication::desktop()->availableGeometry( TQToolTip::parentWidget() );
|
|
|
|
const TQSize size = sizeHint();
|
|
|
|
const int width = size.width(), height = size.height();
|
|
|
|
TQPoint pos;
|
|
|
|
if( !s_rect.isNull() )
|
|
|
|
{
|
|
|
|
pos = s_rect.topLeft();
|
|
|
|
if( pos.y() + height > drect.bottom() )
|
|
|
|
pos.setY( kMax( drect.top(), drect.bottom() - height ) );
|
|
|
|
if( pos.x() + width > drect.right() )
|
|
|
|
pos.setX( kMax( drect.left(), drect.right() - width ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const TQRect r = TQRect( TQToolTip::parentWidget()->mapToGlobal( TQToolTip::parentWidget()->pos() ), TQToolTip::parentWidget()->size() );
|
|
|
|
pos = r.bottomRight();
|
|
|
|
if( pos.y() + height > drect.bottom() )
|
|
|
|
pos.setY( kMax( drect.top(), r.top() - height ) );
|
|
|
|
if( pos.x() + width > drect.right() )
|
|
|
|
pos.setX( kMax( drect.left(), r.left() - width ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
move( pos );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "tooltip.moc"
|