Add tab prelighting support

pull/1/head
Timothy Pearson 12 years ago
parent 0bf8ed2645
commit a66a6bbf0a

@ -11,6 +11,12 @@ source_h = \
$(srcdir)/tdegtk-signals.h \
$(srcdir)/tdegtk-widgetlookup.h \
$(srcdir)/tdegtk-utils.h \
$(srcdir)/tdegtk-tabwidgetdata.h \
$(srcdir)/tdegtk-animations.h \
$(srcdir)/tdegtk-datamap.h \
$(srcdir)/tdegtk-baseengine.h \
$(srcdir)/tdegtk-genericengine.h \
$(srcdir)/tdegtk-tabwidgetengine.h \
$(srcdir)/tdegtk-types.h
source_c = \
@ -25,6 +31,9 @@ source_c = \
$(srcdir)/tdegtk-signals.cpp \
$(srcdir)/tdegtk-widgetlookup.cpp \
$(srcdir)/tdegtk-utils.cpp \
$(srcdir)/tdegtk-tabwidgetdata.cpp \
$(srcdir)/tdegtk-animations.cpp \
$(srcdir)/tdegtk-baseengine.cpp \
$(srcdir)/tdegtk-theme.cpp
enginedir = $(libdir)/gtk-3.0/$(GTK_VERSION)/theming-engines

