00001
00012 #include "AxisWidget.h"
00013
00014 #if QT_VERSION < 0x040000
00015 #include <qabstractlayout.h>
00016 #else
00017
00018 #include <QtGui/QHBoxLayout>
00019 #include <QtGui/QVBoxLayout>
00020 #endif
00021
00022 #include "axes/Range.h"
00023
00024 #include <qpushbutton.h>
00025 #include <qpainter.h>
00026 #include <qevent.h>
00027 #include <qlabel.h>
00028 #include <qcheckbox.h>
00029 #include <qnamespace.h>
00030 #include <qscrollbar.h>
00031 #include <qlineedit.h>
00032 #include <qmessagebox.h>
00033 #include <qsizepolicy.h>
00034
00035 #include <cassert>
00036
00037 using std::string;
00038
00039 using namespace hippodraw;
00040
00043 AxisWidget::
00044 AxisWidget ( QWidget * parent, const char * name, Qt::WFlags wflags )
00045 : QWidget ( parent, name, wflags )
00046 {
00047
00048
00049
00050 lowTextLabel = new QLabel ( "Low: ", this, "lowTextLabel" );
00051 highTextLabel = new QLabel ( "High:", this, "highTextLabel" );
00052
00053 lowSlider = new QScrollBar ( Qt::Horizontal, this );
00054 lowSlider -> setRange ( 0, 99 );
00055 lowSlider -> setPageStep ( 20 );
00056 lowSlider -> setValue ( 50 );
00057 QSizePolicy policy;
00058 policy.setHorData ( QSizePolicy::MinimumExpanding );
00059 lowSlider -> setSizePolicy ( policy );
00060 #if QT_VERSION < 0x040000
00061 lowSlider -> setLineStep ( 1 );
00062 lowSlider ->setFocusPolicy ( WheelFocus );
00063 #else
00064 lowSlider -> setSingleStep ( 1 );
00065 lowSlider ->setFocusPolicy ( Qt::WheelFocus );
00066 #endif
00067
00068 highSlider = new QScrollBar ( Qt::Horizontal, this );
00069 highSlider -> setRange ( 0, 99 );
00070 highSlider -> setPageStep ( 20 );
00071 highSlider -> setValue ( 50 );
00072 highSlider -> setSizePolicy ( policy );
00073 #if QT_VERSION < 0x040000
00074 highSlider -> setLineStep ( 1 );
00075 highSlider ->setFocusPolicy ( WheelFocus );
00076 #else
00077 highSlider -> setSingleStep ( 1);
00078 highSlider ->setFocusPolicy ( Qt::WheelFocus );
00079 #endif
00080 lowTextBox = new QLineEdit ( this, "lowTextBox" );
00081 lowTextBox -> setMaximumHeight ( 26 );
00082 highTextBox = new QLineEdit ( this, "highTextBox" );
00083 highTextBox -> setMaximumHeight ( 26 );
00084
00085 zoomPanCheckBox = new QCheckBox ( "Zoom/Pan", this, "zoomPanCheckBox" );
00086
00087 m_isCut = false;
00088
00089
00090
00091 QVBoxLayout * grandParentLayout = new QVBoxLayout ( this, 2 );
00092 QHBoxLayout * parentLayout = new QHBoxLayout ( grandParentLayout, 5 );
00093
00094 QVBoxLayout * labelLayout = new QVBoxLayout ( parentLayout, 5 );
00095 QVBoxLayout * textSliderLayout = new QVBoxLayout ( parentLayout, 5 );
00096
00097 QHBoxLayout * lowLayout = new QHBoxLayout ( textSliderLayout, 5 );
00098 QHBoxLayout * highLayout = new QHBoxLayout ( textSliderLayout, 5 );
00099
00100 labelLayout->addWidget ( lowTextLabel );
00101 labelLayout->addWidget ( highTextLabel );
00102
00103 lowLayout->addWidget ( lowTextBox );
00104 lowLayout->addWidget ( lowSlider );
00105
00106 highLayout->addWidget ( highTextBox );
00107 highLayout->addWidget ( highSlider );
00108
00109 QHBoxLayout * checkboxlayout = new QHBoxLayout ( grandParentLayout, 5 );
00110 checkboxlayout->addWidget ( zoomPanCheckBox );
00111 checkboxlayout->setAlignment ( Qt::AlignHCenter );
00112
00113
00114
00115 connect ( lowTextBox, SIGNAL ( returnPressed() ),
00116 this, SIGNAL ( lowTextReturnPressed () ) );
00117
00118 connect ( highTextBox, SIGNAL ( returnPressed () ),
00119 this, SIGNAL ( highTextReturnPressed () ) );
00120
00121 connect ( lowSlider, SIGNAL ( sliderReleased () ),
00122 this, SIGNAL ( lowSliderReleased () ) );
00123
00124 connect ( highSlider, SIGNAL ( sliderReleased () ),
00125 this, SIGNAL ( highSliderReleased () ) );
00126
00127 connect ( lowSlider, SIGNAL ( valueChanged ( int ) ),
00128 this, SIGNAL ( lowSliderValueChanged ( int ) ) );
00129
00130 connect ( highSlider, SIGNAL ( valueChanged ( int ) ),
00131 this, SIGNAL ( highSliderValueChanged ( int ) ) );
00132
00133 connect ( lowSlider, SIGNAL ( sliderPressed () ),
00134 this, SIGNAL ( lowSliderPressed () ) );
00135
00136 connect ( highSlider, SIGNAL ( sliderPressed () ),
00137 this, SIGNAL ( highSliderPressed () ) );
00138
00139 connect ( zoomPanCheckBox, SIGNAL ( clicked () ),
00140 this, SIGNAL ( zoomPanCheckBoxClicked () ) );
00141
00142 }
00143
00144 AxisWidget::~AxisWidget ()
00145 {
00146 delete lowTextLabel;
00147 delete highTextLabel;
00148 delete lowSlider;
00149 delete highSlider;
00150 delete lowTextBox;
00151 delete highTextBox;
00152 delete zoomPanCheckBox;
00153 }
00154
00155 void
00156 AxisWidget::
00157 processTextBoxReturnPressed ( Range & currentRange,
00158 const Range & fullRange )
00159 {
00160
00161 if ( !zoomPanCheckBox->isChecked() ){
00162
00163 QString text1 = highTextBox->text();
00164 double hi = text1.toDouble();
00165 QString text = lowTextBox->text();
00166 double lo = text.toDouble();
00167
00168 if ( lo >= hi ) {
00169 invalidRangeError ( "Low not less than high" );
00170 highTextBox->setText ( QString("%1").arg(currentRange.high()) );
00171 lowTextBox->setText ( QString("%1").arg(currentRange.low()) );
00172 return;
00173 }
00174
00175 currentRange.setRange ( lo, hi, currentRange.pos() );
00176
00177 if ( !m_isCut ) return;
00178
00179
00180
00181 setSlider ( lowSlider, currentRange.low(), fullRange );
00182 setSlider ( highSlider, currentRange.high(), fullRange );
00183
00184 }
00185
00186 else {
00187
00188 if ( m_isCut ) {
00189
00190 double width = ( lowTextBox->text()).toDouble();
00191 double oldWidth = getWidthFromSlider ( fullRange );
00192 double position = ( highTextBox->text()).toDouble();
00193 double oldPosition = getPositionFromSlider ( fullRange );
00194
00195 if ( position - width / 2 < fullRange.low() ||
00196 position + width / 2 > fullRange.high() ) {
00197
00198 lowTextBox->setText ( QString("%1").arg( oldWidth ) );
00199 highTextBox->setText ( QString("%1").arg( oldPosition ) );
00200 return;
00201
00202 }
00203
00204
00205
00206 currentRange.setRange ( position - width / 2,
00207 position + width / 2,
00208 currentRange.pos() );
00209
00210
00211
00212 setSliderZero ( lowSlider, width, fullRange );
00213 setSlider ( highSlider, position, fullRange );
00214
00215 }
00216
00217 else {
00218
00219 double width = ( lowTextBox->text()).toDouble();
00220 double position = ( highTextBox->text()).toDouble();
00221
00222
00223
00224 currentRange.setRange ( position - width / 2,
00225 position + width / 2,
00226 currentRange.pos() );
00227
00228 }
00229
00230 }
00231
00232 }
00233
00234 void AxisWidget::processLowSliderReleased ( const Range & fullRange )
00235 {
00236 if ( !zoomPanCheckBox->isChecked() ){
00237 assert ( m_isCut );
00238 double low = (lowTextBox->text()).toDouble();
00239 setSlider ( lowSlider, low, fullRange );
00240 }
00241 else {
00242 double width = (lowTextBox->text()).toDouble();
00243 setSliderZero ( lowSlider, width, fullRange );
00244 }
00245
00246 }
00247
00248 void AxisWidget::processHighSliderReleased ( const Range & fullRange )
00249 {
00250 double positionOrHigh = ( highTextBox->text() ).toDouble();
00251 setSlider ( highSlider, positionOrHigh, fullRange );
00252 }
00253
00256 void
00257 AxisWidget::
00258 processLowSliderMoved ( int,
00259 Range & currentRange,
00260 const Range & fullRange )
00261 {
00262
00263 if ( ! zoomPanCheckBox->isChecked() ) {
00264
00265 assert ( m_isCut );
00266
00267 double new_low = getLowFromSlider ( fullRange );
00268
00269 if ( new_low < currentRange.high() ){
00270 currentRange.setLow ( new_low );
00271 }
00272
00273
00274
00275 double low = currentRange.low();
00276 lowTextBox->setText ( QString("%1").arg(low));
00277
00278 }
00279
00280 else {
00281
00282 if ( m_isCut ) {
00283
00284 double width = getWidthFromSlider ( fullRange );
00285 double position = getPositionFromSlider ( fullRange );
00286
00287 if ( position - width / 2 < fullRange.low() ||
00288 position + width / 2 > fullRange.high() ) {
00289 return;
00290
00291 }
00292
00293
00294
00295 currentRange.setRange ( position - width / 2,
00296 position + width / 2,
00297 currentRange.pos() );
00298
00299
00300
00301 lowTextBox->setText ( QString("%1").arg( width ) );
00302
00303 }
00304
00305 else {
00306
00307 double oldWidth = fullRange.length();
00308 double width = oldWidth * lowSlider->value() / 50 ;
00309 double position = ( fullRange.high() + fullRange.low() ) / 2 ;
00310
00311
00312
00313 currentRange.setRange ( position - width / 2,
00314 position + width / 2,
00315 currentRange.pos() );
00316
00317
00318
00319 lowTextBox->setText ( QString("%1").arg( width ) );
00320
00321
00322 }
00323
00324 }
00325
00326 }
00327
00330 void
00331 AxisWidget::
00332 processHighSliderMoved ( int,
00333 Range & currentRange,
00334 const Range & fullRange )
00335 {
00336 if ( ! zoomPanCheckBox->isChecked() ) {
00337
00338 assert ( m_isCut );
00339
00340 double new_high = getHighFromSlider ( fullRange );
00341
00342 if ( new_high > currentRange.low() ) {
00343 currentRange.setHigh ( new_high );
00344 }
00345
00346
00347
00348 double high = currentRange.high();
00349 highTextBox->setText ( QString("%1").arg(high));
00350 }
00351 else {
00352
00353 if ( m_isCut ) {
00354
00355 double width = currentRange.length ();
00356 double position = getPositionFromSlider ( fullRange );
00357
00358
00359
00360 currentRange.setRange ( position - 0.5 * width,
00361 position + 0.5 * width,
00362 currentRange.pos() );
00363
00364
00365
00366 highTextBox->setText ( QString("%1").arg( position ) );
00367
00368 }
00369 else {
00370
00371 double width = fullRange.length();
00372 double oldPosition = ( fullRange.high() + fullRange.low() ) / 2 ;
00373 double position = ( width *
00374 ( ( double ) ( highSlider->value() - 50 ) ) / 50
00375 ) + oldPosition;
00376
00377
00378
00379 currentRange.setRange ( position - width / 2,
00380 position + width / 2,
00381 currentRange.pos() );
00382
00383
00384
00385 highTextBox->setText ( QString("%1").arg( position ) );
00386 }
00387 }
00388 }
00389
00390 void
00391 AxisWidget::
00392 processZoomPanCheckBoxClicked ( const Range & currentRange,
00393 const Range & fullRange )
00394 {
00395
00396 bool checked = zoomPanCheckBox->isChecked();
00397
00398 if ( m_isCut )
00399 if ( checked )
00400 {
00401
00402
00403
00404
00405 highTextLabel->setText ( "Position" );
00406 lowTextLabel->setText ( "Width " );
00407
00408 double currentWidth = currentRange.high() - currentRange.low();
00409 double currentPosition
00410 = 0.5 * ( currentRange.high() + currentRange.low() );
00411
00412 highTextBox->setText ( QString("%1").arg(currentPosition) );
00413 lowTextBox->setText ( QString("%1").arg(currentWidth) );
00414
00415 setSlider ( highSlider, currentPosition, fullRange );
00416 setSliderZero ( lowSlider, currentWidth, fullRange );
00417
00418 }
00419 else
00420 {
00421 highTextLabel->setText ( "High " );
00422 lowTextLabel->setText ( "Low " );
00423
00424 highTextBox->setText ( QString("%1").arg(currentRange.high()) );
00425 lowTextBox->setText ( QString("%1").arg(currentRange.low()) );
00426
00427 setSlider ( highSlider, currentRange.high(), fullRange );
00428 setSlider ( lowSlider, currentRange.low(), fullRange );
00429
00430 }
00431 else
00432 if ( checked )
00433 {
00434 highTextLabel->setText ( "Position" );
00435 lowTextLabel->setText ( "Width " );
00436
00437 double currentWidth = currentRange.high() - currentRange.low();
00438 double currentPosition
00439 = 0.5 * ( currentRange.high() + currentRange.low() );
00440
00441 highTextBox->setText ( QString("%1").arg(currentPosition) );
00442 lowTextBox->setText ( QString("%1").arg(currentWidth) );
00443 }
00444 else
00445 {
00446 highTextLabel->setText ( "High " );
00447 lowTextLabel->setText ( "Low " );
00448
00449 highTextBox->setText ( QString("%1").arg ( currentRange.high() ) );
00450 lowTextBox->setText ( QString("%1").arg ( currentRange.low() ) );
00451 }
00452 }
00453
00454 void AxisWidget::setCut ( bool flag )
00455 {
00456 m_isCut = flag;
00457 }
00458
00459 void
00460 AxisWidget::
00461 invalidRangeError ( const std::string & bad )
00462 {
00463
00464 const string message
00465 = "Attempt to apply invalid range:\n\n"
00466 + bad + "\n\n"
00467 + "Low end of range must be less than high end.";
00468
00469 QMessageBox::critical ( this,
00470 "Range error",
00471 message.c_str(),
00472 QMessageBox::Ok,
00473 Qt::NoButton,
00474 Qt::NoButton );
00475
00476 }
00477
00478 void AxisWidget::setLowText ( const QString & s, bool readonly )
00479 {
00480 lowTextBox->setText ( s );
00481 lowTextBox->setReadOnly ( readonly );
00482 }
00483
00484 void AxisWidget::setHighText ( const QString & s, bool readonly )
00485 {
00486 highTextBox->setText ( s );
00487 highTextBox->setReadOnly ( readonly );
00488 }
00489
00490 QScrollBar *
00491 AxisWidget::
00492 getLowSlider ()
00493 {
00494 return lowSlider;
00495 }
00496
00497 int AxisWidget::getLowSliderValue ()
00498 {
00499 return lowSlider->value();
00500 }
00501
00502 void AxisWidget::setLowSliderValue ( int value )
00503 {
00504 lowSlider->setValue ( value );
00505 }
00506
00507 QScrollBar *
00508 AxisWidget::
00509 getHighSlider ()
00510 {
00511 return highSlider;
00512 }
00513
00514 int AxisWidget::getHighSliderValue ()
00515 {
00516 return highSlider->value();
00517 }
00518
00519 void AxisWidget::setHighSliderValue ( int value )
00520 {
00521 highSlider->setValue ( value );
00522 }
00523
00524 void AxisWidget::setAllDisabled ( bool flag )
00525 {
00526 lowTextBox->setDisabled ( flag );
00527 highTextBox->setDisabled ( flag );
00528 lowSlider->setDisabled ( flag );
00529 highSlider->setDisabled ( flag );
00530 zoomPanCheckBox->setDisabled ( flag );
00531 }
00532
00533 void
00534 AxisWidget::
00535 updateCutControlValues ( const Range & currentRange,
00536 const Range & fullRange )
00537 {
00538
00539 assert ( m_isCut );
00540
00541 zoomPanCheckBox->setChecked ( false );
00542 highTextLabel->setText ( "High " );
00543 lowTextLabel->setText ( "Low " );
00544
00545 highTextBox->setText ( QString("%1").arg(currentRange.high()) );
00546 lowTextBox->setText ( QString("%1").arg(currentRange.low()) );
00547
00548 setSlider ( highSlider, currentRange.high(), fullRange );
00549 setSlider ( lowSlider, currentRange.low(), fullRange );
00550
00551 }
00552
00553 bool AxisWidget::isZoomPanChecked ()
00554 {
00555 return zoomPanCheckBox->isChecked();
00556 }
00557
00558 void AxisWidget::setZoomPan ( bool check, bool disabled )
00559 {
00560 zoomPanCheckBox->setChecked ( check );
00561 zoomPanCheckBox->setDisabled ( disabled );
00562 }
00563
00564 double
00565 AxisWidget::
00566 getWidthFromSlider ( const Range & fullRange )
00567 {
00568
00569 double width = ( ( (double)( lowSlider->value() -
00570 lowSlider->minValue() ) ) /
00571 ( (double)( lowSlider->maxValue() -
00572 lowSlider->minValue() ) ) *
00573 fullRange.length()
00574 );
00575 return width;
00576 }
00577
00578 double
00579 AxisWidget::
00580 getPositionFromSlider ( const Range & fullRange )
00581 {
00582
00583 double position
00584 = ( ( static_cast <double>( highSlider->value() -
00585 highSlider->minValue() ) ) /
00586 ( static_cast <double>( highSlider->maxValue() -
00587 highSlider->minValue() ) ) *
00588 fullRange.length()
00589 ) + fullRange.low();
00590 return position;
00591 }
00592
00593 double
00594 AxisWidget::
00595 getLowFromSlider ( const Range & fullRange )
00596 {
00597
00598 double low
00599 = ( ( static_cast<double>( lowSlider->value() -
00600 lowSlider->minValue() ) ) /
00601 ( static_cast<double>( lowSlider->maxValue() -
00602 lowSlider->minValue() ) ) *
00603 fullRange.length()
00604 ) + fullRange.low();
00605
00606 return low;
00607 }
00608
00609 double
00610 AxisWidget::
00611 getHighFromSlider ( const Range & fullRange )
00612 {
00613
00614 double high = ( ( static_cast <double>( highSlider->value() -
00615 highSlider->minValue() ) ) /
00616 ( static_cast<double>( highSlider->maxValue() -
00617 highSlider->minValue() ) ) *
00618 fullRange.length()
00619 ) + fullRange.low();
00620 return high;
00621 }
00622
00623 void
00624 AxisWidget::
00625 setSlider ( QScrollBar * s, double value,
00626 const Range & fullRange )
00627 {
00628 int val
00629 = static_cast < int >(
00630 ( value - fullRange.low() ) /
00631 fullRange.length () *
00632 static_cast<double> ( s->maxValue() - s->minValue() )
00633 ) + s->minValue();
00634
00635 s->setValue ( val );
00636 }
00637
00638 void
00639 AxisWidget::
00640 setSliderZero ( QScrollBar * s, double value,
00641 const Range & fullRange )
00642 {
00643 int val
00644 = static_cast<int>(
00645 ( value ) / fullRange.length () *
00646 static_cast<double>( s->maxValue() - s->minValue() )
00647 ) + s->minValue();
00648
00649 s->setValue ( val );
00650 }