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

437 lines
17 KiB

/*
* this file was largely taken from the oxygen gtk engine
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
* Copyright (c) 2010 Ruslan Kabatsayev <b7.10110111@gmail.com>
*
* 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;
}