@ -0,0 +1,436 @@
/*
* 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>
*
* 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-animations.h"
#include "tdegtk-utils.h"
#include "../config.h"
#include <cassert>
#include <iostream>
//_________________________________________
Animations::Animations( void ):
_innerShadowsEnabled( true ),
_hooksInitialized( false )
{
#if OXYGEN_DEBUG
std::cerr << "Oxygen::Animations::Animations" << std::endl;
#endif
// create engines
#if 0
registerEngine( _backgroundHintEngine = new BackgroundHintEngine( this ) );
registerEngine( _comboBoxEngine = new ComboBoxEngine( this ) );
registerEngine( _comboBoxEntryEngine = new ComboBoxEntryEngine( this ) );
registerEngine( _dialogEngine = new DialogEngine( this ) );
registerEngine( _groupBoxEngine = new GroupBoxEngine( this ) );
registerEngine( _groupBoxLabelEngine = new GroupBoxLabelEngine( this ) );
registerEngine( _hoverEngine = new HoverEngine( this ) );
registerEngine( _mainWindowEngine = new MainWindowEngine( this ) );
registerEngine( _menuItemEngine = new MenuItemEngine( this ) );
registerEngine( _panedEngine = new PanedEngine( this ) );
registerEngine( _scrollBarEngine = new ScrollBarEngine( this ) );
registerEngine( _scrolledWindowEngine = new ScrolledWindowEngine( this ) );
registerEngine( _innerShadowEngine = new InnerShadowEngine( this ) );
#endif
registerEngine( _tabWidgetEngine = new TabWidgetEngine( this ) );
#if 0
registerEngine( _treeViewEngine = new TreeViewEngine( this ) );
registerEngine( _widgetSizeEngine = new WidgetSizeEngine( this ) );
// animations specific engines
registerEngine( _widgetStateEngine = new WidgetStateEngine( this ) );
registerEngine( _arrowStateEngine = new ArrowStateEngine( this ) );
registerEngine( _scrollBarStateEngine = new ScrollBarStateEngine( this ) );
registerEngine( _tabWidgetStateEngine = new TabWidgetStateEngine( this ) );
registerEngine( _treeViewStateEngine = new TreeViewStateEngine( this ) );
registerEngine( _menuBarStateEngine = new MenuBarStateEngine( this ) );
registerEngine( _menuStateEngine = new MenuStateEngine( this ) );
registerEngine( _toolBarStateEngine = new ToolBarStateEngine( this ) );
#endif
}
//____________________________________________________________________________________________
Animations::~Animations( void )
{
#if OXYGEN_DEBUG
std::cerr << "Oxygen::Animations::~Animations" << std::endl;
#endif
// delete all engines
for( BaseEngine::List::iterator iter = _engines.begin(); iter != _engines.end(); ++iter )
{ delete *iter; }
// disconnect all signals from map
for( WidgetMap::iterator iter = _allWidgets.begin(); iter != _allWidgets.end(); iter++ )
{ iter->second.disconnect(); }
// clear hooks
_backgroundHintHook.disconnect();
_sizeAllocationHook.disconnect();
_realizationHook.disconnect();
_innerShadowHook.disconnect();
}
#if 0
//_________________________________________
void Animations::initialize( const QtSettings& settings )
{
const bool animationsEnabled( settings.animationsEnabled() );
// pass animations configuration to engines
widgetStateEngine().setEnabled( animationsEnabled && settings.genericAnimationsEnabled() );
widgetStateEngine().setDuration( settings.genericAnimationsDuration() );
arrowStateEngine().setEnabled( animationsEnabled && settings.genericAnimationsEnabled() );
arrowStateEngine().setDuration( settings.genericAnimationsDuration() );
scrollBarStateEngine().setEnabled( animationsEnabled && settings.genericAnimationsEnabled() );
scrollBarStateEngine().setDuration( settings.genericAnimationsDuration() );
tabWidgetStateEngine().setEnabled( animationsEnabled && settings.genericAnimationsEnabled() );
tabWidgetStateEngine().setDuration( settings.genericAnimationsDuration() );
treeViewStateEngine().setEnabled( animationsEnabled && settings.genericAnimationsEnabled() );
treeViewStateEngine().setDuration( settings.genericAnimationsDuration() );
menuBarStateEngine().setAnimationsEnabled( animationsEnabled && (settings.menuBarAnimationType() != None) );
menuBarStateEngine().setFollowMouse( settings.menuBarAnimationType() == FollowMouse );
menuBarStateEngine().setDuration( settings.menuBarAnimationsDuration() );
menuBarStateEngine().setFollowMouseAnimationsDuration( settings.menuBarFollowMouseAnimationsDuration() );
menuStateEngine().setEnabled( animationsEnabled && (settings.menuAnimationType() != None) );
menuStateEngine().setFollowMouse( settings.menuAnimationType() == FollowMouse );
menuStateEngine().setDuration( settings.menuAnimationsDuration() );
menuStateEngine().setFollowMouseAnimationsDuration( settings.menuFollowMouseAnimationsDuration() );
// for now, only Fade animations mode is supported for toolbar animations
toolBarStateEngine().setEnabled( animationsEnabled && (settings.toolBarAnimationType() != None) );
toolBarStateEngine().setFollowMouse( settings.toolBarAnimationType() == FollowMouse );
toolBarStateEngine().setDuration( settings.genericAnimationsDuration() );
toolBarStateEngine().setFollowMouseAnimationsDuration( settings.toolBarAnimationsDuration() );
}
#endif
//____________________________________________________________________________________________
void Animations::initializeHooks( void )
{
if( _hooksInitialized ) return;
#if 0
_backgroundHintHook.connect( "realize", (GSignalEmissionHook)backgroundHintHook, this );
#if ENABLE_INNER_SHADOWS_HACK
if(!getenv("OXYGEN_DISABLE_INNER_SHADOWS_HACK"))
{ _innerShadowHook.connect( "realize", (GSignalEmissionHook)innerShadowHook, this ); }
#endif
#endif
_sizeAllocationHook.connect( "size-allocate", (GSignalEmissionHook)sizeAllocationHook, this );
_realizationHook.connect( "realize", (GSignalEmissionHook)realizationHook, this );
_hooksInitialized = true;
}
//____________________________________________________________________________________________
bool Animations::registerWidget( GtkWidget* widget )
{
if( _allWidgets.find( widget ) != _allWidgets.end() ) return false;
#if OXYGEN_DEBUG
std::cerr << "Oxygen::Animations::registerWidget - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
#endif
Signal destroyId;
destroyId.connect( G_OBJECT( widget ), "destroy", G_CALLBACK( destroyNotifyEvent ), this );
_allWidgets.insert( std::make_pair( widget, destroyId ) );
return true;
}
//____________________________________________________________________________________________
void Animations::unregisterWidget( GtkWidget* widget )
{
#if OXYGEN_DEBUG
std::cerr << "Oxygen::Animations::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 map
_allWidgets.erase( widget );
// erase from all maps
for( BaseEngine::List::iterator iter = _engines.begin(); iter != _engines.end(); ++iter )
{ (*iter)->unregisterWidget( widget ); }
}
//____________________________________________________________________________________________
void Animations::setEnabled( bool value )
{
for( BaseEngine::List::iterator iter = _engines.begin(); iter != _engines.end(); ++iter )
{ (*iter)->setEnabled( value ); }
}
//____________________________________________________________________________________________
gboolean Animations::destroyNotifyEvent( GtkWidget* widget, gpointer data )
{
static_cast<Animations*>(data)->unregisterWidget( widget );
return FALSE;
}
//____________________________________________________________________________________________
gboolean Animations::sizeAllocationHook( GSignalInvocationHint*, guint, const GValue* params, gpointer data )
{
// get widget from params
GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );
// check type
if( !GTK_IS_WIDGET( widget ) ) return FALSE;
// comboboxes
/*
need to force the wrap-width property to 0,
otherwise the "appears-as-list" flag is not respected, which additionally breaks the widget rendering.
This has to be done soon enoug to avoid crash with latest gtk3 versions
*/
if(
GTK_IS_COMBO_BOX( widget ) &&
Gtk::gtk_combobox_appears_as_list( widget ) &&
!gtk_combo_box_get_has_entry( GTK_COMBO_BOX( widget ) ) )
{
gtk_combo_box_set_wrap_width( GTK_COMBO_BOX( widget ), 0 );
return TRUE;
}
#if GTK_CHECK_VERSION( 3, 5, 0 )
/*
HACK: Somehow, style_updated method for GtkRange widgets is not called anymore
as soon as we (oxygen-gtk) install our hooks. This prevents some settings to be
properly initialized, such as the slider length, or the arrows for scrollbars.
Therefore we explicitly call the styleUpdated function ourselves.
*/
if( GTK_IS_RANGE( widget ) )
{
// get class
GtkWidgetClass* widgetClass = GTK_WIDGET_GET_CLASS( widget );
if( widgetClass && widgetClass->style_updated )
{ (*widgetClass->style_updated)(widget); }
}
#endif
// groupbox labels
#if ENABLE_GROUPBOX_HACK
if( static_cast<Animations*>( data )->groupBoxLabelEngine().contains( widget ) )
{
static_cast<Animations*>( data )->groupBoxLabelEngine().adjustSize( widget );
return TRUE;
}
#endif
#if ENABLE_COMBOBOX_LIST_RESIZE
// comboboxes
if( !GTK_IS_WINDOW( widget ) ) return TRUE;
GtkWindow* window( GTK_WINDOW( widget ) );
if( gtk_window_get_type_hint( window ) != GDK_WINDOW_TYPE_HINT_COMBO ) return TRUE;
Animations& animations( *static_cast<Animations*>(data) );
GtkWidget* combobox = animations.comboBoxEngine().find( widget );
if( !combobox ) combobox = animations.comboBoxEntryEngine().find( widget );
if( !combobox ) return true;
int w, h;
gtk_window_get_size( window, &w, &h );
gint sourceX, sourceY;
gint targetX, targetY;
gtk_window_get_position( window, &sourceX, &sourceY );
gdk_window_get_origin( gtk_widget_get_window( combobox ), &targetX, &targetY );
// store allocations
const GtkAllocation comboAllocation( Gtk::gtk_widget_get_allocation( combobox ) );
const GtkAllocation widgetAllocation( Gtk::gtk_widget_get_allocation( widget ) );
const bool widthChanged( widgetAllocation.width != comboAllocation.width - 6 );
const bool positionChanged( sourceX != targetX + comboAllocation.x + 3 );
#if OXYGEN_DEBUG
std::cerr
<< "Animations::comboBoxHook -"
<< " widget: " << widget
<< " widthChanged: " << widthChanged
<< " positionChanged: " << positionChanged
<< std::endl;
#endif
int uglyShadowWidth=!Gtk::gdk_default_screen_is_composited();
// perform move-resize
if( widthChanged && positionChanged )
{
gdk_window_move_resize(
gtk_widget_get_window( widget ),
targetX + comboAllocation.x + 3 - uglyShadowWidth, sourceY,
comboAllocation.width - 6 + 2*uglyShadowWidth, widgetAllocation.height );
} else if( widthChanged ) {
gdk_window_resize(
gtk_widget_get_window( widget ),
comboAllocation.width - 6 + 2*uglyShadowWidth, widgetAllocation.height );
} else if( positionChanged ) {
gdk_window_move(
gtk_widget_get_window( widget ),
targetX + comboAllocation.x + 3 - uglyShadowWidth, sourceY );
}
#endif
return true;
}
#if 0
//____________________________________________________________________________________________
gboolean Animations::backgroundHintHook( GSignalInvocationHint*, guint, const GValue* params, gpointer data )
{
// get widget from params
GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );
// check type
if( !GTK_IS_WIDGET( widget ) ) return FALSE;
if( !GTK_IS_WINDOW( widget ) ) return TRUE;
Animations& animations( *static_cast<Animations*>(data) );
animations.backgroundHintEngine().registerWidget( widget );
return TRUE;
}
//____________________________________________________________________________________________
gboolean Animations::innerShadowHook( GSignalInvocationHint*, guint, const GValue* params, gpointer data )
{
// get widget from params
GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );
// check type
if( !GTK_IS_WIDGET( widget ) ) return FALSE;
// check enabled state
Animations& animations( *static_cast<Animations*>(data) );
if( !animations.innerShadowsEnabled() ) return TRUE;
// blacklist
if( Gtk::g_object_is_a( G_OBJECT( widget ), "SwtFixed" ) ) return TRUE;
if( Gtk::g_object_is_a( G_OBJECT( widget ), "GtkPizza" ) ) return TRUE;
if( Gtk::g_object_is_a( G_OBJECT( widget ), "MessageList") ) return TRUE;
GtkWidget* parent(gtk_widget_get_parent(widget));
if( !GTK_IS_SCROLLED_WINDOW( parent ) ) return TRUE;
GtkWidget* child(gtk_bin_get_child(GTK_BIN(parent)));
if(child!=widget) return TRUE;
#if OXYGEN_DEBUG
std::cerr
<< "Oxygen::Animations::innerShadowHook -"
<< " widget: " << widget << " (" << G_OBJECT_TYPE_NAME(widget) << ")"
<< " parent: " << parent << " (" << G_OBJECT_TYPE_NAME(parent) << ")"
<< " widget path: " << Gtk::gtk_widget_path( widget )
<< " isTreeView: " << (GTK_IS_TREE_VIEW(widget)?"true":"false")
<< " isTextView: " << (GTK_IS_TEXT_VIEW(widget)?"true":"false")
<< std::endl;
#endif
animations.innerShadowEngine().registerWidget( parent );
animations.innerShadowEngine().registerChild( parent, widget );
return TRUE;
}
#endif
//____________________________________________________________________________________________
gboolean Animations::realizationHook( GSignalInvocationHint*, guint, const GValue* params, gpointer data )
{
// get widget from params
GtkWidget* widget( GTK_WIDGET( g_value_get_object( params ) ) );
// check type
if( !GTK_IS_WIDGET( widget ) ) return FALSE;
if( GTK_IS_NOTEBOOK( widget ) )
{ gtk_notebook_set_show_border( GTK_NOTEBOOK(widget), FALSE ); }
#if ENABLE_GROUPBOX_HACK
if( GTK_IS_LABEL( widget ) && GTK_IS_FRAME( gtk_widget_get_parent( widget ) ) )
{
GtkFrame *frame( GTK_FRAME( gtk_widget_get_parent( widget ) ) );
if( widget == gtk_frame_get_label_widget( frame ) && !Gtk::gtk_widget_find_parent( widget, "GtkPizza" ) )
{
#if OXYGEN_DEBUG
std::cout
<< "Oxygen::Animations::realizationHook -"
<< " widget: " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")"
<< " parent: " << frame << " (" << G_OBJECT_TYPE_NAME( frame ) << ")"
<< std::endl;
#endif
// modify alignment
gtk_frame_set_label_align( frame, 0.5, 0.0 );
gtk_frame_set_shadow_type( frame, GTK_SHADOW_OUT );
// register to engine
static_cast<Animations*>( data )->groupBoxLabelEngine().registerWidget( widget );
static_cast<Animations*>( data )->groupBoxLabelEngine().adjustSize( widget );
}
}
#endif
return TRUE;
}

