Re: inserting ColorButton in CellRenderer ....



В Чтв, 13/03/2008 в 15:14 -0400, Roberto Alejandro Espí Muñoz пишет:
> Thanks for your help. I'm trying to follow your directions.  I still
> have some doubts about how to define the two functions you wish me to
> override.  In get_size_vfunc I receive a &Widget, a Gdk::Rectangle*
> cell_area, an offset to x and y and a width and height parameters.
> How can I use them? Do I set those parameters onto the oncoming widget
> or do I set them from the Widget's parameters??  For the second
> function render_vfunc I didn't clearly understand what you wanted me
> to do.

The best way to understand those functions behavior is to look at source
code:

gtkcellrenderertext.c
gtkcellrenderertoggle.c

get_size_vfunc - should set width and height for cell you are going to
poaint button on.

render_vfunc - should paint the button itself.

I will attach source of my ButtonRenderer (Button with text) to give you
some hints. But don't copy it to your code, just get some clue how to
implement your renderer.

-andrew

#include "slib/dbglog.h"
#include "Utils.h"
#include "CellRendererButton.h"
#include "CellData.h"
#include "Profiler.h"

namespace Mgr
{

CellRendererButton::CellRendererButton() :
Glib::ObjectBase     ( typeid( CellRendererButton ) ),
Gtk::CellRenderer    (),
property_data_       ( *this, "data", ( void* )0 ),
property_row_color_  ( *this, "row_color", "" ),
property_activatable_( *this, "activatable", false ),
property_separator_  ( *this, "separator", true ),
property_format_     ( *this, "format", "" )
{
    property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
    property_xpad() = 2;
    property_ypad() = 2;
}

Glib::PropertyProxy< void* > CellRendererButton::property_data()
{
    return property_data_.get_proxy();
}

Glib::PropertyProxy< Glib::ustring > CellRendererButton::property_row_color()
{
    return property_row_color_.get_proxy();
}

Glib::PropertyProxy< bool > CellRendererButton::property_activatable()
{
    return property_activatable_.get_proxy();
}

Glib::PropertyProxy< bool > CellRendererButton::property_separator()
{
    return property_separator_.get_proxy();
}

Glib::PropertyProxy< Glib::ustring > CellRendererButton::property_format()
{
    return property_format_.get_proxy();
}

void CellRendererButton::get_size_vfunc
    ( Gtk::Widget& widget,
      const Gdk::Rectangle* cell_area,
      int* x_offset,
      int* y_offset,
      int* width,
      int* height )
#if ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 4 )
	const
#endif
{
    Glib::ustring text;

#if ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 4 )
    CellRendererButton* self = const_cast< CellRendererButton* >( this );
#else
    CellRendererButton* self = this;
#endif

    void* ptr = self->property_data().get_value();
    if( ptr )
    {
	CellData* data = reinterpret_cast< CellData* >( ptr );
	text = data->get_string();
    }
    Glib::RefPtr<Pango::Layout> ptrLayout = widget.create_pango_layout( text );
    Pango::Rectangle rect = ptrLayout->get_pixel_logical_extents();

    enum
    {
	TOGGLE_WIDTH = 12
    };

    const int calc_width  = property_xpad() * 4 + std::max( (int)TOGGLE_WIDTH, rect.get_width() );
    const int calc_height = property_ypad() * 4 + std::max( (int)TOGGLE_WIDTH, rect.get_height() );

    if( width )
	*width = calc_width;

    if( height )
	*height = calc_height;

    if( self->property_format() == "invisible" )
	return;

    if( cell_area )
    {
	if( x_offset )
	{
	    *x_offset = int( property_xalign() *
			     ( cell_area->get_width() - calc_width ) );
	    *x_offset = std::max( 0, *x_offset );
	}

	if( y_offset )
	{
	    *y_offset = int( property_yalign() *
			     ( cell_area->get_height() - calc_height ) );
	    *y_offset = std::max( 0, *y_offset );
	}
    }
}

void CellRendererButton::render_vfunc
#if ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 4 )
    ( const Glib::RefPtr<Gdk::Drawable>& window,
#else
    ( const Glib::RefPtr<Gdk::Window>& window,
#endif
      Gtk::Widget& widget,
      const Gdk::Rectangle& background_area,
      const Gdk::Rectangle& cell_area,
      const Gdk::Rectangle& /*expose_area*/,
      Gtk::CellRendererState flags )
{
    Glib::ustring rowBG;
    Glib::ustring text;

    void* ptr = property_data().get_value();
    if( ptr )
    {
	CellData* data = reinterpret_cast< CellData* >( ptr );
	parse_attributes( data->get_attr() );
	text = data->get_string();
    }
    Glib::RefPtr<Pango::Layout> ptrLayout = widget.create_pango_layout( text );

    const unsigned int cell_xpad = property_xpad();
    const unsigned int cell_ypad = property_ypad();

    int x_offset = 0, y_offset = 0, width = 0, height = 0;
    get_size( widget, cell_area, x_offset, y_offset, width, height );

    width  -= cell_xpad * 2;
    height -= cell_ypad * 2;

    if( width <= 0 || height <= 0 )
	return;

    Gtk::StateType state;
    Gtk::StateType textState;

    if( ( flags & Gtk::CELL_RENDERER_SELECTED ) != 0 )
    {
	state = Gtk::STATE_SELECTED;
	textState = ( widget.has_focus() ) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;
    }
    else
    {
	if( property_activatable_ )
	    state = Gtk::STATE_NORMAL;
	else
	    state = Gtk::STATE_NORMAL;
	textState = ( widget.is_sensitive() ) ? Gtk::STATE_NORMAL : Gtk::STATE_INSENSITIVE;
    }

    Glib::ustring row_attribute = property_row_color().get_value();

    if( m_colColorSet )
    {
	if( state != Gtk::STATE_SELECTED )
	{
	    Glib::RefPtr< Gdk::GC > gc = Gdk::GC::create( window );
	    gc->set_rgb_fg_color( m_colBgColor );

	    window->draw_rectangle( gc,
				    true,
				    background_area.get_x(),
				    background_area.get_y(),
				    background_area.get_width(),
				    background_area.get_height() );
	}
    }
    else if( !row_attribute.empty() )
    {
	rowBG = Profiler::instance()->get_attr_bg( row_attribute );
	if( state != Gtk::STATE_SELECTED )
	{
	    Gdk::Color color;
	    if( color.parse( rowBG ) )
	    {
		Glib::RefPtr<Gdk::GC> gc = Gdk::GC::create( window );
		gc->set_rgb_fg_color( color );
		window->draw_rectangle( gc,
					true,
					background_area.get_x(),
					background_area.get_y(),
					background_area.get_width(),
					background_area.get_height() );
	    }
	    else
	    {
		rowBG.clear();
	    }
	}
    }

    if( property_format() == "invisible" )
    {
	if( state == Gtk::STATE_SELECTED )
	{
	    Glib::RefPtr< Pango::Layout > ptrLayout = widget.create_pango_layout( "" );

#if ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 4 )
	    Glib::RefPtr<Gdk::Window> win = Glib::RefPtr<Gdk::Window>::cast_dynamic( window );
	    widget.get_style()->paint_layout
		( win,
		  state,
		  true,
		  cell_area,
		  widget,
		  "cellrenderertext",
		  cell_area.get_x() + x_offset + cell_xpad,
		  cell_area.get_y() + y_offset + cell_ypad,
		  ptrLayout );
#else
	    widget.get_style()->paint_layout
		( window,
		  state,
		  true,
		  cell_area,
		  widget,
		  "cellrenderertext",
		  cell_area.get_x() + x_offset + cell_xpad,
		  cell_area.get_y() + y_offset + cell_ypad,
		  ptrLayout );
#endif
	}
    }
    else
    {
#if ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 4 )
	Glib::RefPtr<Gdk::Window> win =
	    Glib::RefPtr<Gdk::Window>::cast_dynamic( window );
	widget.get_style()->paint_box
	    ( win, state, Gtk::SHADOW_OUT,
	      cell_area, widget, "button",
	      cell_area.get_x() + x_offset + cell_xpad,
	      cell_area.get_y() + y_offset + cell_ypad,
	      width, height );
	widget.get_style()->paint_layout
	    ( win,
	      textState,
	      true,
	      cell_area,
	      widget,
	      "cellrenderertext",
	      cell_area.get_x() + x_offset + 2 * cell_xpad,
	      cell_area.get_y() + y_offset + 2 * cell_ypad,
	      ptrLayout );
#else
	widget.get_style()->paint_box
	    ( window, state, Gtk::SHADOW_OUT,
	      cell_area, widget, "button",
	      cell_area.get_x() + x_offset + cell_xpad,
	      cell_area.get_y() + y_offset + cell_ypad,
	      width, height );
	widget.get_style()->paint_layout
	    ( window,
	      textState,
	      true,
	      cell_area,
	      widget,
	      "cellrenderertext",
	      cell_area.get_x() + x_offset + cell_xpad,
	      cell_area.get_y() + y_offset + cell_ypad,
	      ptrLayout );
#endif
    }

    if( m_colColorSet && state == Gtk::STATE_SELECTED )
    {
	Glib::RefPtr< Gdk::GC > gc = Gdk::GC::create( window );
	gc->set_rgb_fg_color( m_colBgColor );

	window->draw_rectangle( gc,
				true,
				background_area.get_x(),
				background_area.get_y() + 1,
				background_area.get_width(),
				3 );
	window->draw_rectangle( gc,
				true,
				background_area.get_x(),
				background_area.get_y() + background_area.get_height() - 4,
				background_area.get_width(),
				3 );
    }
    else if( !rowBG.empty() && state == Gtk::STATE_SELECTED )
    {
	Gdk::Color color;
	if( color.parse( rowBG ) )
	{
	    Glib::RefPtr< Gdk::GC > gc = Gdk::GC::create( window );
	    gc->set_rgb_fg_color( color );

	    window->draw_rectangle( gc,
				    true,
				    background_area.get_x(),
				    background_area.get_y() + 1,
				    background_area.get_width(),
				    3 );
	    window->draw_rectangle( gc,
				    true,
				    background_area.get_x(),
				    background_area.get_y() + background_area.get_height() - 4,
				    background_area.get_width(),
				    3 );
	}
    }
}

bool CellRendererButton::activate_vfunc( GdkEvent*,
					 Gtk::Widget&,
					 const Glib::ustring& path,
					 const Gdk::Rectangle&,
					 const Gdk::Rectangle&,
					 Gtk::CellRendererState )
{
    if( property_activatable_ )
    {
	Glib::ustring local_path = path;
	signal_toggled_( local_path );
	return true;
    }
    return false;
}

void CellRendererButton::parse_attributes( const Glib::ustring& attr_str )
{
    m_colColorSet = false;

    if( attr_str == "" )
	return;
    if( Profiler::instance() == 0 )
	return;

    Glib::ustring val = Profiler::instance()->get_attr_bg( attr_str );
    if( m_colBgColor.parse( val ) )
	m_colColorSet = true;
}

} // namespace Mgr


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