ScrolledWindow problem



I found the error in Gtk::ScrolledWindow class.

The methods get_hscrollbar() and get_vscrollbar() always return 0,
because gtk_scrolled_window_get_hscrollbar() and
gtk_scrolled_window_get_vscrollbar() both return object of type
GtkScrolledBar that cannot be wrapped to Gtk::HScrollbar and
Gtk::VScrollbar.

There is simple test where I discover the problem.

Installed Component versions:
atk-2.0.0
atkmm-2.22.5
cairo-1.10.2
cairomm-1.9.8
fontconfig-2.8.0
gdk-pixbuf-2.22.1
glib-2.28.5
glibmm-2.28.0
gtk+-3.0.8
gtkmm-3.0.0
libsigc++-2.2.9
pango-1.28.4
pangomm-2.28.2
pixman-0.20.2

-- 
Andrew E. Makeev <andrew solvo ru>
Solvo Logistic
#include <gtk/gtk.h>

#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#include <gtkmm/entry.h>
#include <gtkmm/main.h>
#include <gtkmm/scrollbar.h>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/stock.h>
#include <gtkmm/window.h>

#include <iostream>

class ScrolledWindow : public Gtk::ScrolledWindow
{
    public:
	ScrolledWindow()
	    : Gtk::ScrolledWindow()
	    , htype_( Gtk::POLICY_AUTOMATIC )
	    , vtype_( Gtk::POLICY_AUTOMATIC ) {}
	    ~ScrolledWindow()
	    {
	    }

	    void set_policy( Gtk::PolicyType htype, Gtk::PolicyType vtype )
	    {
		htype_ = htype;
		vtype_ = vtype;
		Gtk::ScrolledWindow::set_policy( htype_, vtype_ );
	    }

    protected:
	int gtk_scrolled_window_get_scrollbar_spacing() const
	{
	    GtkScrolledWindowClass* klass = GTK_SCROLLED_WINDOW_GET_CLASS( this->gobj() );

	    if( klass->scrollbar_spacing >= 0 )
		return klass->scrollbar_spacing;
	    else
	    {
		int scrollbar_spacing;
		get_style_property( "scrollbar_spacing", scrollbar_spacing );

		return scrollbar_spacing;
	    }
	}

	void get_preferred_width_vfunc( int& minWidth, int& natWidth ) const
	{
	    get_preferred_size( Gtk::ORIENTATION_HORIZONTAL, minWidth, natWidth );
	}

	void get_preferred_height_vfunc( int& minHeight, int& natHeight ) const
	{
	    get_preferred_size( Gtk::ORIENTATION_VERTICAL, minHeight, natHeight );
	}

