File indexing completed on 2024-05-12 05:34:37

0001 /*
0002     this file is part of the oxygen gtk engine
0003     SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "oxygentreeviewstatedata.h"
0009 #include "../config.h"
0010 
0011 #include <iostream>
0012 
0013 namespace Oxygen
0014 {
0015 
0016     //_____________________________________________
0017     void TreeViewStateData::connect( GtkWidget* widget )
0018     {
0019 
0020         #if OXYGEN_DEBUG
0021         std::cerr << "Oxygen::TreeViewStateData::connect - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
0022         #endif
0023 
0024         _target = widget;
0025 
0026         // connect timeLines
0027         _current._timeLine.connect( (GSourceFunc)delayedUpdate, this );
0028         _previous._timeLine.connect( (GSourceFunc)delayedUpdate, this );
0029 
0030         // set directions
0031         _current._timeLine.setDirection( TimeLine::Forward );
0032         _previous._timeLine.setDirection( TimeLine::Backward );
0033 
0034     }
0035 
0036     //_____________________________________________
0037     void TreeViewStateData::disconnect( GtkWidget* widget )
0038     {
0039         #if OXYGEN_DEBUG
0040         std::cerr << "Oxygen::TreeViewStateData::disconnect - " << widget << " (" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
0041         #endif
0042 
0043         _current._timeLine.disconnect();
0044         _current._info.clear();
0045 
0046         _previous._timeLine.disconnect();
0047         _previous._info.clear();
0048 
0049         _target = 0L;
0050 
0051     }
0052 
0053     //_____________________________________________
0054     bool TreeViewStateData::updateState( const Gtk::CellInfo& info, bool state )
0055     {
0056         if( state && info != _current._info )
0057         {
0058 
0059             // stop current animation if running
0060             if( _current._timeLine.isRunning() ) _current._timeLine.stop();
0061 
0062             // stop previous animation if running
0063             if( _current._info.isValid() )
0064             {
0065                 if( _previous._timeLine.isRunning() ) _previous._timeLine.stop();
0066 
0067                 // update dirty rect, to make sure de-allocated cellInfo gets repainted
0068                 if( _previous._info.isValid() && GTK_IS_TREE_VIEW( _target ) )
0069                 { _dirtyRect = _previous._info.backgroundRect( GTK_TREE_VIEW( _target ) ); }
0070 
0071                 // move current tab info to previous
0072                 _previous._info = _current._info;
0073                 _previous._timeLine.start();
0074             }
0075 
0076             // assign new info to current and start animation
0077             _current._info = info;
0078             if( _current._info.isValid() ) _current._timeLine.start();
0079 
0080             return true;
0081 
0082         } else if( (!state) && info == _current._info ) {
0083 
0084             // stop current animation if running
0085             if( _current._timeLine.isRunning() ) _current._timeLine.stop();
0086 
0087             // stop previous animation if running
0088             if( _previous._timeLine.isRunning() ) _previous._timeLine.stop();
0089 
0090             // update dirty rect, to make sure de-allocated cellInfo gets repainted
0091             if( _previous._info.isValid() && GTK_IS_TREE_VIEW( _target ) )
0092             { _dirtyRect = _previous._info.backgroundRect( GTK_TREE_VIEW( _target ) ); }
0093 
0094             // move current tab info to previous
0095             _previous._info = _current._info;
0096             if( _previous._info.isValid() ) _previous._timeLine.start();
0097 
0098             // assign invalid info to current
0099             _current._info.clear();
0100 
0101             return true;
0102 
0103         } else return false;
0104 
0105     }
0106 
0107     //_____________________________________________
0108     GdkRectangle TreeViewStateData::dirtyRect( void )
0109     {
0110 
0111         GdkRectangle rect( Gtk::gdk_rectangle() );
0112         if( GTK_IS_TREE_VIEW( _target ) )
0113         {
0114             GtkTreeView* treeView( GTK_TREE_VIEW( _target ) );
0115 
0116             const GdkRectangle previousRect( _previous._info.backgroundRect( treeView ) );
0117             const GdkRectangle currentRect( _current._info.backgroundRect( treeView ) );
0118             if( Gtk::gdk_rectangle_is_valid( &previousRect ) && Gtk::gdk_rectangle_is_valid( &currentRect ) )
0119             {
0120 
0121                 gdk_rectangle_union( &previousRect, &currentRect, &rect );
0122 
0123             } else if( Gtk::gdk_rectangle_is_valid( &previousRect ) ) {
0124 
0125                 rect = previousRect;
0126 
0127             } else if( Gtk::gdk_rectangle_is_valid( &currentRect ) ) {
0128 
0129                 rect = currentRect;
0130 
0131             }
0132 
0133             // also union with dirty rect
0134             if( Gtk::gdk_rectangle_is_valid( &_dirtyRect ) )
0135             {
0136                 if( Gtk::gdk_rectangle_is_valid( &rect ) ) gdk_rectangle_union( &_dirtyRect, &rect, &rect );
0137                 else rect = _dirtyRect;
0138 
0139                 _dirtyRect = Gtk::gdk_rectangle();
0140 
0141             }
0142 
0143             // finally convert to widget coordinated
0144             gtk_tree_view_convert_bin_window_to_widget_coords(
0145                 treeView, rect.x, rect.y,
0146                 &rect.x, &rect.y );
0147 
0148 
0149         }
0150 
0151         return rect;
0152 
0153     }
0154 
0155     //_____________________________________________
0156     gboolean TreeViewStateData::delayedUpdate( gpointer pointer )
0157     {
0158 
0159         TreeViewStateData& data( *static_cast<TreeViewStateData*>( pointer ) );
0160 
0161         if( data._target )
0162         {
0163             const GdkRectangle rect( data.dirtyRect() );
0164             Gtk::gtk_widget_queue_draw( data._target, &rect );
0165         }
0166 
0167         return FALSE;
0168 
0169     }
0170 
0171 }