/* Copyright 2005 Nicholas Bishop * * This file is part of SharpConstruct. * * SharpConstruct 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. * * SharpConstruct 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 SharpConstruct; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Slider.hh" #include "Utilities.h" #include #include #include #include using SharpConstruct::GInterface::Slider; Slider::Slider() : start_( 0 ), snap_( true ), in_slide_( false ) { show(); get_adjustment()->set_lower( -100 ); get_adjustment()->set_upper( 100 ); } Slider::Slider( const double l, const double h ) : start_( 0 ), snap_( true ), in_slide_( false ) { show(); get_adjustment()->set_lower( l ); get_adjustment()->set_upper( h ); } double Slider::Start() const { return start_; } bool Slider::Snap() const { return snap_; } double Slider::Range() const { return get_adjustment()->get_upper() - get_adjustment()->get_lower(); } bool Slider::InSlide() const { return in_slide_; } Slider::SliderSignal& Slider::SignalStart() { return signal_start_; } Slider::SliderSignal& Slider::SignalContinue() { return signal_continue_; } Slider::SliderSignal& Slider::SignalEnd() { return signal_end_; } bool Slider::on_button_press_event( GdkEventButton* e ) { mouse_down_x_ = e->x + get_allocation().get_x(); start_slide_(); queue_draw(); return true; } bool Slider::on_button_release_event( GdkEventButton* e ) { end_slide_(); queue_draw(); return true; } bool Slider::on_expose_event( GdkEventExpose* e ) { Glib::RefPtr< Gtk::Style > style( Gtk::Style::create() ); const Glib::RefPtr< Gdk::Window > wnd( get_window() ); const Gdk::Rectangle area( get_allocation() ); Gtk::StateType state( sensitive() ? Gtk::STATE_ACTIVE : Gtk::STATE_INSENSITIVE ); const int x( area.get_x() ); const int y( area.get_y() ); const int w( get_width() ); const int h( get_height() ); get_style()->paint_box( wnd, state, Gtk::SHADOW_IN, area, *this, "trough", x, y + 7, w, h - 14 ); const int x1( amount_to_loc_( Start() ) ); const int x2( amount_to_loc_( get_value() ) ); int start_x( x1 ), width( x2 - x1 ); if( x1 > x2 ) { start_x = x2; width = x1 - x2; } // Make sure the button is visible if( width < 10 ) width = 10; Gtk::StateType mstate( Gtk::STATE_NORMAL ); int mx, my; get_pointer( mx, my ); if( in_slide_ ) mstate = Gtk::STATE_ACTIVE; else if( mx < get_width() && my < get_height() ) mstate = Gtk::STATE_PRELIGHT; get_style()->paint_slider( wnd, mstate, Gtk::SHADOW_OUT, area, *this, "hscale", start_x, y, width, h, Gtk::ORIENTATION_HORIZONTAL ); Glib::RefPtr< Pango::Layout > layout( Pango::Layout::create ( get_pango_context() ) ); layout->set_alignment( Pango::ALIGN_RIGHT ); layout->set_text( Glib::Ascii::dtostr( lround( get_value() ) ) ); get_style()->paint_layout( wnd, Gtk::STATE_PRELIGHT, true, area, *this, "hscale", get_width() / 2 + x, y + 1, layout ); return true; } bool Slider::on_motion_notify_event( GdkEventMotion* e ) { if( in_slide_ ) { int mx, my; Gdk::ModifierType mask; get_window()->get_pointer( mx, my, mask ); const Gdk::Rectangle area( get_allocation() ); if( my < area.get_y() - 100 || my > area.get_y() + area.get_height() + 100 ) { set_value( original_ ); } else { const int delta( mx - mouse_down_x_ ); set_value( loc_to_amount_ ( amount_to_loc_( original_ ) + delta ) ); } continue_slide_(); } queue_draw(); return true; } void Slider::on_realize() { Range::on_realize(); add_events( Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK ); } void Slider::on_size_request( Gtk::Requisition* r ) { *r = Gtk::Requisition(); r->height = 20; } void Slider::start_slide_() { SignalStart().emit( get_value() ); original_ = get_value(); in_slide_ = true; } void Slider::continue_slide_() { SignalContinue().emit( get_value() ); } void Slider::end_slide_() { in_slide_ = false; if( get_value() != original_ ) SignalEnd().emit( get_value() ); if( Snap() ) set_value( Start() ); } int Slider::amount_to_loc_( const double a ) const { return ( get_width() * ( a - get_adjustment()->get_lower() ) ) / Range() + get_allocation().get_x(); } double Slider::loc_to_amount_( const int l ) const { return ( Range() * ( l - get_allocation().get_x() ) ) / get_width() + get_adjustment()->get_lower(); }