/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002 The Inti Development Team.
 *  Copyright (C) 2000 Red Hat, Inc.
 *
 *  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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
//! @file inti/gtk/scale.h
//! @brief A GtkScale, GtkHScale and GtkVScale C++ wrapper interface.
//!
//! Provides Scale, a widget used only for deriving the subclasses HScale and VScale.

#ifndef INTI_GTK_SCALE_H
#define INTI_GTK_SCALE_H

#ifndef INTI_GTK_RANGE_H
#include <inti/gtk/range.h>
#endif

#ifndef __GTK_HSCALE_H__
#include <gtk/gtkhscale.h>
#endif

#ifndef __GTK_VSCALE_H__
#include <gtk/gtkvscale.h>
#endif

namespace Inti {

namespace Gtk {

class ScaleClass;
class HScaleClass;
class VScaleClass;

//! @class Scale scale.h inti/gtk/scale.h
//! @brief A GtkScale C++ wrapper class.
//!
//! The Scale widget is an abstract class, used only for deriving the subclasses HScale and VScale.
//!
//! A Scale is a slider control used to select a numeric value. To use it, you'll probably want to
//! investigate the methods on its base class, Range, in addition to the methods for Scale itself.
//! To set the value of a scale, you would normally use Gtk::Range::set_value(). To detect changes
//! to the value, you would normally connect to the <EM>value_changed</EM> signal. 

class Scale : public Range
{
	friend class G::Object;
	friend class ScaleClass;

	Scale(const Scale&);
	Scale& operator=(const Scale&);

protected:
//! @name Constructors
//! @{

	Scale();
	//!< Construct a new Scale.

	explicit Scale(GtkScale *scale, bool reference = false);
	//!< Construct a new Scale from an existing GtkScale.
	//!< @param scale A pointer to a GtkScale.
	//!< @param reference Set false if the initial reference count is floating, set true if it's not.
	//!<
	//!< <BR>The <EM>scale</EM> can be a newly created GtkScale or an existing
	//!< GtkScale (see G::Object::Object).

	virtual ~Scale() = 0;
	//!< Destructor.

//! @}
//  Override this do_ method only when you want to change the default behaviour of GtkScale.

	virtual void do_draw_value();

//! @name Signal Handlers
//! @{

	virtual char* on_format_value(double value);
	//!< Called to format the scale value before it gets displayed.
	//!< @param value The scale value to format.
	//!< @return An allocated string representing <EM>value</EM>. 
	//!<
	//!< <BR>This signal handler allows you to change how the scale value is displayed.
	//!< The return value must be an allocated string representing value. That string
	//!< will then be used to display the scale's value. Here's an example signal handler
	//!< which displays a value 1.0 as with "-->1.0<--".<BR>
	//!< @code
	//!< char*
	//!< MyScale::on_format_value(double value)
	//!< {
	//!< 	return g_strdup_printf("-->%0.*g<--", scale->get_digits(value));
	//!< }
	//!< @endcode
	
//! @}
//  Properties

	typedef G::Property<int> DigitsPropertyType;
	typedef G::PropertyProxy<G::Object, DigitsPropertyType> DigitsPropertyProxy;
	static const DigitsPropertyType digits_property;

	typedef G::Property<bool> DrawValuePropertyType;
	typedef G::PropertyProxy<G::Object, DrawValuePropertyType> DrawValuePropertyProxy;
	static const DrawValuePropertyType draw_value_property;

	typedef G::Property<PositionType, int> ValuePosPropertyType;
	typedef G::PropertyProxy<G::Object, ValuePosPropertyType> ValuePosPropertyProxy;
	static const ValuePosPropertyType value_pos_property;

//  Signals

	typedef G::Signal1<char*, double> FormatValueSignalType;
	typedef G::SignalProxy<TypeInstance, FormatValueSignalType> FormatValueSignalProxy;
	static const FormatValueSignalType format_value_signal;

public:
//! @name Accessors
//! @{

	GtkScale* gtk_scale() const { return (GtkScale*)instance; }
	//!< Get a pointer to the GtkScale structure.

	GtkScaleClass* gtk_scale_class() const;
	//!< Get a pointer to the GtkScaleClass structure.
	
	operator GtkScale* () const;
	//!< Conversion operator; safely converts a Scale to a GtkScale pointer.

	int get_digits() const;
	//!< Gets the number of decimal places that are displayed in the value. 

	bool get_draw_value() const;
	//!< Returns whether the current value is displayed as a string next to the slider. 

	PositionType get_value_pos() const;
	//!< Gets the position in which the current value is displayed. 
	//! @return The position in which the current value is displayed. 
 
//! @}
//! @name Methods
//! @{

	void set_digits(int digits);
	//!< Sets the number of decimal places that are displayed in the value. 
	//!< @param digits The number of decimal places to display, e.g. use 1 to display 1.0, 2 to display 1.00 etc.
	//!<
	//!< <BR>Also causes the value of the adjustment to be rounded off to this number of digits,
	//!< so the retrieved value matches the value the user saw. 
 
	void set_draw_value(bool draw_value);
	//!< Specifies whether the current value is displayed as a string next to the slider. 
	//!< @param draw_value Set <EM>true</EM> to display the current value.
 
 	void set_value_pos(PositionType pos);
	//!< Sets the position in which the current value is displayed. 
	//!< @param pos The position in which the current value is displayed. 
 
	String format_value(double value);
	//!< Emits the "format_value" signal to format the value.
	//!< @param value the current adjustment value.	
	//!<
	//!< <BR>If there are no user signal handlers, falls back to a default format.

//! @}
//! @name Property Proxies
//! @{