    private:
	void get_preferred_size( Gtk::Orientation orientation,
				 int& minSize,
				 int& natSize ) const
	{
	    int extraWidth = 0;
	    int extraHeight = 0;

	    minSize = natSize = 0;

	    int scrollbarSpacing = gtk_scrolled_window_get_scrollbar_spacing();

	    Gtk::Requisition hscrollbarRequisition;
	    Gtk::Requisition vscrollbarRequisition;
	    Gtk::Requisition fakeReq;

	    //const Gtk::HScrollbar* hb = get_hscrollbar();
	    /* replaced ^^^^^^^^^^ to get my code working as I expected */
	    Gtk::Scrollbar* hb = 0;
	    GtkScrollbar* ghb = ( GtkScrollbar* )
		    gtk_scrolled_window_get_hscrollbar( const_cast< GtkScrolledWindow* >( gobj() ) );
	    if( ghb == NULL )
	    {
		std::cout << "GTK scrollbar is NULL" << std::endl;
	    }
	    else if( GTK_IS_HSCROLLBAR( ghb ) )
	    {
		std::cout << "GTK scrollbar is VALID" << std::endl;
	    }
	    else
	    {
		std::cout << "GTK scrollbar is type: " << G_OBJECT_TYPE_NAME( ghb ) << std::endl;
		GTypeInstance* ginst = (GTypeInstance*)ghb;
		GTypeClass* gclass = (GTypeClass*)ginst->g_class;
		GType gtype = gclass->g_type;

		hb = Glib::wrap( ghb );
	    }
	    /* ^^^^^^^^^^^ recomment to get HScrollbar always NULL ^^^^^^^^^^^^^*/

	    const Gtk::VScrollbar* vb = get_vscrollbar();
	    if( hb )
		hb->get_preferred_size( hscrollbarRequisition, fakeReq );
	    else
	    {
		hscrollbarRequisition.width = 0;
		hscrollbarRequisition.height = 0;
	    }
	    if( vb )
		vb->get_preferred_size( vscrollbarRequisition, fakeReq );
	    else
	    {
		vscrollbarRequisition.width = 0;
		vscrollbarRequisition.height = 0;
	    }

	    const Gtk::Widget* child = get_child();
	    if( child && child->get_visible() )
	    {
		int minChildSize, natChildSize;

		if( orientation == Gtk::ORIENTATION_HORIZONTAL )
		{
		    if( htype_ == Gtk::POLICY_NEVER )
		    {
			child->get_preferred_width( minChildSize, natChildSize );

			minSize += minChildSize;
			natSize += natChildSize;
		    }
		    else
		    {
			int minWidth = property_min_content_width().get_value();

			if( vb && vb->get_visible() )
			{
			    minWidth = MAX( minWidth, vscrollbarRequisition.width );
			}
			minSize += minWidth;
			natSize += minWidth;
		    }
		}
		else
		{
		    if( vtype_ == Gtk::POLICY_NEVER )
		    {
			child->get_preferred_height( minChildSize, natChildSize );

			minSize += minChildSize;
			natSize += natChildSize;
		    }
		    else
		    {
			int minHeight = property_min_content_height().get_value();

			if( hb && hb->get_visible() )
			{
			    minHeight = MAX( minHeight, hscrollbarRequisition.height );
			}
			minSize += minHeight;
			natSize += minHeight;
		    }
		}
	    }

	    if( htype_ != Gtk::POLICY_NEVER )
	    {
		if( orientation == Gtk::ORIENTATION_HORIZONTAL )
		{
		    minSize = MAX( minSize, hscrollbarRequisition.width );
		    natSize = MAX( natSize, hscrollbarRequisition.width );
		}
	    }

	    if( vtype_ != Gtk::POLICY_NEVER )
	    {
		if( orientation == Gtk::ORIENTATION_VERTICAL )
		{
		    minSize = MAX( minSize, vscrollbarRequisition.height );
		    natSize = MAX( natSize, vscrollbarRequisition.height );
		}
	    }

	    std::cout << "HB: " << hb << " vis: " << ( hb ? hb->get_visible() : false ) << std::endl;
	    if( hb && hb->get_visible() )
		extraHeight = scrollbarSpacing + hscrollbarRequisition.height;
	    if( vb && vb->get_visible() )
		extraWidth = scrollbarSpacing + vscrollbarRequisition.width;

	    if( orientation == Gtk::ORIENTATION_HORIZONTAL )
	    {
		minSize += MAX( 0, extraWidth );
		natSize += MAX( 0, extraWidth );
	    }
	    else
	    {
		minSize += MAX( 0, extraHeight );
		natSize += MAX( 0, extraHeight );
	    }

	    if( get_shadow_type() != Gtk::SHADOW_NONE )
	    {
		Glib::RefPtr< Gtk::StyleContext > context = get_style_context();
		Gtk::StateFlags state = get_state_flags();

		context->context_save();
		context->add_class( GTK_STYLE_CLASS_FRAME );
		Gtk::Border padding = context->get_padding( state );
		Gtk::Border border = context->get_border( state );

		if( orientation == Gtk::ORIENTATION_HORIZONTAL )
		{
		    minSize += ( padding.get_left() + padding.get_right() + border.get_left() + border.get_right() );
		    natSize += ( padding.get_left() + padding.get_right() + border.get_left() + border.get_right() );
		}
		else
		{
		    minSize += ( padding.get_top() + padding.get_bottom() + border.get_top() + border.get_bottom() );
		    natSize += ( padding.get_top() + padding.get_bottom() + border.get_top() + border.get_bottom() );
		}

		context->context_restore();
	    }
	}

	Gtk::PolicyType htype_;
	Gtk::PolicyType vtype_;
};

class App : public Gtk::Window
{
    public:
	App() : Gtk::Window( Gtk::WINDOW_TOPLEVEL )
	{
	    Gtk::VBox* vbox = Gtk::manage( new Gtk::VBox( false, 5 ) );
	    add( *vbox );

	    ScrolledWindow* sw = Gtk::manage( new ScrolledWindow() );
	    sw->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER );
	    vbox->pack_start( *sw, false, false );

	    Gtk::HBox* box = Gtk::manage( new Gtk::HBox( false, 5 ) );
	    sw->add( *box );

	    Gtk::Label* l = Gtk::manage( new Gtk::Label( "Entry:" ) );
	    box->pack_start( *l, false, false );

	    Gtk::Entry* e = Gtk::manage( new Gtk::Entry() );
	    box->pack_start( *e, false, false );

	    Gtk::Button* b = Gtk::manage( new Gtk::Button( Gtk::Stock::CLOSE ) );
	    b->signal_clicked().connect( sigc::ptr_fun( &Gtk::Main::quit ) );
	    box->pack_start( *b, false, false );

	    l = Gtk::manage( new Gtk::Label( "Spacer" ) );
	    vbox->pack_start( *l, true, false );

	    show_all_children();
	}
};

int main( int argc, char* argv[] )
{
    Gtk::Main kit( argc, argv );
    App app;
    kit.run( app );
    return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]