WPropertyDoubleWidget.cpp 6.54 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

25
#include <sstream>
26
#include <cmath>
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
27
#include <string>
28 29 30 31 32 33 34 35 36 37 38

#include <boost/lexical_cast.hpp>

#include "../../../common/WLogger.h"
#include "../../../common/WPropertyVariable.h"

#include "WPropertyDoubleWidget.h"

WPropertyDoubleWidget::WPropertyDoubleWidget( WPropDouble property, QGridLayout* propertyGrid, QWidget* parent ):
    WPropertyWidget( property, propertyGrid, parent ),
    m_doubleProperty( property ),
39 40
    m_slider( Qt::Horizontal, &m_parameterWidgets ),
    m_edit( &m_parameterWidgets ),
41 42 43
    m_layout( &m_parameterWidgets ),
    m_asText( &m_informationWidgets ),
    m_infoLayout( &m_informationWidgets )
44 45
{
    // initialize members
46
    m_edit.resize( m_edit.minimumSizeHint().width() *.8 , m_edit.size().height() );
47
    m_edit.setMaximumWidth( m_edit.minimumSizeHint().width() );
48 49

    // layout both against each other
50 51 52 53
    m_layout.addWidget( &m_slider );
    m_layout.addWidget( &m_edit );

    m_parameterWidgets.setLayout( &m_layout );
54

55 56 57 58
    // Information Output ( Property Purpose = PV_PURPOSE_INFORMATION )
    m_infoLayout.addWidget( &m_asText );
    m_informationWidgets.setLayout( &m_infoLayout );

59 60 61
    update();

    // connect the modification signal of the edit and slider with our callback
62
    connect( &m_slider, SIGNAL( sliderMoved( int ) ), this, SLOT( sliderChanged( int ) ) );
63 64
    connect( &m_edit, SIGNAL( returnPressed() ), this, SLOT( editChanged() ) );
    connect( &m_edit, SIGNAL( textEdited( const QString& ) ), this, SLOT( textEdited( const QString& ) ) );
65 66 67 68 69 70 71
}

WPropertyDoubleWidget::~WPropertyDoubleWidget()
{
    // cleanup
}

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
/**
 * Helper function converting a double into a nice formatted string.
 *
 * \param value the value to convert
 *
 * \return a string containing the double in a nicely formatted way.
 */
std::string toString( double value )
{
    std::ostringstream o;
    o.precision( 5 );
    o << value;
    return o.str();
}

87 88
void WPropertyDoubleWidget::update()
{
89 90
    // get the min constraint
    WPVDouble::PropertyConstraintMin minC = m_doubleProperty->getMin();
91
    m_min = 0;
92 93
    if ( minC.get() )
    {
94
        m_min = minC->getMin();
95 96 97 98
    }
    else
    {
        WLogger::getLogger()->addLogMessage(
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
99
                std::string( "The property has no minimum constraint. You should define it to avoid unexpected behaviour." ) +
100
                std::string( "Using default (" + boost::lexical_cast< std::string >( m_min ) + ")." ),
101 102 103 104 105
                "PropertyWidget( " + m_doubleProperty->getName() + " )", LL_WARNING );
    }

    // get the max constraint
    WPVDouble::PropertyConstraintMax maxC = m_doubleProperty->getMax();
106
    m_max = 100;
107 108
    if ( maxC.get() )
    {
109
        m_max = maxC->getMax();
110 111 112 113
    }
    else
    {
        WLogger::getLogger()->addLogMessage(
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
114
                std::string( "The property has no maximum constraint. You should define it to avoid unexpected behaviour." ) +
115
                std::string( "Using default (" + boost::lexical_cast< std::string >( m_max ) + ")." ),
116 117 118 119
                "PropertyWidget( " + m_doubleProperty->getName() + " )", LL_WARNING );
    }

    // setup the slider
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
    m_slider.setMinimum( 0 );
    m_slider.setMaximum( 100 );

    // calculate maximum size of the text widget.
    // XXX: this is not the optimal way but works for now
    // int length = m_min < 0 ? 5 : 4;   // reserve some extra space for the "-" in negative numbers
    // double fmax = std::max( std::abs( m_min ), std::abs( m_max ) );    // use the number with the most numbers
    // while ( ( fmax / 10 ) >= 1.0 )
    // {
    //     ++length;
    //     fmax /= 10.0;
    // }
    int length = 6; // use fixed length to have a uniform look among several widgets

    // resize the text widget
    //m_edit.setMaxLength( length );
    m_edit.setMaximumWidth( m_edit.minimumSizeHint().width() * length / 2 );
137 138
//     m_edit.setMinimumWidth( m_edit.minimumSizeHint().width() * length / 4 );
//     m_edit.resize( m_edit.minimumSizeHint().width() * length / 2, m_edit.size().height() );
139

140
    // set the initial values
141 142
    QString valStr = QString( toString( m_doubleProperty->get() ).c_str() );
    m_edit.setText( valStr );
143
    m_slider.setValue( toPercent( m_doubleProperty->get() ) );
144 145 146

    // do not forget to update the label
    m_asText.setText( valStr );
147 148
}

149 150 151 152 153 154 155 156 157 158 159
int WPropertyDoubleWidget::toPercent( double value )
{
    return 100.0 * ( ( value - m_min ) / ( m_max - m_min ) );
}

double WPropertyDoubleWidget::fromPercent( int perc )
{
    return ( static_cast< double >( perc ) / 100.0 ) * ( m_max - m_min ) + m_min;
}

void WPropertyDoubleWidget::sliderChanged( int value )
160 161
{
    // set to the property
162 163 164 165 166 167 168 169 170 171 172
    invalidate( !m_doubleProperty->set( fromPercent( value ) ) );    // NOTE: set automatically checks the validity of the value

    // set the value in the line edit
    m_edit.setText( QString( toString( m_doubleProperty->get() ).c_str() ) );
}

void WPropertyDoubleWidget::editChanged()
{
    // set the value in the line edit
    bool valid;
    double value = m_edit.text().toDouble( &valid );
173

174 175 176 177 178
    if ( !valid )
    {
        invalidate();
        return;
    }
179 180
    // set to the property
    invalidate( !m_doubleProperty->set( value ) );    // NOTE: set automatically checks the validity of the value
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199

    // update slider
    m_slider.setValue( toPercent( value ) );
}

void WPropertyDoubleWidget::textEdited( const QString& text )
{
    // this method does NOT set the property actually, but tries to validate it
    bool valid;

    double value = text.toDouble( &valid );
    if ( !valid )
    {
        invalidate();
        return;
    }

    // simply check validity
    invalidate( !m_doubleProperty->accept( value ) );
200 201
}