	const DigitsPropertyProxy prop_digits()
	{
		return DigitsPropertyProxy(this, &digits_property);
	}
	//!< The number of decimal places that are displayed in the value (int : Read / Write).

	const DrawValuePropertyProxy prop_draw_value()
	{
		return DrawValuePropertyProxy(this, &draw_value_property);
	}
	//!< Whether the current value is displayed as a string next to the slider (bool : Read / Write).

	const ValuePosPropertyProxy prop_value_pos()
	{
		return ValuePosPropertyProxy(this, &value_pos_property);
	}
	//!< The position in which the current value is displayed (PositionType : Read / Write.

//! @}
//! @name Signal Proxies
//! @{

	const FormatValueSignalProxy sig_format_value()
	{
		return FormatValueSignalProxy(this, &format_value_signal);
	}
	//!< Connect to the format_value_signal; emitted to format the scale value before it gets displayed.
	
//! @}
};

//! @class HScale scale.h inti/gtk/scale.h
//! @brief A GtkHScale C++ wrapper class.
//!
//! The HScale widget is used to allow the user to select a value using a horizontal slider.
//! The position to show the current value, and the number of decimal places shown can be
//! set using the parent Scale class's methods.

class HScale : public Scale
{
	friend class G::Object;
	friend class HScaleClass;

	HScale(const HScale&);
	HScale& operator=(const HScale&);
	
protected:
//! @name Constructors
//! @{

	explicit HScale(GtkHScale *hscale, bool reference = false);
	//!< Construct a new HScale from an existing GtkHScale.
	//!< @param hscale A pointer to a GtkHScale.
	//!< @param reference Set false if the initial reference count is floating, set true if it's not.
	//!<
	//!< <BR>The <EM>hscale</EM> can be a newly created GtkHScale or an existing
	//!< GtkHScale (see G::Object::Object).

//! @}
	
public:
//! @name Constructors
//! @{

	HScale();
	//!< Construct a new horizontal scale.

	explicit HScale(Adjustment& adjustment);
	//!< Construct a new horizontal scale with the specified adjustement.
	//!< @param adjustment The Adjustment which sets the range of the scale.

	HScale(double min, double max, double step = 1.0);
	//!< Construct a new horizontal scale that lets the user input a number between min and max
	//!< (including min and max) with the increment step. 
	//!< @param min The minimum value.
	//!< @param max The maximum value.
	//!< @param step The step increment (tick size) used with keyboard shortcuts.
	//!<
	//!< <BR>The <EM>step</EM> must be nonzero; it's the distance the slider moves when using
	//!< the arrow keys to adjust the scale value.

	virtual ~HScale();
	//!< Destructor.

//! @}
//! @name Accessors
//! @{

	GtkHScale* gtk_hscale() const { return (GtkHScale*)instance; }
	//!< Get a pointer to the GtkHScale structure.
	
	GtkHScaleClass* gtk_hscale_class() const;
	//!< Get a pointer to the GtkHScaleClass structure.
	
	operator GtkHScale* () const;
	//!< Conversion operator; safely converts a HScale to a GtkHScale pointer.
	
//! @}
};

//! @class VScale scale.h inti/gtk/scale.h
//! @brief A GtkVScale C++ wrapper class.
//!
//! The VScale widget is used to allow the user to select a value using a vertical slider.
//! The position to show the current value, and the number of decimal places shown can be
//! set using the parent Scale class's methods.

class VScale : public Scale
{
	friend class G::Object;
	friend class VScaleClass;

	VScale(const VScale&);
	VScale& operator=(const VScale&);
	
protected:
//! @name Constructors
//! @{

	explicit VScale(GtkVScale *vscale, bool reference = false);
	//!< Construct a new VScale from an existing GtkVScale.
	//!< @param vscale A pointer to a GtkVScale.
	//!< @param reference Set false if the initial reference count is floating, set true if it's not.
	//!<
	//!< <BR>The <EM>vscale</EM> can be a newly created GtkVScale or an existing
	//!< GtkVScale (see G::Object::Object).
	
//! @}

public:
//! @name Constructors
//! @{

	VScale();
	//!< Construct a new vertical scale.

	explicit VScale(Adjustment& adjustment);
	//!< Construct a new vertical scale with the specified adjustement.
	//!< @param adjustment The Adjustment which sets the range of the scale.

	VScale(double min, double max, double step = 1.0);
	//!< Construct a new vertical scale that lets the user input a number between min and max
	//!< (including min and max) with the increment step.
	//!< @param min The minimum value.
	//!< @param max The maximum value.
	//!< @param step The step increment (tick size) used with keyboard shortcuts.
	//!<
	//!< <BR>The <EM>step</EM> must be nonzero; it's the distance the slider moves when using
	//!< the arrow keys to adjust the scale value.

	virtual ~VScale();
	//!< Destructor.

//! @}
//! @name Accessors
//! @{

	GtkVScale* gtk_vscale() const { return (GtkVScale*)instance; }
	//!< Get a pointer to the GtkVScale structure.
	
	GtkVScaleClass* gtk_vscale_class() const;
	//!< Get a pointer to the GtkVScaleClass structure.
	
	operator GtkVScale* () const;
	//!< Conversion operator; safely converts a VScale to a GtkVScale pointer.
	
//! @}
};

} // namespace Gtk

} // namespace Inti

#endif // INTI_GTK_SCALE_H

