You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gtk3-tqt-engine/tdegtk/tdegtk-widgetlookup.cpp

232 lines
6.8 KiB

/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
*
* Hook-setup code provided by Ruslan
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#include "tdegtk-widgetlookup.h"
#include "config.h"
#include <iostream>
#include <cairo/cairo-gobject.h>
// #define TDEGTK_DEBUG 1
//__________________________________________________________________
WidgetLookup::WidgetLookup( void ):
_hooksInitialized( false ),
_context( 0L )
{}
//_____________________________________________________
WidgetLookup::~WidgetLookup( void )
{
// disconnect hooks
_drawHook.disconnect();
}
//_____________________________________________________
void WidgetLookup::initializeHooks( void )
{
#if TDEGTK_DEBUG
std::cerr << "Oxygen::WidgetLookup::initializeHooks" << std::endl;
#endif
if( _hooksInitialized ) return;
// install hook and test
if( !_drawHook.connect( "draw", (GSignalEmissionHook)drawHook, this ) ) return;
// set initialization flag
_hooksInitialized = true;
return;
}
//_____________________________________________________
GtkWidget* WidgetLookup::find( cairo_t* context, const GtkWidgetPath* path ) const
{
// check path
if( !path ) return 0L;
// get length and check
const gint length( gtk_widget_path_length( path ) );
if( length < 1 ) return 0L;
// lookup last type
return find( context, gtk_widget_path_iter_get_object_type( path, length-1 ) );
}
//_____________________________________________________
GtkWidget* WidgetLookup::find( cairo_t* context, GType type ) const
{
// check context
if( context != _context )
{
#if TDEGTK_DEBUG
std::cerr << "Oxygen::WidgetLookup::find - invalid context: " << context << std::endl;
#endif
return 0L;
}
#if TDEGTK_DEBUG
std::cerr
<< "Oxygen::WidgetLookup::find -"
<< " context: " << context
<< " type: " << g_type_name( type )
<< std::endl;
#endif
// look for type in stored widgets
/* we loop backward, since last added widgets are more likely to be looked up */
for( WidgetList::const_reverse_iterator iter = _widgets.rbegin(); iter != _widgets.rend(); ++iter )
{
// compare types and return if matched
if( G_OBJECT_TYPE( *iter ) == type )
{
#if TDEGTK_DEBUG
std::cerr
<< "Oxygen::WidgetLookup::find -"
<< " context: " << context
<< " type: " << g_type_name( type )
<< " found: " << *iter
<< std::endl;
#endif
return *iter;
}
}
#if TDEGTK_DEBUG
std::cerr
<< "Oxygen::WidgetLookup::find -"
<< " context: " << context
<< " type: " << g_type_name( type )
<< " - no match found"
<< std::endl;
#endif
return 0L;
}
//_____________________________________________________
void WidgetLookup::bind( GtkWidget* widget, cairo_t* context )
{
// check if context has changed and clear widgets if yes
if( context != _context )
{
#if TDEGTK_DEBUG
std::cerr
<< "Oxygen::WidgetLookup::bind -"
<< " context: " << _context
<< " widgets: " << _widgets.size()
<< std::endl;
#endif
_context = context;
_widgets.clear();
}
_widgets.push_back( widget );
// add to all widgets map
if( _allWidgets.find( widget ) == _allWidgets.end() )
{
Signal destroyId;
destroyId.connect( G_OBJECT( widget ), "destroy", G_CALLBACK( destroyNotifyEvent ), this );
_allWidgets.insert( std::make_pair( widget, destroyId ) );
}
}
//____________________________________________________________________________________________
void WidgetLookup::unregisterWidget( GtkWidget* widget )
{
#if TDEGTK_DEBUG
std::cerr << "Oxygen::WidgetLookup::unregisterWidget - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
#endif
// find in map
WidgetMap::iterator iter( _allWidgets.find( widget ) );
assert( iter != _allWidgets.end() );
// disconnect signal
iter->second.disconnect();
// erase from lists
_allWidgets.erase( widget );
_widgets.remove( widget );
}
//_____________________________________________________
gboolean WidgetLookup::drawHook( GSignalInvocationHint*, guint numParams, const GValue* params, gpointer data )
{
// check number of parameters
if( numParams < 2 ) return FALSE;
// get widget from params
GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );
// check type
if( !GTK_IS_WIDGET( widget ) ) return FALSE;
// check second parameter type.
if( !G_VALUE_HOLDS( params+1, CAIRO_GOBJECT_TYPE_CONTEXT ) )
{ return FALSE; }
// retrieve context and cast
cairo_t* context( static_cast<cairo_t*>( g_value_get_boxed(params+1) ) );
#if TDEGTK_DEBUG
std::cerr
<< "Oxygen::WidgetLookup::drawHook -"
<< " widget: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")"
<< " context: " << context
<< std::endl;
#endif
// bind widget and context
static_cast<WidgetLookup*>( data )->bind( widget, context );
return TRUE;
}
//____________________________________________________________________________________________
gboolean WidgetLookup::destroyNotifyEvent( GtkWidget* widget, gpointer data )
{
static_cast<WidgetLookup*>(data)->unregisterWidget( widget );
return FALSE;
}