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