467 lines
14 KiB
C++
467 lines
14 KiB
C++
/* Copyright (C) 2004 Bart
|
|
* Copyright (C) 2010 Curtis Gedak
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "DrawingAreaVisualDisk.h"
|
|
#include "Partition.h"
|
|
#include "PartitionLUKS.h"
|
|
#include "PartitionVector.h"
|
|
#include "Utils.h"
|
|
|
|
#define MAIN_BORDER 5
|
|
#define BORDER 4
|
|
#define SEP 4
|
|
#define HEIGHT 70 + 2 * MAIN_BORDER
|
|
|
|
namespace GParted
|
|
{
|
|
|
|
DrawingAreaVisualDisk::DrawingAreaVisualDisk()
|
|
{
|
|
selected_vp = NULL ;
|
|
|
|
//set and allocated some standard colors
|
|
color_used .set( Utils::get_color( GParted::FS_USED ) );
|
|
get_colormap() ->alloc_color( color_used ) ;
|
|
|
|
color_unused .set( Utils::get_color( GParted::FS_UNUSED ) );
|
|
get_colormap() ->alloc_color( color_unused ) ;
|
|
|
|
color_unallocated .set( Utils::get_color( GParted::FS_UNALLOCATED ) );
|
|
get_colormap() ->alloc_color( color_unallocated ) ;
|
|
|
|
color_text .set( "black" );
|
|
get_colormap() ->alloc_color( color_text ) ;
|
|
|
|
add_events( Gdk::BUTTON_PRESS_MASK );
|
|
|
|
set_size_request( -1, HEIGHT ) ;
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::load_partitions( const PartitionVector & partitions, Sector device_length )
|
|
{
|
|
clear() ;
|
|
|
|
TOT_SEP = get_total_separator_px( partitions ) ;
|
|
set_static_data( partitions, visual_partitions, device_length ) ;
|
|
|
|
queue_resize() ;
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::set_selected( const Partition * partition_ptr )
|
|
{
|
|
selected_vp = NULL ;
|
|
set_selected( visual_partitions, partition_ptr );
|
|
|
|
queue_draw() ;
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::clear()
|
|
{
|
|
free_colors( visual_partitions ) ;
|
|
visual_partitions .clear() ;
|
|
selected_vp = NULL ;
|
|
|
|
queue_resize() ;
|
|
}
|
|
|
|
int DrawingAreaVisualDisk::get_total_separator_px( const PartitionVector & partitions )
|
|
{
|
|
for ( unsigned int t = 0 ; t < partitions .size() ; t++ )
|
|
if ( partitions[ t ] .type == GParted::TYPE_EXTENDED )
|
|
return ( partitions[ t ] .logicals .size() -1 + partitions .size() -1 ) * SEP ;
|
|
|
|
|
|
return ( partitions .size() -1 ) * SEP ;
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::set_static_data( const PartitionVector & partitions,
|
|
std::vector<visual_partition> & visual_partitions,
|
|
Sector length )
|
|
{
|
|
for ( unsigned int t = 0 ; t < partitions .size() ; t++ )
|
|
{
|
|
visual_partitions .push_back( visual_partition() ) ;
|
|
|
|
visual_partitions.back().partition_ptr = & partitions[t];
|
|
Sector partition_length = partitions[ t ] .get_sector_length() ;
|
|
visual_partitions .back() .fraction = partition_length / static_cast<double>( length ) ;
|
|
|
|
Glib::ustring color_str = Utils::get_color( partitions[t].get_filesystem_partition().filesystem );
|
|
visual_partitions.back().color.set( color_str );
|
|
get_colormap() ->alloc_color( visual_partitions .back() .color );
|
|
|
|
if ( partitions[ t ] .type == GParted::TYPE_EXTENDED )
|
|
set_static_data( partitions[t].logicals,
|
|
visual_partitions.back().logicals, partition_length );
|
|
else
|
|
visual_partitions .back() .pango_layout = create_pango_layout(
|
|
partitions[ t ] .get_path() + "\n" + Utils::format_size( partition_length, partitions[ t ] .sector_size ) ) ;
|
|
}
|
|
}
|
|
|
|
int DrawingAreaVisualDisk::calc_length( std::vector<visual_partition> & visual_partitions, int length_px )
|
|
{
|
|
int calced_length = 0 ;
|
|
|
|
for ( int t = 0 ; t < static_cast<int>( visual_partitions .size() ) ; t++ )
|
|
{
|
|
visual_partitions[ t ] .length = Utils::round( length_px * visual_partitions[ t ] .fraction ) ;
|
|
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
visual_partitions[ t ] .length =
|
|
calc_length( visual_partitions[ t ] .logicals,
|
|
visual_partitions[ t ] .length - (2 * BORDER) ) + (2 * BORDER) ;
|
|
else if ( visual_partitions[ t ] .length < MIN_SIZE )
|
|
visual_partitions[ t ] .length = MIN_SIZE ;
|
|
|
|
calced_length += visual_partitions[ t ] .length ;
|
|
}
|
|
|
|
return calced_length + (visual_partitions .size() - 1) * SEP ;
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::calc_position_and_height( std::vector<visual_partition> & visual_partitions,
|
|
int start,
|
|
int border )
|
|
{
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() ; t++ )
|
|
{
|
|
visual_partitions[ t ] .x_start = start ;
|
|
visual_partitions[ t ] .y_start = border ;
|
|
visual_partitions[ t ] .height = HEIGHT - ( border * 2 ) ;
|
|
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
calc_position_and_height( visual_partitions[ t ] .logicals,
|
|
visual_partitions[ t ] .x_start + BORDER,
|
|
visual_partitions[ t ] .y_start + BORDER ) ;
|
|
|
|
start += visual_partitions[ t ] .length + SEP ;
|
|
}
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::calc_usage( std::vector<visual_partition> & visual_partitions )
|
|
{
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() ; t++ )
|
|
{
|
|
if ( visual_partitions[t].partition_ptr->type != TYPE_UNALLOCATED &&
|
|
visual_partitions[t].partition_ptr->type != TYPE_EXTENDED )
|
|
{
|
|
if ( visual_partitions[t].partition_ptr->sector_usage_known() )
|
|
{
|
|
visual_partitions[t].partition_ptr->get_usage_triple(
|
|
visual_partitions[ t ] .length - BORDER *2,
|
|
visual_partitions[ t ] .used_length,
|
|
visual_partitions[ t ] .unused_length,
|
|
visual_partitions[ t ] .unallocated_length ) ;
|
|
}
|
|
else
|
|
{
|
|
//Specifically show unknown figures as unused
|
|
visual_partitions[ t ] .used_length = 0 ;
|
|
visual_partitions[ t ] .unused_length = visual_partitions[ t ] .length - BORDER *2 ;
|
|
visual_partitions[ t ] .unallocated_length = 0 ;
|
|
}
|
|
|
|
//used
|
|
visual_partitions[ t ] .x_used_start = visual_partitions[ t ] .x_start + BORDER ;
|
|
|
|
//unused
|
|
visual_partitions[ t ] .x_unused_start = visual_partitions[ t ] .x_used_start
|
|
+ visual_partitions[ t ] .used_length ;
|
|
|
|
//unallocated
|
|
visual_partitions[ t ] .x_unallocated_start = visual_partitions[ t ] .x_unused_start
|
|
+ visual_partitions[ t ] .unused_length ;
|
|
|
|
//y position and height
|
|
visual_partitions[ t ] .y_usage_start = visual_partitions[ t ] .y_start + BORDER ;
|
|
visual_partitions[ t ] .usage_height = visual_partitions[ t ] .height - (2 * BORDER) ;
|
|
}
|
|
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
calc_usage( visual_partitions[ t ] .logicals ) ;
|
|
}
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::calc_text( std::vector<visual_partition> & visual_partitions )
|
|
{
|
|
int length, height ;
|
|
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() ; t++ )
|
|
{
|
|
if ( visual_partitions[ t ] .pango_layout )
|
|
{
|
|
//see if the text fits in the partition... (and if so, center the text..)
|
|
visual_partitions[ t ] .pango_layout ->get_pixel_size( length, height ) ;
|
|
if ( length < visual_partitions[ t ] .length - (2 * BORDER) - 2 )
|
|
{
|
|
visual_partitions[ t ] .x_text = visual_partitions[ t ] .x_start +
|
|
Utils::round( (visual_partitions[ t ] .length / 2) - (length / 2) ) ;
|
|
|
|
visual_partitions[ t ] .y_text = visual_partitions[ t ] .y_start +
|
|
Utils::round( (visual_partitions[ t ] .height / 2) - (height / 2) ) ;
|
|
}
|
|
else
|
|
visual_partitions[ t ] .x_text = visual_partitions[ t ] .y_text = 0 ;
|
|
}
|
|
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
calc_text( visual_partitions[ t ] .logicals ) ;
|
|
}
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::draw_partition( const visual_partition & vp )
|
|
{
|
|
//partition...
|
|
gc ->set_foreground( vp .color );
|
|
get_window() ->draw_rectangle( gc,
|
|
true,
|
|
vp .x_start,
|
|
vp .y_start,
|
|
vp .length,
|
|
vp .height );
|
|
|
|
//used..
|
|
if ( vp .used_length > 0 )
|
|
{
|
|
gc ->set_foreground( color_used );
|
|
get_window() ->draw_rectangle( gc,
|
|
true,
|
|
vp .x_used_start,
|
|
vp .y_usage_start,
|
|
vp .used_length,
|
|
vp .usage_height );
|
|
}
|
|
|
|
//unused
|
|
if ( vp .unused_length > 0 )
|
|
{
|
|
gc ->set_foreground( color_unused );
|
|
get_window() ->draw_rectangle( gc,
|
|
true,
|
|
vp .x_unused_start,
|
|
vp .y_usage_start,
|
|
vp .unused_length,
|
|
vp .usage_height );
|
|
}
|
|
|
|
//unallocated
|
|
if ( vp .unallocated_length > 0 )
|
|
{
|
|
gc ->set_foreground( color_unallocated );
|
|
get_window() ->draw_rectangle( gc,
|
|
true,
|
|
vp .x_unallocated_start,
|
|
vp .y_usage_start,
|
|
vp .unallocated_length,
|
|
vp .usage_height );
|
|
}
|
|
|
|
//text
|
|
if ( vp .x_text > 0 )
|
|
{
|
|
gc ->set_foreground( color_text );
|
|
get_window() ->draw_layout( gc,
|
|
vp .x_text,
|
|
vp .y_text,
|
|
vp .pango_layout ) ;
|
|
}
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::draw_partitions( const std::vector<visual_partition> & visual_partitions )
|
|
{
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() ; t++ )
|
|
{
|
|
draw_partition( visual_partitions[ t ] ) ;
|
|
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
draw_partitions( visual_partitions[ t ] .logicals ) ;
|
|
}
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::set_selected( const std::vector<visual_partition> & visual_partitions, int x, int y )
|
|
{
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() && ! selected_vp ; t++ )
|
|
{
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
set_selected( visual_partitions[ t ] .logicals, x, y ) ;
|
|
|
|
if ( ! selected_vp &&
|
|
visual_partitions[ t ] .x_start <= x &&
|
|
x < visual_partitions[ t ] .x_start + visual_partitions[ t ] .length &&
|
|
visual_partitions[ t ] .y_start <= y &&
|
|
y < visual_partitions[ t ] .y_start + visual_partitions[ t ] .height )
|
|
{
|
|
selected_vp = & visual_partitions[ t ] ;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::set_selected( const std::vector<visual_partition> & visual_partitions,
|
|
const Partition * partition_ptr )
|
|
{
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() && ! selected_vp ; t++ )
|
|
{
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
set_selected( visual_partitions[t].logicals, partition_ptr );
|
|
|
|
if ( ! selected_vp && *visual_partitions[t].partition_ptr == *partition_ptr )
|
|
selected_vp = & visual_partitions[ t ] ;
|
|
}
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::on_realize()
|
|
{
|
|
Gtk::DrawingArea::on_realize() ;
|
|
|
|
gc = Gdk::GC::create( get_window() );
|
|
gc ->set_line_attributes( 2,
|
|
Gdk::LINE_ON_OFF_DASH,
|
|
Gdk::CAP_BUTT,
|
|
Gdk::JOIN_MITER ) ;
|
|
}
|
|
|
|
bool DrawingAreaVisualDisk::on_expose_event( GdkEventExpose * event )
|
|
{
|
|
bool ret_val = Gtk::DrawingArea::on_expose_event( event ) ;
|
|
|
|
draw_partitions( visual_partitions ) ;
|
|
|
|
//selection
|
|
if ( selected_vp )
|
|
{
|
|
gc ->set_foreground( color_used ) ;
|
|
get_window() ->draw_rectangle( gc,
|
|
false,
|
|
selected_vp ->x_start + BORDER/2 ,
|
|
selected_vp ->y_start + BORDER/2 ,
|
|
selected_vp ->length - BORDER,
|
|
selected_vp ->height - BORDER ) ;
|
|
}
|
|
|
|
return ret_val ;
|
|
}
|
|
|
|
bool DrawingAreaVisualDisk::on_button_press_event( GdkEventButton * event )
|
|
{
|
|
bool ret_val = Gtk::DrawingArea::on_button_press_event( event ) ;
|
|
|
|
selected_vp = NULL ;
|
|
set_selected( visual_partitions, static_cast<int>( event ->x ), static_cast<int>( event ->y ) ) ;
|
|
queue_draw() ;
|
|
|
|
if ( selected_vp )
|
|
{
|
|
signal_partition_selected.emit( selected_vp->partition_ptr, false );
|
|
|
|
if ( event ->type == GDK_2BUTTON_PRESS )
|
|
signal_partition_activated .emit() ;
|
|
else if ( event ->button == 3 )
|
|
signal_popup_menu .emit( event ->button, event ->time ) ;
|
|
}
|
|
|
|
return ret_val ;
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::on_size_allocate( Gtk::Allocation & allocation )
|
|
{
|
|
Gtk::DrawingArea::on_size_allocate( allocation ) ;
|
|
|
|
MIN_SIZE = BORDER * 2 + 2 ;
|
|
|
|
int available_size = allocation .get_width() - (2 * MAIN_BORDER),
|
|
calced = 0,
|
|
px_left ;
|
|
|
|
do
|
|
{
|
|
px_left = available_size - TOT_SEP ;
|
|
calced = available_size ; //for first time :)
|
|
do
|
|
{
|
|
px_left -= ( calced - available_size ) ;
|
|
calced = calc_length( visual_partitions, px_left ) ;
|
|
}
|
|
while ( calced > available_size && px_left > 0 ) ;
|
|
|
|
MIN_SIZE-- ;
|
|
}
|
|
while ( px_left <= 0 && MIN_SIZE > 0 ) ;
|
|
|
|
//due to rounding a few px may be lost. here we salvage them..
|
|
if ( visual_partitions .size() && calced > 0 )
|
|
{
|
|
px_left = available_size - calced ;
|
|
|
|
while ( px_left > 0 )
|
|
px_left = spreadout_leftover_px( visual_partitions, px_left ) ;
|
|
}
|
|
|
|
//and calculate the rest..
|
|
calc_position_and_height( visual_partitions, MAIN_BORDER, MAIN_BORDER ) ;//0, 0 ) ;
|
|
calc_usage( visual_partitions ) ;
|
|
calc_text( visual_partitions ) ;
|
|
queue_draw();
|
|
}
|
|
|
|
int DrawingAreaVisualDisk::spreadout_leftover_px( std::vector<visual_partition> & visual_partitions, int pixels )
|
|
{
|
|
int extended = -1 ;
|
|
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() && pixels > 0 ; t++ )
|
|
if ( ! visual_partitions[ t ] .logicals .size() )
|
|
{
|
|
visual_partitions[ t ] .length++ ;
|
|
pixels-- ;
|
|
}
|
|
else
|
|
extended = t ;
|
|
|
|
if ( extended > -1 && pixels > 0 )
|
|
{
|
|
int actually_used = pixels - spreadout_leftover_px( visual_partitions[ extended ] .logicals, pixels ) ;
|
|
visual_partitions[ extended ] .length += actually_used ;
|
|
pixels -= actually_used ;
|
|
}
|
|
|
|
return pixels ;
|
|
}
|
|
|
|
void DrawingAreaVisualDisk::free_colors( std::vector<visual_partition> & visual_partitions )
|
|
{
|
|
for ( unsigned int t = 0 ; t < visual_partitions .size() ; t++ )
|
|
{
|
|
get_colormap() ->free_color( visual_partitions[ t ] .color ) ;
|
|
|
|
if ( visual_partitions[ t ] .logicals .size() > 0 )
|
|
free_colors( visual_partitions[ t ] .logicals ) ;
|
|
}
|
|
}
|
|
|
|
DrawingAreaVisualDisk::~DrawingAreaVisualDisk()
|
|
{
|
|
clear() ;
|
|
|
|
//free the allocated colors
|
|
get_colormap() ->free_color( color_used ) ;
|
|
get_colormap() ->free_color( color_unused ) ;
|
|
get_colormap() ->free_color( color_unallocated ) ;
|
|
get_colormap() ->free_color( color_text ) ;
|
|
}
|
|
|
|
} //GParted
|