@ -0,0 +1,337 @@
#ifndef tdegtk_animations_h
#define tdegtk_animations_h
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* 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-arrowstateengine.h"
// #include "tdegtk-backgroundhintengine.h"
#include "tdegtk-baseengine.h"
// #include "tdegtk-comboboxengine.h"
// #include "tdegtk-comboboxentryengine.h"
// #include "tdegtk-dialogengine.h"
// #include "tdegtk-groupboxengine.h"
// #include "tdegtk-groupboxlabelengine.h"
#include "tdegtk-hooks.h"
// #include "tdegtk-hoverengine.h"
// #include "tdegtk-mainwindowengine.h"
// #include "tdegtk-menubarstateengine.h"
// #include "tdegtk-menuitemengine.h"
// #include "tdegtk-menustateengine.h"
// #include "tdegtk-panedengine.h"
// #include "tdegtk-scrollbarengine.h"
// #include "tdegtk-scrollbarstateengine.h"
// #include "tdegtk-scrolledwindowengine.h"
// #include "tdegtk-innershadowengine.h"
#include "tdegtk-signals.h"
#include "tdegtk-tabwidgetengine.h"
// #include "tdegtk-tabwidgetstateengine.h"
// #include "tdegtk-toolbarstateengine.h"
// #include "tdegtk-treeviewengine.h"
// #include "tdegtk-treeviewstateengine.h"
// #include "tdegtk-widgetsizeengine.h"
// #include "tdegtk-widgetstateengine.h"
#include <gtk/gtk.h>
#include <vector>
#include <map>
//! keeps track of all animation engines
class Animations
{
public:
//! constructor
Animations( void );
//! destructor
virtual ~Animations( void );
//! initialize settings
// void initialize( const QtSettings& );
//! initialize hooks
void initializeHooks( void );
//! unregister widget
bool registerWidget( GtkWidget* );
//! unregister widget
void unregisterWidget( GtkWidget* );
//! enabled state
void setEnabled( bool value );
#if 0
//! inner shadow enabled state
void setInnerShadowsEnabled( bool value )
{ _innerShadowsEnabled = value; }
//! inner shadow enabled state
bool innerShadowsEnabled( void ) const
{ return _innerShadowsEnabled; }
//! combobox engine
ComboBoxEngine& comboBoxEngine( void ) const
{ return *_comboBoxEngine; }
//! comboboxentry engine
ComboBoxEntryEngine& comboBoxEntryEngine( void ) const
{ return *_comboBoxEntryEngine; }
//! dialog engine
DialogEngine& dialogEngine( void ) const
{ return *_dialogEngine; }
//! groupbox engine
GroupBoxEngine& groupBoxEngine( void ) const
{ return *_groupBoxEngine; }
//! background hint
BackgroundHintEngine& backgroundHintEngine( void ) const
{ return *_backgroundHintEngine; }
//! main window engine
MainWindowEngine& mainWindowEngine( void ) const
{ return *_mainWindowEngine; }
//! menu item engine
MenuItemEngine& menuItemEngine( void ) const
{ return *_menuItemEngine; }
//! hover engine
HoverEngine& hoverEngine( void ) const
{ return *_hoverEngine; }
//! paned (splitter) engine
PanedEngine& panedEngine( void ) const
{ return *_panedEngine; }
//! scrollbar engine
ScrollBarEngine& scrollBarEngine( void ) const
{ return *_scrollBarEngine; }
//! scrolled window engine
ScrolledWindowEngine& scrolledWindowEngine( void ) const
{ return *_scrolledWindowEngine; }
//! inner shadow engine
InnerShadowEngine& innerShadowEngine( void ) const
{ return *_innerShadowEngine; }
#endif
//! tab widget engine
TabWidgetEngine& tabWidgetEngine( void ) const
{ return *_tabWidgetEngine; }
#if 0
//! tree view engine
TreeViewEngine& treeViewEngine( void ) const
{ return *_treeViewEngine; }
//! window size engine
WidgetSizeEngine& widgetSizeEngine( void ) const
{ return *_widgetSizeEngine; }
//!@name animations specific engines
//@{
//! widget mouse-over and focus animations engine
WidgetStateEngine& widgetStateEngine( void ) const
{ return *_widgetStateEngine; }
//! arrow mouse-over animations engine
ArrowStateEngine& arrowStateEngine( void ) const
{ return *_arrowStateEngine; }
//! scrollbar arrow mouse-over animations engine
ScrollBarStateEngine& scrollBarStateEngine( void ) const
{ return *_scrollBarStateEngine; }
//! notebook tabs mouse-over animations engine
TabWidgetStateEngine& tabWidgetStateEngine( void ) const
{ return *_tabWidgetStateEngine; }
//! tree view mouse-over animation engine
TreeViewStateEngine& treeViewStateEngine( void ) const
{ return *_treeViewStateEngine; }
//! menubar mouse-over animation engine
MenuBarStateEngine& menuBarStateEngine( void ) const
{ return *_menuBarStateEngine; }
//! menu mouse-over animation engine
MenuStateEngine& menuStateEngine( void ) const
{ return *_menuStateEngine; }
//! toolbar mouse-over animation engine
ToolBarStateEngine& toolBarStateEngine( void ) const
{ return *_toolBarStateEngine; }
#endif
//@}
protected:
//! register new engine
void registerEngine( BaseEngine* engine )
{ _engines.push_back( engine ); }
#if 0
//! groupbox engine
GroupBoxLabelEngine& groupBoxLabelEngine( void ) const
{ return *_groupBoxLabelEngine; }
#endif
//! destruction callback
static gboolean destroyNotifyEvent( GtkWidget*, gpointer );
//! combobox list size adjustment hook
static gboolean sizeAllocationHook( GSignalInvocationHint*, guint, const GValue*, gpointer );
#if 0
//! background hint setting hook
static gboolean backgroundHintHook( GSignalInvocationHint*, guint, const GValue*, gpointer );
//! inner shadow composited mode enabling hook
static gboolean innerShadowHook( GSignalInvocationHint*, guint, const GValue*, gpointer );
#endif
//! widget realize hook
static gboolean realizationHook( GSignalInvocationHint*, guint, const GValue*, gpointer );
private:
//! inner shadow enabled state
bool _innerShadowsEnabled;
//! list of engines
BaseEngine::List _engines;
#if 0
//! background hint engine
BackgroundHintEngine* _backgroundHintEngine;
//! combobox engine
ComboBoxEngine* _comboBoxEngine;
//! combobox entry engine
ComboBoxEntryEngine* _comboBoxEntryEngine;
//! dialog engine
DialogEngine* _dialogEngine;
//! groupbox engine
GroupBoxEngine* _groupBoxEngine;
//! groupbox engine
GroupBoxLabelEngine* _groupBoxLabelEngine;
//! hover engine
HoverEngine* _hoverEngine;
//! main window engine
MainWindowEngine* _mainWindowEngine;
//! menu item engine
MenuItemEngine* _menuItemEngine;
//! paned engine
PanedEngine* _panedEngine;
//! scrollbar engine
ScrollBarEngine* _scrollBarEngine;
//! scrolled window engine
ScrolledWindowEngine* _scrolledWindowEngine;
//! inner shadow engine
InnerShadowEngine* _innerShadowEngine;
#endif
//! tab widget engine
TabWidgetEngine* _tabWidgetEngine;
#if 0
//! tree view engine
TreeViewEngine* _treeViewEngine;
//! widget size engine
WidgetSizeEngine* _widgetSizeEngine;
//!@name Animation specific engines
//@{
//! widget mouse-over and focus animations engine
WidgetStateEngine* _widgetStateEngine;
//! arrow mouse-over animations engine
ArrowStateEngine* _arrowStateEngine;
//! scrollbar arrow mouse-over animations engine
ScrollBarStateEngine* _scrollBarStateEngine;
//! notebook tabs mouse-over animations engine
TabWidgetStateEngine* _tabWidgetStateEngine;
//! tree view mouse-over animation engine
TreeViewStateEngine* _treeViewStateEngine;
//! menubar mouse-over animation engine
MenuBarStateEngine* _menuBarStateEngine;
//! menu mouse-over animation engine
MenuStateEngine* _menuStateEngine;
//! toolbar mouse-over animation engine
ToolBarStateEngine* _toolBarStateEngine;
#endif
//@}
//!@name hooks
//@{
//! true when hooks are initialized
bool _hooksInitialized;
//! realization hook
Hook _realizationHook;
//! size allocation hook
Hook _sizeAllocationHook;
//! background hint hook
Hook _backgroundHintHook;
//! inner shadows hook
Hook _innerShadowHook;
//@}
//! keep track of all registered widgets, and associated destroy callback
typedef std::map< GtkWidget*, Signal > WidgetMap;
WidgetMap _allWidgets;
};
#endif

