File indexing completed on 2024-04-28 05:32:11

0001 #ifndef oxygengtkcellinfo_h
0002 #define oxygengtkcellinfo_h
0003 /*
0004 * this file is part of the oxygen gtk engine
0005 * SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0006 *
0007 * SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "oxygenflags.h"
0011 
0012 #include <vector>
0013 #include <iostream>
0014 #include <gdk/gdk.h>
0015 #include <gtk/gtk.h>
0016 
0017 namespace Oxygen
0018 {
0019     namespace Gtk
0020     {
0021 
0022         //! stores information for a given treeview cell
0023         /*!
0024         note: treeview itself is not stored as a member of the object, to avoid carying dangling pointers
0025         around. As a consequence it must be passed as argument of all methods that would need it. This
0026         implicitely requires that the same treeview is used in constructor and accessors, although it would
0027         not crash if not the case
0028         */
0029         class CellInfo
0030         {
0031 
0032             public:
0033 
0034             //! empty constructor
0035             explicit CellInfo( void ):
0036                 _path( 0L ),
0037                 _column( -1 )
0038             {}
0039 
0040             //! copy constructor
0041             CellInfo( const CellInfo& other ):
0042                 _path( other._path ? gtk_tree_path_copy( other._path ):0L ),
0043                 _column( other._column )
0044             {}
0045 
0046             //! construct from tree view and position
0047             /*! unfortunately the path retrieval does not always work because x and y must be positive */
0048             explicit CellInfo( GtkTreeView* treeView, int x, int y ):
0049                 _path(0L),
0050                 _column(-1)
0051             {
0052                 GtkTreeViewColumn *column( 0L );
0053                 gtk_tree_view_get_path_at_pos( treeView, x, y, &_path, &column, 0L, 0L );
0054                 _column = indexOfColumn( treeView, column );
0055             }
0056 
0057             //! construct from tree view and rectangle
0058             explicit CellInfo( GtkTreeView* treeView, int x, int y, int w, int h );
0059 
0060             //! destructor
0061             virtual ~CellInfo( void )
0062             { if( _path ) gtk_tree_path_free( _path ); }
0063 
0064             //! assignment operator
0065             CellInfo& operator = (const CellInfo& other )
0066             {
0067                 if( _path ) gtk_tree_path_free( _path );
0068                 _path = other._path ? gtk_tree_path_copy( other._path ):0L;
0069                 _column = other._column;
0070                 return *this;
0071             }
0072 
0073             //! equal to operator
0074             bool operator == (const CellInfo& other ) const
0075             { return sameColumn( other ) && samePath( other ); }
0076 
0077             //! equal to operator
0078             bool operator != (const CellInfo& other ) const
0079             { return !( sameColumn( other ) && samePath( other )); }
0080 
0081             //! clear
0082             void clear( void )
0083             {
0084                 if( _path ) gtk_tree_path_free( _path );
0085                 _path = 0L;
0086                 _column = -1;
0087             }
0088 
0089             //!@name accessors
0090             //@{
0091 
0092             //! true if valid
0093             bool isValid( void ) const
0094             { return _path && _column >= 0; }
0095 
0096             //! returns true if column is the last one
0097             bool isLastVisibleColumn( GtkTreeView* ) const;
0098 
0099             //! returns true if column is the first one
0100             bool isFirstVisibleColumn( GtkTreeView* ) const;
0101 
0102             //! returns true if column is the one that contains expander
0103             bool isExpanderColumn( GtkTreeView* treeView ) const
0104             { return _column >= 0 && _column == indexOfColumn( treeView, gtk_tree_view_get_expander_column( treeView ) ); }
0105 
0106             //! returs true if column is let of expander column
0107             bool isLeftOfExpanderColumn( GtkTreeView* ) const;
0108 
0109             //! returns true if path has parent
0110             bool hasParent( GtkTreeView* ) const;
0111 
0112             //! parent cell
0113             CellInfo parent( void ) const;
0114 
0115             //! returns true if path has children
0116             bool hasChildren( GtkTreeView* ) const;
0117 
0118             //! returns true if path is last at its given level
0119             bool isLast( GtkTreeView* ) const;
0120 
0121             //! return path depth
0122             unsigned int depth( void ) const
0123             { return _path ? (unsigned int) gtk_tree_path_get_depth( _path ):0;  }
0124 
0125             //! true if column match
0126             bool sameColumn( const CellInfo& other ) const
0127             { return _column == other._column; }
0128 
0129             //! true if path match
0130             bool samePath( const CellInfo& other ) const
0131             {
0132                 if( _path ) return other._path && !gtk_tree_path_compare( _path, other._path );
0133                 else return !other._path;
0134             }
0135 
0136             //! background rect
0137             GdkRectangle backgroundRect( GtkTreeView* ) const;
0138 
0139             //@}
0140 
0141             private:
0142 
0143             //! path
0144             GtkTreePath* _path;
0145 
0146             //! column index
0147             gint _column;
0148 
0149             //! streamer
0150             friend std::ostream& operator << (std::ostream& out, const CellInfo& info )
0151             {
0152 
0153                 if( info.isValid() )
0154                 {
0155                     gchar* path( gtk_tree_path_to_string( info._path ) );
0156                     out << path;
0157                     g_free( path );
0158                 } else out << "invalid";
0159                 return out;
0160             }
0161 
0162             static gint indexOfColumn( GtkTreeView*, GtkTreeViewColumn* );
0163 
0164         };
0165 
0166         //! cell info flags
0167         /*! stores relevant information from cell info needed for painting */
0168         class CellInfoFlags
0169         {
0170 
0171             public:
0172 
0173             //! constructor
0174             explicit CellInfoFlags( void ):
0175                 _depth(0),
0176                 _expanderSize(0),
0177                 _levelIndent(0)
0178             {}
0179 
0180             //! flags
0181             enum CellFlag
0182             {
0183                 HasParent = 1<<0,
0184                 HasChildren = 1<<1,
0185                 IsLast = 1<<2,
0186                 Reversed = 1<<3
0187             };
0188 
0189             OX_DECLARE_FLAGS( CellFlags, CellFlag );
0190 
0191             //! constructor from CellInfo
0192             explicit CellInfoFlags( GtkTreeView* treeView, const CellInfo& cellInfo );
0193 
0194             //! flags
0195             CellFlags _flags;
0196 
0197             //! depth
0198             unsigned int _depth;
0199             int _expanderSize;
0200             int _levelIndent;
0201 
0202             //! keep track of whether this cell, or parents are last in hierarchy
0203             std::vector<bool> _isLast;
0204         };
0205 
0206     }
0207 
0208     OX_DECLARE_OPERATORS_FOR_FLAGS( Gtk::CellInfoFlags::CellFlags );
0209 
0210 }
0211 #endif