scalar-unit.cpp revision 136163cf52e17c002bdf20591c539a858ef911ed
/**
* \brief Scalar Unit Widget - A labelled text box, with spin buttons and
* optional icon or suffix, for entering the values of various unit
* types.
*
* A ScalarUnit is a control for entering, viewing, or manipulating
* numbers with units. This differs from ordinary numbers like 2 or
* 3.14 because the number portion of a scalar *only* has meaning
* when considered with its unit type. For instance, 12 m and 12 in
* have very different actual values, but 1 m and 100 cm have the same
* value. The ScalarUnit allows us to abstract the presentation of
* the scalar to the user from the internal representations used by
* the program.
*
* Authors:
* Bryce Harrington <bryce@bryceharrington.org>
* Derek P. Moore <derekm@hackunix.org>
* buliabyak@gmail.com
*
* Copyright (C) 2004-2005 Authors
*
* Released under GNU GPL. Read the file 'COPYING' for more information.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "scalar-unit.h"
#include "spinbutton.h"
namespace Inkscape {
namespace UI {
namespace Widget {
/**
* Construct a ScalarUnit
*
* \param label Label.
* \param unit_type Unit type (defaults to UNIT_TYPE_LINEAR).
* \param suffix Suffix, placed after the widget (defaults to "").
* \param icon Icon filename, placed before the label (defaults to "").
* \param unit_menu UnitMenu drop down; if not specified, one will be created
* and displayed after the widget (defaults to NULL).
* \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label
* indicates the next character should be used for the
* mnemonic accelerator key (defaults to true).
*/
ScalarUnit::ScalarUnit(Glib::ustring const &label, Glib::ustring const &tooltip,
UnitType unit_type,
Glib::ustring const &suffix,
Glib::ustring const &icon,
UnitMenu *unit_menu,
bool mnemonic)
: Scalar(label, tooltip, suffix, icon, mnemonic),
_unit_menu(unit_menu),
_hundred_percent(0),
_absolute_is_increment(false),
_percentage_is_increment(false)
{
if (_unit_menu == NULL) {
_unit_menu = new UnitMenu();
g_assert(_unit_menu);
_unit_menu->setUnitType(unit_type);
pack_start(*Gtk::manage(_unit_menu), false, false, 4);
}
_unit_menu->signal_changed()
.connect_notify(sigc::mem_fun(*this, &ScalarUnit::on_unit_changed));
static_cast<SpinButton*>(_widget)->setUnitMenu(_unit_menu);
}
/**
* Initializes the scalar based on the settings in _unit_menu.
* Requires that _unit_menu has already been initialized.
*/
void
ScalarUnit::initScalar(double min_value, double max_value)
{
g_assert(_unit_menu != NULL);
Scalar::setDigits(_unit_menu->getDefaultDigits());
Scalar::setIncrements(_unit_menu->getDefaultStep(),
_unit_menu->getDefaultPage());
Scalar::setRange(min_value, max_value);
}
/** Sets the unit for the ScalarUnit widget */
bool
ScalarUnit::setUnit(Glib::ustring const &unit) {
g_assert(_unit_menu != NULL);
// First set the unit
if (!_unit_menu->setUnit(unit)) {
return false;
}
lastUnits = unit;
return true;
}
/** Gets the object for the currently selected unit */
Unit
ScalarUnit::getUnit() const {
g_assert(_unit_menu != NULL);
return _unit_menu->getUnit();
}
/** Gets the UnitType ID for the unit */
UnitType
ScalarUnit::getUnitType() const {
g_assert(_unit_menu);
return _unit_menu->getUnitType();
}
/** Sets the number and unit system */
void
ScalarUnit::setValue(double number, Glib::ustring const &units) {
g_assert(_unit_menu != NULL);
_unit_menu->setUnit(units);
Scalar::setValue(number);
}
/** Convert and sets the number only and keeps the current unit. */
void
ScalarUnit::setValueKeepUnit(double number, Glib::ustring const &units) {
g_assert(_unit_menu != NULL);
if (units == "") {
// set the value in the default units
Scalar::setValue(number);
} else {
double conversion = _unit_menu->getConversion(units);
Scalar::setValue(number / conversion);
}
}
/** Sets the number only */
void
ScalarUnit::setValue(double number) {
Scalar::setValue(number);
}
/** Returns the value in the given unit system */
double
ScalarUnit::getValue(Glib::ustring const &unit_name) const {
g_assert(_unit_menu != NULL);
if (unit_name == "") {
// Return the value in the default units
return Scalar::getValue();
} else {
double conversion = _unit_menu->getConversion(unit_name);
return conversion * Scalar::getValue();
}
}
/** Grab focus, and select the text that is in the entry field.
*/
void
ScalarUnit::grabFocusAndSelectEntry() {
_widget->grab_focus();
static_cast<SpinButton*>(_widget)->select_region(0, 20);
}
void
ScalarUnit::setHundredPercent(double number)
{
_hundred_percent = number;
}
void
ScalarUnit::setAbsoluteIsIncrement(bool value)
{
_absolute_is_increment = value;
}
void
ScalarUnit::setPercentageIsIncrement(bool value)
{
_percentage_is_increment = value;
}
/** Convert value from % to absolute, using _hundred_percent and *_is_increment flags */
double
ScalarUnit::PercentageToAbsolute(double value)
{
// convert from percent to absolute
double convertedVal = 0;
double hundred_converted = _hundred_percent / _unit_menu->getConversion("px"); // _hundred_percent is in px
if (_percentage_is_increment)
value += 100;
convertedVal = 0.01 * hundred_converted * value;
if (_absolute_is_increment)
convertedVal -= hundred_converted;
return convertedVal;
}
/** Convert value from absolute to %, using _hundred_percent and *_is_increment flags */
double
ScalarUnit::AbsoluteToPercentage(double value)
{
double convertedVal = 0;
// convert from absolute to percent
if (_hundred_percent == 0) {
if (_percentage_is_increment)
convertedVal = 0;
else
convertedVal = 100;
} else {
double hundred_converted = _hundred_percent / _unit_menu->getConversion("px", lastUnits); // _hundred_percent is in px
if (_absolute_is_increment)
value += hundred_converted;
convertedVal = 100 * value / hundred_converted;
if (_percentage_is_increment)
convertedVal -= 100;
}
return convertedVal;
}
/** Assuming the current unit is absolute, get the corresponding % value */
double
ScalarUnit::getAsPercentage()
{
double convertedVal = AbsoluteToPercentage(Scalar::getValue());
return convertedVal;
}
/** Assuming the current unit is absolute, set the value corresponding to a given % */
void
ScalarUnit::setFromPercentage(double value)
{
double absolute = PercentageToAbsolute(value);
Scalar::setValue(absolute);
}
/** Signal handler for updating the value and suffix label when unit is changed */
void
ScalarUnit::on_unit_changed()
{
g_assert(_unit_menu != NULL);
Glib::ustring abbr = _unit_menu->getUnitAbbr();
_suffix->set_label(abbr);
Inkscape::Util::UnitTable &table = _unit_menu->getUnitTable();
Inkscape::Util::Unit new_unit = (table.getUnit(abbr));
Inkscape::Util::Unit old_unit = (table.getUnit(lastUnits));
double convertedVal = 0;
if (old_unit.type == UNIT_TYPE_DIMENSIONLESS && new_unit.type == UNIT_TYPE_LINEAR) {
convertedVal = PercentageToAbsolute(Scalar::getValue());
} else if (old_unit.type == UNIT_TYPE_LINEAR && new_unit.type == UNIT_TYPE_DIMENSIONLESS) {
convertedVal = AbsoluteToPercentage(Scalar::getValue());
} else {
double conversion = _unit_menu->getConversion(lastUnits);
convertedVal = Scalar::getValue() / conversion;
}
Scalar::setValue(convertedVal);
lastUnits = abbr;
}
} // namespace Widget
} // namespace UI
} // namespace Inkscape
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :