modern-gtk2: Use Cairo for drawing the partition resizer (!17)

GdkGC has been deprecated in the underlying C / GTK+ 2.22 library.  It
is less clearly stated but Gdk::GC is also deprecated in C++ / gtkmm.
Cairo based rendering should be used instead.
https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html
https://gitlab.gnome.org/GNOME/gtk/blob/2.22.0/NEWS#L124
https://developer.gnome.org/gtkmm/2.24/classGdk_1_1GC.html

First commit in a series to convert Gdk::GC based drawing to Cairo based
drawing.  This specific commit makes the transition for the graphical
partition resizing widget that is used in the "Create New Partition",
"Paste" creating new partition and "Resize/Move" dialogs.

Cairo is not pixel based but instead uses a continuous coordinate space.
To draw in a pixel aligned way follow the guidance in the Cairo FAQ.
https://www.cairographics.org/FAQ/#sharp_lines

Additional references:
https://developer.gnome.org/gdk2/stable/gdk2-Drawing-Primitives.html#gdk-draw-line
https://developer.gnome.org/gdk2/stable/gdk2-Drawing-Primitives.html#gdk-draw-rectangle

Closes !17 - Gtk2 modernisation
This commit is contained in:
Luca Bacci 2018-08-02 18:10:11 +02:00 committed by Mike Fleetwood
parent c602170faa
commit d17d129044
6 changed files with 132 additions and 112 deletions

View File

@ -47,7 +47,9 @@ public:
int get_x_start() ; int get_x_start() ;
int get_x_end() ; int get_x_end() ;
virtual void Draw_Partition() ; virtual void draw_partition(const Cairo::RefPtr<Cairo::Context>& cr);
void redraw();
//public signals (emitted upon resize/move) //public signals (emitted upon resize/move)
sigc::signal<void,int,int, ArrowType> signal_resize; sigc::signal<void,int,int, ArrowType> signal_resize;
@ -66,13 +68,10 @@ protected:
bool drawingarea_on_button_press_event( GdkEventButton * ev ) ; bool drawingarea_on_button_press_event( GdkEventButton * ev ) ;
bool drawingarea_on_button_release_event( GdkEventButton * ev ) ; bool drawingarea_on_button_release_event( GdkEventButton * ev ) ;
bool drawingarea_on_leave_notify( GdkEventCrossing * ev ) ; bool drawingarea_on_leave_notify( GdkEventCrossing * ev ) ;
void Draw_Resize_Grip( ArrowType ) ; void draw_resize_grip(const Cairo::RefPtr<Cairo::Context>& cr, ArrowType);
Gtk::DrawingArea drawingarea ; Gtk::DrawingArea drawingarea ;
Glib::RefPtr<Gdk::GC> gc_drawingarea ;
Glib::RefPtr<Gdk::Pixmap> pixmap ;
Glib::RefPtr<Gdk::GC> gc_pixmap ;
Gdk::Color color_used, color_unused, color_arrow, color_background, color_partition, color_arrow_rectangle; Gdk::Color color_used, color_unused, color_arrow, color_background, color_partition, color_arrow_rectangle;

View File

@ -33,7 +33,7 @@ private:
//overridden signal handler //overridden signal handler
virtual bool drawingarea_on_mouse_motion( GdkEventMotion * ev ) ; virtual bool drawingarea_on_mouse_motion( GdkEventMotion * ev ) ;
virtual void Draw_Partition() ; virtual void draw_partition(const Cairo::RefPtr<Cairo::Context>& cr);
}; };
#endif /* GPARTED_FRAME_RESIZER_EXTENDED_H */ #endif /* GPARTED_FRAME_RESIZER_EXTENDED_H */

View File

@ -372,9 +372,9 @@ void Dialog_Base_Partition::on_spinbutton_value_changed( SPINBUTTON spinbutton )
frame_resizer_base ->set_x_start( Utils::round( spinbutton_before .get_value() / MB_PER_PIXEL ) ) ; frame_resizer_base ->set_x_start( Utils::round( spinbutton_before .get_value() / MB_PER_PIXEL ) ) ;
frame_resizer_base ->set_x_end( 500 - Utils::round( spinbutton_after .get_value() / MB_PER_PIXEL ) ) ; frame_resizer_base ->set_x_end( 500 - Utils::round( spinbutton_after .get_value() / MB_PER_PIXEL ) ) ;
frame_resizer_base ->Draw_Partition() ; frame_resizer_base->redraw();
Check_Change() ; Check_Change() ;
} }
} }

View File

@ -382,7 +382,7 @@ void Dialog_Partition_New::combobox_changed(bool type)
// Maximum length of the file system label varies according to the selected file system type. // Maximum length of the file system label varies according to the selected file system type.
filesystem_label_entry.set_max_length( Utils::get_filesystem_label_maxlength( fs.filesystem ) ); filesystem_label_entry.set_max_length( Utils::get_filesystem_label_maxlength( fs.filesystem ) );
frame_resizer_base ->Draw_Partition() ; frame_resizer_base->redraw();
} }

View File

@ -17,6 +17,9 @@
#include "Frame_Resizer_Base.h" #include "Frame_Resizer_Base.h"
#include <gdkmm/general.h>
Frame_Resizer_Base::Frame_Resizer_Base() Frame_Resizer_Base::Frame_Resizer_Base()
{ {
BORDER = 8 ; BORDER = 8 ;
@ -45,13 +48,13 @@ void Frame_Resizer_Base::init()
sigc::mem_fun(*this, &Frame_Resizer_Base::drawingarea_on_leave_notify) ) ; sigc::mem_fun(*this, &Frame_Resizer_Base::drawingarea_on_leave_notify) ) ;
this ->add( drawingarea ) ; this ->add( drawingarea ) ;
color_used .set( "#F8F8BA" ); this ->get_colormap() ->alloc_color( color_used ) ; color_used.set("#F8F8BA");
color_unused .set( "white" ); this ->get_colormap() ->alloc_color( color_unused ) ; color_unused.set("white");
color_arrow .set( "black" ); this ->get_colormap() ->alloc_color( color_arrow ) ; color_arrow.set("black");
color_background .set( "darkgrey" ); this ->get_colormap() ->alloc_color( color_background ) ; color_background.set("darkgrey");
color_arrow_rectangle .set( "lightgrey" ); this ->get_colormap() ->alloc_color( color_arrow_rectangle ) ; color_arrow_rectangle.set("lightgrey");
cursor_resize = new Gdk::Cursor( Gdk::SB_H_DOUBLE_ARROW ) ; cursor_resize = new Gdk::Cursor( Gdk::SB_H_DOUBLE_ARROW ) ;
cursor_move = new Gdk::Cursor( Gdk::FLEUR ) ; cursor_move = new Gdk::Cursor( Gdk::FLEUR ) ;
@ -69,16 +72,12 @@ void Frame_Resizer_Base::init()
void Frame_Resizer_Base::set_rgb_partition_color( const Gdk::Color & color ) void Frame_Resizer_Base::set_rgb_partition_color( const Gdk::Color & color )
{ {
this ->get_colormap() ->free_color( color_partition ) ;
this ->color_partition = color ; this ->color_partition = color ;
this ->get_colormap() ->alloc_color( color_partition ) ;
} }
void Frame_Resizer_Base::override_default_rgb_unused_color( const Gdk::Color & color ) void Frame_Resizer_Base::override_default_rgb_unused_color( const Gdk::Color & color )
{ {
this ->get_colormap() ->free_color( color_unused ) ;
this ->color_unused = color ; this ->color_unused = color ;
this ->get_colormap() ->alloc_color( color_unused ) ;
} }
void Frame_Resizer_Base::set_x_start( int x_start ) void Frame_Resizer_Base::set_x_start( int x_start )
@ -129,12 +128,6 @@ int Frame_Resizer_Base::get_x_end()
void Frame_Resizer_Base::drawingarea_on_realize() void Frame_Resizer_Base::drawingarea_on_realize()
{ {
gc_drawingarea = Gdk::GC::create( drawingarea .get_window() );
pixmap = Gdk::Pixmap::create( drawingarea .get_window(),
drawingarea .get_allocation() .get_width(),
drawingarea .get_allocation() .get_height() );
gc_pixmap = Gdk::GC::create( pixmap );
drawingarea .add_events( Gdk::POINTER_MOTION_MASK ); drawingarea .add_events( Gdk::POINTER_MOTION_MASK );
drawingarea .add_events( Gdk::BUTTON_PRESS_MASK ); drawingarea .add_events( Gdk::BUTTON_PRESS_MASK );
drawingarea .add_events( Gdk::BUTTON_RELEASE_MASK ); drawingarea .add_events( Gdk::BUTTON_RELEASE_MASK );
@ -142,8 +135,24 @@ void Frame_Resizer_Base::drawingarea_on_realize()
} }
bool Frame_Resizer_Base::drawingarea_on_expose( GdkEventExpose * ev ) bool Frame_Resizer_Base::drawingarea_on_expose( GdkEventExpose * ev )
{ {
Draw_Partition() ; Glib::RefPtr<Gdk::Window> window = drawingarea.get_window();
if (!window)
return true;
Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
// Clip to the area indicated by the expose event so that we only redraw
// the portion of the window that needs to be redrawn.
cr->rectangle(ev->area.x, ev->area.y,
ev->area.width, ev->area.height);
cr->clip();
cr->set_line_cap(Cairo::LINE_CAP_SQUARE);
cr->set_line_width(1.0);
draw_partition(cr);
return true; return true;
} }
@ -281,8 +290,8 @@ bool Frame_Resizer_Base::drawingarea_on_mouse_motion( GdkEventMotion * ev )
X_START_MOVE = static_cast<int>( ev ->x ) ; X_START_MOVE = static_cast<int>( ev ->x ) ;
signal_move .emit( X_START - GRIPPER, X_END - GRIPPER - BORDER * 2 ) ; signal_move .emit( X_START - GRIPPER, X_END - GRIPPER - BORDER * 2 ) ;
} }
Draw_Partition() ; redraw();
} }
else else
{ {
@ -357,47 +366,49 @@ bool Frame_Resizer_Base::drawingarea_on_leave_notify( GdkEventCrossing *ev )
return true; return true;
} }
void Frame_Resizer_Base::Draw_Partition()
void Frame_Resizer_Base::draw_partition(const Cairo::RefPtr<Cairo::Context>& cr)
{ {
UNUSED = X_END - X_START - BORDER * 2 - USED ; UNUSED = X_END - X_START - BORDER * 2 - USED ;
if ( UNUSED < 0 ) if ( UNUSED < 0 )
UNUSED = 0 ; UNUSED = 0 ;
if ( drawingarea .get_window() ) // Background color
{ Gdk::Cairo::set_source_color(cr, color_background);
//i couldn't find a clear() for a pixmap, that's why ;) cr->rectangle(0, 0, 536, 50);
gc_pixmap ->set_foreground( color_background ); cr->fill();
pixmap ->draw_rectangle( gc_pixmap, true, 0, 0, 536, 50 );
// The two rectangles on each side of the partition
//the two rectangles on each side of the partition Gdk::Cairo::set_source_color(cr, color_arrow_rectangle);
gc_pixmap ->set_foreground( color_arrow_rectangle ); cr->rectangle(0, 0, 10, 50);
pixmap ->draw_rectangle( gc_pixmap, true, 0, 0, 10, 50 ); cr->fill();
pixmap ->draw_rectangle( gc_pixmap, true, 526, 0, 10, 50 ); cr->rectangle(526, 0, 10, 50);
cr->fill();
//partition
gc_pixmap ->set_foreground( color_partition ); // Partition
pixmap ->draw_rectangle( gc_pixmap, true, X_START, 0, X_END - X_START, 50 ); Gdk::Cairo::set_source_color(cr, color_partition);
cr->rectangle(X_START, 0, X_END - X_START, 50);
//used cr->fill();
gc_pixmap ->set_foreground( color_used );
pixmap ->draw_rectangle( gc_pixmap, true, X_START +BORDER, BORDER, USED, 34 ); // Used
Gdk::Cairo::set_source_color(cr, color_used);
//unused cr->rectangle(X_START + BORDER, BORDER, USED, 34);
gc_pixmap ->set_foreground( color_unused ); cr->fill();
pixmap ->draw_rectangle( gc_pixmap, true, X_START +BORDER +USED, BORDER, UNUSED, 34 );
// Unused
//resize grips Gdk::Cairo::set_source_color(cr, color_unused);
if ( ! fixed_start ) cr->rectangle(X_START + BORDER + USED, BORDER, UNUSED, 34);
Draw_Resize_Grip( ARROW_LEFT ) ; cr->fill();
Draw_Resize_Grip( ARROW_RIGHT ) ; // Resize grips
if (!fixed_start)
//and draw everything to "real" screen.. draw_resize_grip(cr, ARROW_LEFT);
drawingarea .get_window() ->draw_drawable( gc_drawingarea, pixmap, 0, 0, 0, 0 ) ;
} draw_resize_grip(cr, ARROW_RIGHT);
} }
void Frame_Resizer_Base::Draw_Resize_Grip( ArrowType arrow_type )
void Frame_Resizer_Base::draw_resize_grip(const Cairo::RefPtr<Cairo::Context>& cr, ArrowType arrow_type)
{ {
if ( arrow_type == ARROW_LEFT ) if ( arrow_type == ARROW_LEFT )
{ {
@ -412,28 +423,30 @@ void Frame_Resizer_Base::Draw_Resize_Grip( ArrowType arrow_type )
arrow_points[ 2 ] .set_x( X_END ) ; arrow_points[ 2 ] .set_x( X_END ) ;
} }
//attach resize arrows to the partition // Attach resize arrows to the partition
gc_pixmap ->set_foreground( color_arrow_rectangle ); Gdk::Cairo::set_source_color(cr, color_arrow_rectangle);
pixmap ->draw_rectangle( gc_pixmap, cr->rectangle((arrow_type == ARROW_LEFT ? X_START - GRIPPER : X_END + 1) + 0.5,
false, 5 + 0.5,
arrow_type == ARROW_LEFT ? X_START - GRIPPER : X_END +1, 9,
5, 40);
9, cr->stroke();
40 ) ;
Gdk::Cairo::set_source_color(cr, color_arrow);
gc_pixmap ->set_foreground( color_arrow ); cr->move_to(arrow_points[0].get_x(), arrow_points[0].get_y());
pixmap ->draw_polygon( gc_pixmap, true, arrow_points ); cr->line_to(arrow_points[1].get_x(), arrow_points[1].get_y());
cr->line_to(arrow_points[2].get_x(), arrow_points[2].get_y());
cr->close_path();
cr->fill();
}
void Frame_Resizer_Base::redraw()
{
drawingarea.queue_draw();
} }
Frame_Resizer_Base::~Frame_Resizer_Base() Frame_Resizer_Base::~Frame_Resizer_Base()
{ {
this ->get_colormap() ->free_color( color_used ) ;
this ->get_colormap() ->free_color( color_unused ) ;
this ->get_colormap() ->free_color( color_arrow ) ;
this ->get_colormap() ->free_color( color_background ) ;
this ->get_colormap() ->free_color( color_partition ) ;
this ->get_colormap() ->free_color( color_arrow_rectangle ) ;
delete cursor_resize; delete cursor_resize;
delete cursor_move; delete cursor_move;
} }

View File

@ -17,6 +17,9 @@
#include "Frame_Resizer_Extended.h" #include "Frame_Resizer_Extended.h"
#include <gdkmm/general.h>
Frame_Resizer_Extended::Frame_Resizer_Extended() Frame_Resizer_Extended::Frame_Resizer_Extended()
{ {
} }
@ -123,8 +126,8 @@ bool Frame_Resizer_Extended::drawingarea_on_mouse_motion( GdkEventMotion * ev )
} }
} }
} }
Draw_Partition() ; redraw();
} }
//check if pointer is over a gripper //check if pointer is over a gripper
@ -151,30 +154,35 @@ bool Frame_Resizer_Extended::drawingarea_on_mouse_motion( GdkEventMotion * ev )
return true ; return true ;
} }
void Frame_Resizer_Extended::Draw_Partition()
void Frame_Resizer_Extended::draw_partition(const Cairo::RefPtr<Cairo::Context>& cr)
{ {
//i couldn't find a clear() for a pixmap, that's why ;) // Background color
gc_pixmap ->set_foreground( color_background ); Gdk::Cairo::set_source_color(cr, color_background);
pixmap ->draw_rectangle( gc_pixmap, true, 0, 0, 536, 50 ); cr->rectangle(0, 0, 536, 50);
cr->fill();
//the two rectangles on each side of the partition
gc_pixmap ->set_foreground( color_arrow_rectangle ); // The two rectangles on each side of the partition
pixmap ->draw_rectangle( gc_pixmap, true, 0, 0, 10, 50 ); Gdk::Cairo::set_source_color(cr, color_arrow_rectangle);
pixmap ->draw_rectangle( gc_pixmap, true, 526, 0, 10, 50 ); cr->rectangle(0, 0, 10, 50);
cr->fill();
//used cr->rectangle(526, 0, 10, 50);
gc_pixmap ->set_foreground( color_used ); cr->fill();
pixmap ->draw_rectangle( gc_pixmap, true, USED_START + BORDER, BORDER, USED, 34 );
// Used
//partition Gdk::Cairo::set_source_color(cr, color_used);
gc_pixmap ->set_foreground( color_partition ); cr->rectangle(USED_START + BORDER, BORDER, USED, 34);
cr->fill();
// Partition
Gdk::Cairo::set_source_color(cr, color_partition);
for( short t = 0; t < 9 ; t++ ) for( short t = 0; t < 9 ; t++ )
pixmap ->draw_rectangle( gc_pixmap, false, X_START +t, t, X_END - X_START -t*2, 50 - t*2 ); {
cr->rectangle(X_START + t + 0.5, t + 0.5, X_END - X_START - t*2, 50 - t*2);
//resize grips cr->stroke();
Draw_Resize_Grip( ARROW_LEFT ) ; }
Draw_Resize_Grip( ARROW_RIGHT ) ;
// Resize grips
//and draw everything to "real" screen.. draw_resize_grip(cr, ARROW_LEFT);
drawingarea .get_window() ->draw_drawable( gc_drawingarea, pixmap, 0, 0, 0, 0 ) ; draw_resize_grip(cr, ARROW_RIGHT);
} }