@ -0,0 +1,27 @@
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* 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-baseengine.h"
#include "tdegtk-animations.h"
//______________________________________________________
bool BaseEngine::registerWidget( GtkWidget* widget )
{ return parent().registerWidget( widget ); }

@ -0,0 +1,83 @@
#ifndef tdegtk_baseengine_h
#define tdegtk_baseengine_h
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* 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 <gtk/gtk.h>
#include <vector>
//! forward declaration
class Animations;
//! base class for all engines
/*! engines map pointers to GtkWidget to some data, needed for animations */
class BaseEngine
{
public:
//! constructor
BaseEngine( Animations* parent ):
_parent( parent ),
_enabled( true )
{}
virtual ~BaseEngine()
{}
//! register widget
virtual bool registerWidget( GtkWidget* widget );
//! unregister widget
virtual void unregisterWidget( GtkWidget* ) = 0;
//! engine list
typedef std::vector< BaseEngine* > List;
//! enable state
/*! returns true if changed */
virtual bool setEnabled( bool value )
{
if( _enabled == value ) return false;
_enabled = value;
return true;
}
//! enable state
bool enabled( void ) const
{ return _enabled; }
protected:
//! returns parent
virtual Animations& parent( void ) const
{ return *_parent; }
private:
//! parent
Animations* _parent;
//! enable flag
bool _enabled;
};
#endif

