summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tdegtk/Makefile.am9
-rw-r--r--tdegtk/tdegtk-animations.cpp436
-rw-r--r--tdegtk/tdegtk-animations.h337
-rw-r--r--tdegtk/tdegtk-baseengine.cpp27
-rw-r--r--tdegtk/tdegtk-baseengine.h83
-rw-r--r--tdegtk/tdegtk-datamap.h170
-rw-r--r--tdegtk/tdegtk-draw.cpp12
-rw-r--r--tdegtk/tdegtk-genericengine.h112
-rw-r--r--tdegtk/tdegtk-tabwidgetdata.cpp308
-rw-r--r--tdegtk/tdegtk-tabwidgetdata.h189
-rw-r--r--tdegtk/tdegtk-tabwidgetengine.h109
11 files changed, 1788 insertions, 4 deletions
diff --git a/tdegtk/Makefile.am b/tdegtk/Makefile.am
index 26f45dd..4d18449 100644
--- a/tdegtk/Makefile.am
+++ b/tdegtk/Makefile.am
@@ -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
diff --git a/tdegtk/tdegtk-animations.cpp b/tdegtk/tdegtk-animations.cpp
new file mode 100644
index 0000000..54aea87
--- /dev/null
+++ b/tdegtk/tdegtk-animations.cpp
@@ -0,0 +1,436 @@
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <[email protected]>
+* Copyright (c) 2010 Ruslan Kabatsayev <[email protected]>
+*
+* 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;
+
+ }
diff --git a/tdegtk/tdegtk-animations.h b/tdegtk/tdegtk-animations.h
new file mode 100644
index 0000000..17fc873
--- /dev/null
+++ b/tdegtk/tdegtk-animations.h
@@ -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 <[email protected]>
+*
+* 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
+
diff --git a/tdegtk/tdegtk-baseengine.cpp b/tdegtk/tdegtk-baseengine.cpp
new file mode 100644
index 0000000..c6eb4de
--- /dev/null
+++ b/tdegtk/tdegtk-baseengine.cpp
@@ -0,0 +1,27 @@
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <[email protected]>
+*
+* 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 ); }
diff --git a/tdegtk/tdegtk-baseengine.h b/tdegtk/tdegtk-baseengine.h
new file mode 100644
index 0000000..85c28d2
--- /dev/null
+++ b/tdegtk/tdegtk-baseengine.h
@@ -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 <[email protected]>
+*
+* 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
+
diff --git a/tdegtk/tdegtk-datamap.h b/tdegtk/tdegtk-datamap.h
new file mode 100644
index 0000000..e82cdc0
--- /dev/null
+++ b/tdegtk/tdegtk-datamap.h
@@ -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 <[email protected]>
+*
+* 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
+
diff --git a/tdegtk/tdegtk-draw.cpp b/tdegtk/tdegtk-draw.cpp
index 77c0b7c..a4788f2 100644
--- a/tdegtk/tdegtk-draw.cpp
+++ b/tdegtk/tdegtk-draw.cpp
@@ -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);
}
diff --git a/tdegtk/tdegtk-genericengine.h b/tdegtk/tdegtk-genericengine.h
new file mode 100644
index 0000000..236ab60
--- /dev/null
+++ b/tdegtk/tdegtk-genericengine.h
@@ -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 <[email protected]>
+*
+* 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
+
diff --git a/tdegtk/tdegtk-tabwidgetdata.cpp b/tdegtk/tdegtk-tabwidgetdata.cpp
new file mode 100644
index 0000000..19d70b8
--- /dev/null
+++ b/tdegtk/tdegtk-tabwidgetdata.cpp
@@ -0,0 +1,308 @@
+/*
+* this file was largely taken from the oxygen gtk engine
+* Copyright (c) 2010 Hugo Pereira Da Costa <[email protected]>
+*
+* 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();
+
+ }
+
+
diff --git a/tdegtk/tdegtk-tabwidgetdata.h b/tdegtk/tdegtk-tabwidgetdata.h
new file mode 100644
index 0000000..e7284bf
--- /dev/null
+++ b/tdegtk/tdegtk-tabwidgetdata.h
@@ -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 <[email protected]>
+*
+* 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
+
diff --git a/tdegtk/tdegtk-tabwidgetengine.h b/tdegtk/tdegtk-tabwidgetengine.h
new file mode 100644
index 0000000..6ec74d9
--- /dev/null
+++ b/tdegtk/tdegtk-tabwidgetengine.h
@@ -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 <[email protected]>
+*
+* 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
+