@ -0,0 +1,170 @@
#ifndef oxygendatamap_h
#define oxygendatamap_h
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* 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 <cassert>
#include <map>
#include <gtk/gtk.h>
//! generic class to map data to widgets
/*
Note: I'm not sure about memory management. At some point one might need to allocate the registered
data on the heap rather than on the stack, to be able to safely pass the data pointer around via callbacks.
The current implementation should make that possible without external code change, provided that the map
content is properly deleted (as opposed to erased) in destructor and 'unregister' method.
*/
template <typename T>
class DataMap
{
public:
//! constructor
DataMap( void ):
_lastWidget( 0L ),
_lastData( 0L )
{}
virtual ~DataMap(){}
//! insert new widget
inline T& registerWidget( GtkWidget* widget )
{
T& data( _map.insert( std::make_pair( widget, T() ) ).first->second );
_lastWidget = widget;
_lastData = &data;
return data;
}
//! true if widget is in list
virtual bool contains( GtkWidget* widget )
{
// check against last widget
if( widget == _lastWidget ) return true;
// find in map, returns false if not found
typename Map::iterator iter = _map.find( widget );
if( iter == _map.end() ) return false;
// store as last widget/last data, to speed up lookup.
_lastWidget = widget;
_lastData = &iter->second;
return true;
}
//! return value
virtual T& value( GtkWidget* widget )
{
// check against last widget
if( widget == _lastWidget ) return *_lastData;
// find in map, abort if not found
typename Map::iterator iter( _map.find( widget ) );
assert( iter != _map.end() );
// store as last widget/last data, to speed up lookup.
_lastWidget = widget;
_lastData = &iter->second;
return iter->second;
}
//! erase
virtual void erase( GtkWidget* widget )
{
// clear last widget and data, if match
if( _lastWidget == widget )
{
_lastWidget = 0L;
_lastData = 0L;
}
// erase from map
_map.erase( widget );
}
//! connect all widgets in map
void connectAll( void )
{
for( typename Map::iterator iter = _map.begin(); iter != _map.end(); iter++ )
{ iter->second.connect( iter->first ); }
}
//! connect all widgets in map
void disconnectAll( void )
{
for( typename Map::iterator iter = _map.begin(); iter != _map.end(); iter++ )
{ iter->second.disconnect( iter->first ); }
}
//! erase
virtual void clear( void )
{
_lastWidget = 0L;
_lastData = 0L;
_map.clear();
}
//! retrieve internal map
typedef std::map<GtkWidget*, T> Map;
Map& map( void )
{ return _map; }
//! retrieve internal map
const Map& map( void ) const
{ return _map; }
protected:
//! copy constructor is private
DataMap( const DataMap& )
{ assert( false ); }
//! assignment operator
DataMap& operator = ( const DataMap& )
{
assert( false );
return *this;
}
private:
//! pointer to last inquired widget
GtkWidget* _lastWidget;
//! pointer to last retrieved data
T* _lastData;
//! internal map between widget and data
Map _map;
};
#endif

@ -32,6 +32,7 @@
#include "tdegtk-types.h"
#include "tdegtk-widgetlookup.h"
#include "tdegtk-utils.h"
#include "tdegtk-animations.h"
#include "tqtcairopainter.h"
@ -49,6 +50,7 @@
p.drawRect(x, y, w, h);
WidgetLookup m_widgetLookup;
Animations m_animations;
// Keep this in sync with gtkToTQPaletteColorGroup() below
static TQColorGroup gtkToTQtColorGroup(GtkThemingEngine* engine, GtkStateFlags state) {
@ -662,11 +664,13 @@ tdegtk_draw_extension (DRAW_ARGS,
widget = m_widgetLookup.find(cr, path);
if (gtk_theming_engine_has_class(engine, GTK_STYLE_CLASS_NOTEBOOK)) {
// Register tabbar with animation engine
m_animations.tabWidgetEngine().registerWidget(widget);
// Check tab properties
const int tabIndex = Gtk::gtk_notebook_find_tab(widget, x+width/2, y+height/2);
// Style::instance().animations().tabWidgetEngine().updateTabRect(widget, tabIndex, x, y, width, height);
// bool prelight = (tabIndex == Style::instance().animations().tabWidgetEngine().hoveredTab(widget));
bool prelight = false;
m_animations.tabWidgetEngine().updateTabRect(widget, tabIndex, x, y, width, height);
bool prelight = (tabIndex == m_animations.tabWidgetEngine().hoveredTab(widget));
GtkNotebook* notebook = GTK_NOTEBOOK(widget);
// bool firstTab = (tabIndex == 0);
// bool lastTab = (tabIndex == gtk_notebook_get_n_pages(notebook)-1);
@ -725,7 +729,7 @@ tdegtk_draw_extension (DRAW_ARGS,
DRAW_FILLED_RECTANGLE_OVER_SPECIFIC_AREA(p2, brush, 0, 0, width, height)
// Draw tab
tqApp->style().drawControl(TQStyle::CE_TabBarTab, &p2, ceData, elementFlags, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE) | ((tabIndex==currentPage)?TQStyle::Style_Selected:TQStyle::Style_Default), tabOpt);
tqApp->style().drawControl(TQStyle::CE_TabBarTab, &p2, ceData, elementFlags, boundingRect, gtkToTQtColorGroup(engine, state), gtkToTQtStyleFlags(engine, state, TQT3WT_NONE) | ((tabIndex==currentPage)?TQStyle::Style_Selected:TQStyle::Style_Default) | ((prelight)?TQStyle::Style_MouseOver:TQStyle::Style_Default), tabOpt);
cairo_restore(cr);
}

@ -0,0 +1,112 @@
#ifndef tdegtk_genericengine_h
#define tdegtk_genericengine_h
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* 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-baseengine.h"
#include "tdegtk-datamap.h"
#include <gtk/gtk.h>
//! forward declaration
class Animations;
//! associates widgets with some type of data
template< typename T>
class GenericEngine: public BaseEngine
{
public:
//! constructor
GenericEngine( Animations* widget ):
BaseEngine( widget )
{}
//! destructor
virtual ~GenericEngine( void )
{}
//! register widget
virtual bool registerWidget( GtkWidget* widget )
{
if( _data.contains( widget ) ) return false;
if( enabled() )
{
T& data( _data.registerWidget( widget ) );
data.connect( widget );
} else _data.registerWidget( widget );
BaseEngine::registerWidget( widget );
return true;
}
//! unregister widget
virtual void unregisterWidget( GtkWidget* widget )
{
if( !_data.contains( widget ) ) return;
_data.value( widget ).disconnect( widget );
_data.erase( widget );
}
//! enabled state
/*! returns true if changed */
inline virtual bool setEnabled( bool value );
//! true if widget is included
virtual bool contains( GtkWidget* widget )
{ return _data.contains( widget ); }
protected:
//! return refence to data
virtual DataMap<T>& data( void )
{ return _data; }
//! return refence to data
virtual const DataMap<T>& data( void ) const
{ return _data; }
private:
//! map widgets to data
DataMap<T> _data;
};
//________________________________________________________________________
template< typename T> bool GenericEngine<T>::setEnabled( bool value )
{
if( enabled() == value ) return false;
BaseEngine::setEnabled( value );
if( enabled() ) _data.connectAll();
else _data.disconnectAll();
return true;
}
#endif

@ -0,0 +1,308 @@
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* the tabwidget data code is largely inspired from the gtk redmond engine
*
* 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-tabwidgetdata.h"
#include "tdegtk-utils.h"
#include "config.h"
#include <gtk/gtk.h>
#include <cassert>
#include <iostream>
//________________________________________________________________________________
void TabWidgetData::connect( GtkWidget* widget )
{
#if TDEGTK_DEBUG
std::cerr << "TDEGTK::TabWidgetData::connect - " << widget << std::endl;
#endif
_target = widget;
_motionId.connect( G_OBJECT(widget), "motion-notify-event", G_CALLBACK( motionNotifyEvent ), this );
_leaveId.connect( G_OBJECT(widget), "leave-notify-event", G_CALLBACK( leaveNotifyEvent ), this );
_pageAddedId.connect( G_OBJECT(widget), "page-added", G_CALLBACK( pageAddedEvent ), this );
updateRegisteredChildren( widget );
}
//________________________________________________________________________________
void TabWidgetData::disconnect( GtkWidget* widget )
{
#if TDEGTK_DEBUG
std::cerr << "TDEGTK::TabWidgetData::disconnect - " << widget << std::endl;
#endif
_target = 0L;
_motionId.disconnect();
_leaveId.disconnect();
_pageAddedId.disconnect();
// disconnect all children
for( ChildDataMap::iterator iter = _childrenData.begin(); iter != _childrenData.end(); ++iter )
{ iter->second.disconnect(); }
_childrenData.clear();
}
//________________________________________________________________________________
void TabWidgetData::updateHoveredTab( GtkWidget* widget )
{
if( !widget ) widget = _target;
if( !widget ) return;
// get pointer position
int xPointer(0), yPointer(0);
GdkDeviceManager* manager( gdk_display_get_device_manager( gtk_widget_get_display( widget ) ) );
GdkDevice* pointer( gdk_device_manager_get_client_pointer( manager ) );
if( !pointer ) return;
gdk_window_get_device_position( gtk_widget_get_window( widget ), pointer, &xPointer, &yPointer, 0L );
// loop over tabs and check matching
for( unsigned int i = (unsigned int)Gtk::gtk_notebook_find_first_tab( widget ); i < _tabRects.size(); i++ )
{
if( Gtk::gdk_rectangle_contains( &_tabRects[i], xPointer, yPointer ) )
{ setHoveredTab( widget, i ); return; }
}
// reset hovered tab
setHoveredTab( widget, -1 );
return;
}
//________________________________________________________________________________
void TabWidgetData::updateTabRect( GtkWidget* widget, int index, const GdkRectangle& r )
{
// make sure the vector has the right size
if( !GTK_IS_NOTEBOOK( widget ) ) return;
GtkNotebook* notebook = GTK_NOTEBOOK( widget );
_tabRects.resize( gtk_notebook_get_n_pages( notebook ), defaultRect() );
// check index against number of tabs
if( index < 0 || index >= (int)_tabRects.size() )
{ return; }
// store rectangle
_tabRects[index]=r;
}
//________________________________________________________________________________
void TabWidgetData::setDirty( bool value )
{
if( _dirty == value ) return;
_dirty = value;
if( _dirty && _target )
{
// we should only update the tabbar rect here
GdkRectangle updateRect;
Gtk::gtk_notebook_get_tabbar_rect( GTK_NOTEBOOK( _target ), &updateRect );
Gtk::gtk_widget_queue_draw( _target, &updateRect );
#if TDEGTK_DEBUG
std::cerr << "TDEGTK::TabWidgetData::setDirty - update: " << updateRect << std::endl;
#endif
}
}
//________________________________________________________________________________
bool TabWidgetData::isInTab( int x, int y ) const
{
// loop over tab rectangles and check.
for( RectangleList::const_iterator iter = _tabRects.begin(); iter != _tabRects.end(); ++iter )
{ if( Gtk::gdk_rectangle_contains( &(*iter), x, y ) ) return true; }
return false;
}
//________________________________________________________________________________
void TabWidgetData::setHoveredTab( GtkWidget* widget, int index )
{
if( _hoveredTab == index ) return;
_hoveredTab = index;
GdkRectangle updateRect( Gtk::gdk_rectangle() );
for( RectangleList::const_iterator iter = _tabRects.begin(); iter != _tabRects.end(); ++iter )
{ gdk_rectangle_union( &(*iter), &updateRect, &updateRect ); }
gtk_widget_queue_draw_area( widget, updateRect.x-4, updateRect.y-4, updateRect.width+8, updateRect.height+8 );
return;
}
//________________________________________________________________________________
gboolean TabWidgetData::motionNotifyEvent(GtkWidget* widget, GdkEventMotion*, gpointer data )
{
static_cast<TabWidgetData*>( data )->updateHoveredTab( widget );
return FALSE;
}
//________________________________________________________________________________
gboolean TabWidgetData::leaveNotifyEvent( GtkWidget* widget, GdkEventCrossing*, gpointer data )
{
// reset hovered tab
static_cast<TabWidgetData*>( data )->setHoveredTab( widget, -1 );
return FALSE;
}
//________________________________________________________________________________
void TabWidgetData::pageAddedEvent( GtkNotebook* parent, GtkWidget* child, guint, gpointer data)
{
#if TDEGTK_DEBUG
std::cerr << "TDEGTK::TabWidgetData::pageAddedEvent - " << child << std::endl;
#endif
static_cast<TabWidgetData*>(data)->updateRegisteredChildren( GTK_WIDGET( parent ) );
}
//________________________________________________________________________________
void TabWidgetData::updateRegisteredChildren( GtkWidget* widget )
{
if( !widget ) widget = _target;
if( !widget ) return;
// cast to notebook and check against number of pages
if( GTK_IS_NOTEBOOK( widget ) )
{
GtkNotebook* notebook( GTK_NOTEBOOK( widget ) );
for( int i = 0; i < gtk_notebook_get_n_pages( notebook ); ++i )
{
// retrieve page and tab label
GtkWidget* page( gtk_notebook_get_nth_page( notebook, i ) );
registerChild( gtk_notebook_get_tab_label( notebook, page ) );
}
}
}
//________________________________________________________________________________
void TabWidgetData::registerChild( GtkWidget* widget )
{
// do nothing if child is invalid (might happen: not checked at calling stage)
if( !widget ) return;
// make sure widget is not already in map
if( _childrenData.find( widget ) == _childrenData.end() )
{
#if TDEGTK_DEBUG
std::cerr << "TDEGTK::TabWidgetData::registerChild - " << widget << std::endl;
#endif
// allocate new ChildData
ChildData data;
data._destroyId.connect( G_OBJECT(widget), "destroy", G_CALLBACK( childDestroyNotifyEvent ), this );
data._enterId.connect( G_OBJECT(widget), "enter-notify-event", G_CALLBACK( childCrossingNotifyEvent ), this );
data._leaveId.connect( G_OBJECT(widget), "leave-notify-event", G_CALLBACK( childCrossingNotifyEvent ), this );
if( GTK_IS_CONTAINER( widget ) )
{ data._addId.connect( G_OBJECT(widget), "add", G_CALLBACK( childAddedEvent ), this ); }
// and insert in map
_childrenData.insert( std::make_pair( widget, data ) );
}
/*
also insert widget's children, recursively.
that should take care of buttons in tabs and other fancy stuff that applications mght do
*/
if( GTK_IS_CONTAINER( widget ) )
{
GList *children( gtk_container_get_children( GTK_CONTAINER(widget) ) );
for( GList* child = g_list_first(children); child; child = g_list_next(child) )
{ registerChild( GTK_WIDGET( child->data ) ); }
if( children ) g_list_free( children );
}
}
//________________________________________________________________________________
void TabWidgetData::unregisterChild( GtkWidget* widget )
{
ChildDataMap::iterator iter( _childrenData.find( widget ) );
if( iter == _childrenData.end() ) return;
#if TDEGTK_DEBUG
std::cerr << "TDEGTK::TabWidgetData::unregisterChild - " << widget << std::endl;
#endif
iter->second.disconnect();
_childrenData.erase( iter );
}
//____________________________________________________________________________________________
gboolean TabWidgetData::childDestroyNotifyEvent( GtkWidget* widget, gpointer data )
{
static_cast<TabWidgetData*>(data)->unregisterChild( widget );
return FALSE;
}
//____________________________________________________________________________________________
void TabWidgetData::childAddedEvent( GtkContainer* parent, GtkWidget*, gpointer data )
{
static_cast<TabWidgetData*>(data)->updateRegisteredChildren();
return;
}
//____________________________________________________________________________________________
gboolean TabWidgetData::childCrossingNotifyEvent( GtkWidget* widget, GdkEventCrossing*, gpointer data )
{
// retrieve widget's parent and check type
static_cast<TabWidgetData*>(data)->updateHoveredTab();
return FALSE;
}
//____________________________________________________________________________________________
void TabWidgetData::ChildData::disconnect( void )
{
_destroyId.disconnect();
_enterId.disconnect();
_leaveId.disconnect();
_addId.disconnect();
}

@ -0,0 +1,189 @@
#ifndef tdegtk_tabwidgetdata_h
#define tdegtk_widgetdata_h
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* 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-signals.h"
#include <gtk/gtk.h>
#include <vector>
#include <map>
//! detects and stores tab widget hovered tab
class TabWidgetData
{
public:
//! constructor
TabWidgetData( void ):
_target(0L),
_hoveredTab(-1),
_dragInProgress( false ),
_dirty( false )
{}
//! destructor
virtual ~TabWidgetData( void )
{ disconnect( _target ); }
//! setup connections
void connect( GtkWidget* );
//! disconnect
void disconnect( GtkWidget* );
//!@name modifiers
//@{
//! update tab rectangle
/* this is used to decide when a tab is hovered or not */
void updateTabRect( GtkWidget*, int, const GdkRectangle& );
//! update hovered tab
void updateHoveredTab( GtkWidget* = 0L );
//! true when drag is in progress
void setDragInProgress( bool value )
{ _dragInProgress = value; }
//! toggle dirty state
void toggleDirty( void )
{ setDirty( !isDirty() ); }
//! mark as dirty
void setDirty( bool );
//@}
//@name accessors
//@{
//! true if hovered
int hoveredTab( void ) const
{ return _hoveredTab; }
//! true when drag is in progress
bool dragInProgress( void ) const
{ return _dragInProgress; }
//! true if is dirty
bool isDirty( void ) const
{ return _dirty; }
//! returns true if provided point is in one tab of the widget
bool isInTab( int x, int y ) const;
//@]
protected:
//! set current tab
void setHoveredTab( GtkWidget*, int );
//! child registration
//@{
void updateRegisteredChildren( GtkWidget* = 0L );
void registerChild( GtkWidget* );
void unregisterChild( GtkWidget* );
//@}
//!@name static callbacks
//@{
static gboolean motionNotifyEvent( GtkWidget*, GdkEventMotion*, gpointer );
static gboolean leaveNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer );
static void pageAddedEvent( GtkNotebook*, GtkWidget*, guint, gpointer );
static gboolean childDestroyNotifyEvent( GtkWidget*, gpointer );
static gboolean childCrossingNotifyEvent( GtkWidget*, GdkEventCrossing*, gpointer );
static void childAddedEvent( GtkContainer*, GtkWidget*, gpointer );
//@}
private:
//! default tabRect size
GdkRectangle defaultRect( void ) const
{
GdkRectangle out = {0, 0, -1, -1};
return out;
}
//! target widget
GtkWidget* _target;
//!@name callbacks IDs
//@{
Signal _motionId;
Signal _leaveId;
Signal _pageAddedId;
//@}
//! index of currently hovered tab
int _hoveredTab;
//! true when there is a drag in progress
bool _dragInProgress;
//! true when tabbar is dirty
/*! a repaint is triggered of the full tabbar when set to true.
This forces the tabbar base to be redrawn event if the selected tab
has not been primarily damaged */
bool _dirty;
//! store rectangles matching tabs
typedef std::vector<GdkRectangle> RectangleList;
RectangleList _tabRects;
//! child data
/*!
one must keep track of the tab widgets children enter/leave event
to properly update tab hover because some tabs have embedded children.
This is notably the case for gimp, nautilus (in tabbed mode), etc.
*/
class ChildData
{
public:
//! constructor
ChildData( void )
{}
//! destructor
virtual ~ChildData( void )
{}
//! disconnect all signals
void disconnect( void );
Signal _destroyId;
Signal _addId;
Signal _enterId;
Signal _leaveId;
};
//! map registered children and corresponding data
typedef std::map<GtkWidget*, ChildData> ChildDataMap;
ChildDataMap _childrenData;
};
#endif

@ -0,0 +1,109 @@
#ifndef tdegtk_tabwidgetengine_h
#define tdegtk_tabwidgetengine_h
/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* 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-genericengine.h"
#include "tdegtk-datamap.h"
#include "tdegtk-tabwidgetdata.h"
#include <gtk/gtk.h>
//! forward declaration
class Animations;
//! stores data associated to editable tabwidgetes
/*!
ensures that the text entry and the button of editable tabwidgetes
gets hovered and focus flags at the same time
*/
class TabWidgetEngine: public GenericEngine<TabWidgetData>
{
public:
//! constructor
TabWidgetEngine( Animations* widget ):
GenericEngine<TabWidgetData>( widget )
{}
//! destructor
virtual ~TabWidgetEngine( void )
{}
//!@name modifiers
//@{
//! returns hovered tab, if any
void updateTabRect( GtkWidget* widget, int index, int x, int y, int w, int h )
{
GdkRectangle local = { x, y, w, h };
return data().value( widget ).updateTabRect( widget, index, local );
}
//! returns hovered tab, if any
void updateTabRect( GtkWidget* widget, int index, const GdkRectangle& r )
{ return data().value( widget ).updateTabRect( widget, index, r ); }
//! returns hovered tab, if any
void updateHoveredTab( GtkWidget* widget )
{ return data().value( widget ).updateHoveredTab( widget ); }
//! true when drag is in progress
void setDragInProgress( GtkWidget* widget, bool value )
{ data().value( widget ).setDragInProgress( value ); }
//! toggle dirty state
void toggleDirty( GtkWidget* widget )
{ data().value( widget ).toggleDirty(); }
//! true when tabbar is dirty
void setDirty( GtkWidget* widget, bool value )
{ data().value( widget ).setDirty( value ); }
//@}
//!@name accessors
//@{
//! returns hovered tab, if any
int hoveredTab( GtkWidget* widget )
{ return data().value( widget ).hoveredTab(); }
//! returns true if provided point is in one tab of the widget
bool isInTab( GtkWidget* widget, int x, int y )
{ return data().value( widget ).isInTab( x, y ); }
//! true when drag is in progress
bool dragInProgress( GtkWidget* widget )
{ return data().value( widget ).dragInProgress(); }
//! true when tabbar is dirty
bool isDirty( GtkWidget* widget )
{ return data().value( widget ).isDirty(); }
//@}
};
#endif
Loading…
Cancel
Save