28 #define YUILogComponent "qt-wizard"
29 #include <yui/YUILog.h>
32 #include <yui/YShortcut.h>
35 #include <QSvgRenderer>
37 #include <QStackedWidget>
44 #include <qpushbutton.h>
46 #include <qtabwidget.h>
47 #include <qtoolbutton.h>
48 #include <QGraphicsDropShadowEffect>
50 #include "QY2ListView.h"
51 #include "QY2Styler.h"
52 #include "QY2HelpDialog.h"
53 #include <QGridLayout>
54 #include <QHeaderView>
60 #include "YQApplication.h"
62 #include "YQAlignment.h"
63 #include "YQReplacePoint.h"
66 #include "YQWizardButton.h"
67 #include "YQWidgetFactory.h"
68 #include "YQSignalBlocker.h"
69 #include <yui/YEvent.h>
70 #include "YQMainWinDock.h"
79 #define TEXTDOMAIN "qt"
81 #define USE_ICON_ON_HELP_BUTTON 0
86 const std::string & backButtonLabel,
87 const std::string & abortButtonLabel,
88 const std::string & nextButtonLabel,
89 YWizardMode wizardMode )
90 : QSplitter( Qt::Horizontal, (QWidget *) parent->widgetRep() )
97 , _backButtonLabel( backButtonLabel )
98 , _abortButtonLabel( abortButtonLabel )
99 , _nextButtonLabel( nextButtonLabel )
102 setObjectName(
"wizard" );
103 setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
105 QHBoxLayout* layout =
new QHBoxLayout(
this );
106 layout->setSpacing( 0 );
107 layout->setMargin( 0 );
109 setWidgetRep(
this );
112 _stepsEnabled = ( (wizardMode == YWizardMode_Steps) || main_wizard );
113 _treeEnabled = (wizardMode == YWizardMode_Tree);
115 _stepsRegistered =
false;
117 _direction = YQWizard::Forward;
124 _releaseNotesButton = 0;
136 _sendButtonEvents =
true;
137 _contentsReplacePoint = 0;
139 _previousWindowIcon = topLevelWidget()->windowIcon();
145 if( topLevelWidget()->windowTitle().isEmpty() )
148 QPixmap pixmap ( YUI::app()->applicationIcon().c_str() );
149 if ( !pixmap.isNull() )
150 setWindowIcon ( QIcon ( pixmap ) );
153 layout->addLayout( layoutSideBar(
this ) );
154 layout->addWidget( layoutWorkArea(
this ) );
156 setStretchFactor(indexOf(_sideBar),0);
157 setStretchFactor(indexOf(_workArea),1);
161 if ( !_stepsEnabled )
162 QY2Styler::styler()->registerWidget(
this );
164 if ( !main_wizard && _stepsEnabled )
168 else if ( main_wizard )
180 if (
this == main_wizard )
184 else if ( main_wizard )
187 main_wizard->setSizes( sizes() );
192 QY2Styler::styler()->unregisterWidget(
this );
193 topLevelWidget()->setWindowIcon( _previousWindowIcon );
199 return this != main_wizard;
203 void YQWizard::layoutTitleBar( QWidget * parent )
205 QFrame * titleBar =
new QFrame( parent );
206 YUI_CHECK_NEW( titleBar );
208 QHBoxLayout *layout =
new QHBoxLayout( titleBar );
209 titleBar->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
215 QLabel * left =
new QLabel( titleBar );
216 layout->addWidget( left );
217 left->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
218 left->setObjectName(
"titleBar-left" );
224 layout->addStretch( 10 );
231 QLabel * right =
new QLabel( titleBar );
232 YUI_CHECK_NEW( right );
234 layout->addWidget( right );
235 right->setObjectName(
"titleBar-right" );
239 QLayout *YQWizard::layoutSideBar( QWidget * parent )
241 _sideBar =
new QStackedWidget( parent );
242 YUI_CHECK_NEW( _sideBar );
244 _sideBar->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) );
245 _sideBar->setObjectName( QString(
"_sideBar-%1" ).arg(
long(
this ) ) );
246 _sideBar->installEventFilter(
this );
248 QVBoxLayout *vbox =
new QVBoxLayout( );
249 vbox->addWidget( _sideBar );
256 else if ( _stepsEnabled )
268 void YQWizard::layoutStepsPanel()
271 _stepsPanel =
new QFrame( _sideBar );
272 _sideBar->addWidget( _stepsPanel );
273 _stepsPanel->setObjectName(
"steps" );
274 QY2Styler::styler()->registerChildWidget(
this, _stepsPanel );
275 _stepsPanel->setProperty(
"class",
"steps QFrame" );
283 QString qId = fromUTF8(
id );
285 if ( _stepsIDs[ qId ] )
287 yuiError() <<
"Step ID \"" <<
id <<
"\" (\"" << text
288 <<
"\") already used for \"" << _stepsIDs[ qId ]->name() <<
"\""
293 if ( !_stepsList.empty() && _stepsList.last()->name() == fromUTF8( text ) )
301 _stepsList.last()->addID( qId );
309 _stepsIDs.insert( qId, _stepsList.last() );
312 if ( _currentStepID.isNull() )
313 _currentStepID = qId;
329 yuiDebug() <<
"updateSteps" << std::endl;
331 if ( !_stepsRegistered )
332 setUpdatesEnabled(
false);
335 delete _stepsPanel->layout();
336 _stepsPanel->setMaximumWidth( 65000 );
338 QVBoxLayout *_stepsVBox =
new QVBoxLayout( _stepsPanel );
340 QGridLayout *_stepsGrid =
new QGridLayout( );
341 _stepsGrid->setObjectName( QString(
"_stepsGrid_%1" ).arg(
long(
this ) ) );
342 YUI_CHECK_NEW( _stepsGrid );
343 _stepsVBox->addLayout( _stepsGrid );
344 _stepsGrid->setColumnMinimumWidth( 0, 10 );
345 _stepsGrid->setRowStretch( 0, 1 );
346 _stepsGrid->setRowStretch( 1, 1 );
347 _stepsGrid->setRowStretch( 2, 99 );
349 const int statusCol = 1;
350 const int nameCol = 2;
358 for ( QList<Step*>::iterator i = _stepsList.begin(); i != _stepsList.end(); ++i)
362 step->deleteLabels();
364 if ( step->isHeading() )
370 yuiDebug() <<
"Adding StepHeading \"" << step->name() <<
"\"" << std::endl;
371 QLabel * label =
new QLabel( step->name(), _stepsPanel );
372 YUI_CHECK_NEW( label );
373 label->setObjectName( step->name() );
374 label->setAlignment( Qt::AlignLeft | Qt::AlignTop );
375 label->setProperty(
"class",
"steps_heading" );
377 step->setNameLabel( label );
378 _stepsGrid->addWidget( label,
380 1, nameCol - statusCol + 1);
388 yuiDebug() <<
"Adding Step \"" << step->name() <<
"\"" << std::endl;
390 QLabel * statusLabel =
new QLabel( _stepsPanel );
391 YUI_CHECK_NEW( statusLabel );
393 step->setStatusLabel( statusLabel );
394 statusLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
395 _stepsGrid->addWidget( statusLabel, row, statusCol );
401 QLabel * nameLabel =
new QLabel( step->name(), _stepsPanel );
402 YUI_CHECK_NEW( nameLabel );
403 nameLabel->setAlignment( Qt::AlignLeft | Qt::AlignTop );
404 nameLabel->setObjectName( step->name() );
406 step->setNameLabel( nameLabel );
407 _stepsGrid->addWidget( nameLabel, row, nameCol );
414 _stepsVBox->addStretch( 99 );
415 QVBoxLayout *rbl =
new QVBoxLayout();
416 rbl->addWidget( _releaseNotesButton, 0, Qt::AlignCenter );
418 _stepsVBox->addLayout( rbl );
419 _stepsVBox->addStretch( 29 );
423 if ( !_stepsRegistered )
425 QY2Styler::styler()->registerWidget(
this );
426 setUpdatesEnabled(
true );
427 QY2Styler::styler()->updateRendering(
this );
428 _stepsRegistered =
true;
435 yuiDebug() <<
"steps dirty: " << _stepsDirty << std::endl;
441 QList<YQWizard::Step*>::iterator step = _stepsList.begin();
452 while ( step != _stepsList.end() && *step !=
currentStep )
454 ( *step )->setStatus( Step::Done );
460 if ( step != _stepsList.end() )
468 while ( step != _stepsList.end() )
470 ( *step )->setStatus( Step::Todo );
478 yuiDebug() <<
"Setting current step to \"" <<
id <<
"\"" << std::endl;
480 _currentStepID = fromUTF8(
id );
486 QList<Step*> _oldSteps = wizard->
stepsList();
488 if (_oldSteps.empty())
491 foreach(
Step *oldStep, _oldSteps)
495 if( !oldStep->isHeading() )
496 newStep =
new Step( oldStep->name());
500 foreach( QString oneId, oldStep->id())
502 newStep->addID( oneId);
503 _stepsIDs.insert( oneId, newStep );
506 newStep->setEnabled( oldStep->isEnabled());
507 _stepsList.append(newStep);
512 setSizes( main_wizard->sizes());
518 yuiDebug() <<
"Deleting steps" << std::endl;
521 _stepsPanel->setFixedWidth( _stepsPanel->width() );
523 qDeleteAll(_stepsList);
526 _currentStepID = QString::null;
536 return _stepsIDs[ id ];
540 void YQWizard::layoutTreePanel()
542 _treePanel =
new QFrame( _sideBar );
543 YUI_CHECK_NEW( _treePanel );
544 QHBoxLayout *layout =
new QHBoxLayout( _treePanel );
545 _sideBar->addWidget( _treePanel );
547 QVBoxLayout * vbox =
new QVBoxLayout();
548 YUI_CHECK_NEW( vbox );
549 layout->addLayout( vbox );
554 YUI_CHECK_NEW( _tree );
555 vbox->addWidget( _tree );
557 _tree->header()->hide();
558 _tree->header()->setSectionResizeMode( 0, QHeaderView::Stretch );
560 _tree->setRootIsDecorated(
true );
563 connect( _tree, &pclass(_tree)::itemSelectionChanged,
566 connect( _tree, &pclass(_tree)::itemDoubleClicked,
574 QString qId = fromUTF8(
id );
578 yuiError() <<
"YQWizard widget not created with `opt(`treeEnabled) !" << std::endl;
585 if ( ! parentID.empty() )
593 YUI_CHECK_NEW( item );
598 YUI_CHECK_NEW( item );
601 if ( ! qId.isEmpty() )
602 _treeIDs.insert( qId, item );
622 return _treeIDs[ fromUTF8(
id ) ];
636 _tree->setCurrentItem(item);
637 _tree->scrollToItem(item);
649 if ( item && ! item->id().isEmpty() )
666 QTreeWidgetItem * sel = _tree->currentItem();
672 if ( item && ! item->id().isEmpty() )
673 return toUTF8( item->id() );
677 return std::string();
682 QWidget *YQWizard::layoutWorkArea( QWidget * parent )
684 _workArea =
new QFrame( parent );
685 _workArea->setObjectName(
"work_area" );
687 QY2Styler::styler()->registerChildWidget(
this, _workArea );
689 QVBoxLayout *vbox =
new QVBoxLayout( _workArea );
690 YUI_CHECK_NEW( vbox );
696 _menuBar =
new QMenuBar( _workArea );
697 YUI_CHECK_NEW( _menuBar );
700 vbox->addWidget( _menuBar );
703 QVBoxLayout *innerbox =
new QVBoxLayout( _workArea );
704 YUI_CHECK_NEW( innerbox );
706 innerbox->setMargin ( YQWidgetMargin );
708 vbox->addLayout(innerbox);
709 vbox->setMargin( 0 );
716 QHBoxLayout * headingHBox =
new QHBoxLayout();
717 YUI_CHECK_NEW( headingHBox );
719 innerbox->addLayout( headingHBox );
721 _dialogIcon =
new QLabel( _workArea );
722 YUI_CHECK_NEW( _dialogIcon );
723 headingHBox->addWidget( _dialogIcon );
724 _dialogIcon->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum ) );
725 _dialogIcon->setObjectName(
"DialogIcon" );
727 _dialogHeading =
new QLabel( _workArea );
728 YUI_CHECK_NEW( _dialogHeading );
729 headingHBox->addWidget( _dialogHeading );
730 _dialogHeading->setAlignment( Qt::AlignLeft );
731 _dialogHeading->setWordWrap(
true );
732 _dialogHeading->setTextFormat( Qt::PlainText );
733 _dialogHeading->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum ) );
734 _dialogHeading->setObjectName(
"DialogHeading" );
736 _releaseNotesButton =
new QPushButton( _(
"Release Notes..." ), _workArea );
737 YUI_CHECK_NEW( _workArea );
738 headingHBox->addWidget( _releaseNotesButton );
739 _releaseNotesButton->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Minimum ) );
741 connect( _releaseNotesButton, &pclass(_releaseNotesButton)::clicked,
744 _releaseNotesButton->hide();
750 layoutClientArea( _workArea );
751 innerbox->addWidget( _clientArea );
757 QLayout *bb = layoutButtonBox( _workArea );
758 innerbox->addLayout( bb );
765 void YQWizard::layoutClientArea( QWidget * parent )
767 _clientArea =
new QFrame( parent );
768 YUI_CHECK_NEW( _clientArea );
769 _clientArea->setObjectName(
"_clientArea");
770 QVBoxLayout *layout =
new QVBoxLayout( _clientArea );
771 layout->setMargin( 0 );
777 _contents =
new YQAlignment(
this, _clientArea, YAlignCenter, YAlignCenter );
778 YUI_CHECK_NEW( _contents );
779 layout->addWidget( _contents );
780 _contents->QObject::setProperty(
"class",
"Contents" );
782 _contents->setStretchable( YD_HORIZ,
true );
783 _contents->setStretchable( YD_VERT,
true );
784 _contents->installEventFilter(
this );
785 _contents->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
791 _contentsReplacePoint = YUI::widgetFactory()->createReplacePoint( _contents );
797 YUI::widgetFactory()->createEmpty( _contentsReplacePoint );
798 _contentsReplacePoint->showChild();
804 QLayout *YQWizard::layoutButtonBox( QWidget * parent )
810 QHBoxLayout * hbox =
new QHBoxLayout();
811 YUI_CHECK_NEW( hbox );
813 hbox->setSpacing( 0 );
814 hbox->setMargin( 0 );
817 _helpButton =
new QPushButton( _(
"Help" ), parent );
818 YUI_CHECK_NEW( _helpButton );
819 _helpButton->setShortcut( Qt::Key_F1 );
821 connect( _helpButton, &pclass(_helpButton)::clicked,
824 hbox->addWidget( _helpButton );
826 hbox->addStretch( 10 );
832 _abortButton =
new YQWizardButton(
this, parent, _abortButtonLabel );
833 YUI_CHECK_NEW( _abortButton );
835 hbox->addWidget( (QWidget *) _abortButton->widgetRep() );
836 connect( _abortButton, &pclass(_abortButton)::clicked,
839 hbox->addSpacing( 10 );
845 _backButton =
new YQWizardButton(
this, parent, _backButtonLabel );
846 YUI_CHECK_NEW( _backButton );
848 hbox->addWidget( (QWidget *) _backButton->widgetRep() );
849 connect( _backButton, &pclass(_backButton)::clicked,
852 if ( _backButton->
text().isEmpty() )
859 hbox->addSpacing( 5 );
861 _nextButton =
new YQWizardButton(
this, parent, _nextButtonLabel );
862 YUI_CHECK_NEW( _nextButton );
864 hbox->addWidget( (QWidget *) _nextButton->widgetRep() );
865 connect( _nextButton, &pclass(_nextButton)::clicked,
887 if ( QString( signal ).contains(
"nextClicked()" ) )
889 yuiDebug() <<
"nextClicked connected, no longer directly sending button events" << std::endl;
890 _sendButtonEvents =
false;
897 if ( QString( signal ).contains(
"nextClicked()" ) )
899 yuiDebug() <<
"nextClicked disconnected, directly sending button events again" << std::endl;
900 _sendButtonEvents =
true;
909 if ( ! iconName.empty() )
911 QPixmap icon( iconName.c_str() );
914 yuiWarning() <<
"Couldn't load dialog icon \"" << iconName <<
"\"" << std::endl;
917 _dialogIcon->setPixmap( icon );
918 topLevelWidget()->setWindowIcon( icon );
923 _dialogIcon->clear();
924 topLevelWidget()->setWindowIcon( QIcon() );
932 QString title = fromUTF8( titleText.c_str() );
934 if ( !title.isEmpty() )
943 if ( _dialogHeading )
945 if ( ! headingText.empty() )
946 _dialogHeading->setText( fromUTF8( headingText ) );
948 _dialogHeading->clear();
954 if ( _dialogHeading )
956 QString label = _dialogHeading->text();
957 label = label.simplified();
959 if ( ! label.isEmpty() )
960 return toUTF8( label );
963 return "untitled YQWizard";
969 _qHelpText = fromUTF8( helpText );
970 _qHelpText.replace(
"&product;", fromUTF8( YUI::app()->productName() ) );
978 if ( _sendButtonEvents )
981 _direction = YQWizard::Backward;
989 if ( _sendButtonEvents )
998 if ( _sendButtonEvents )
1001 _direction = YQWizard::Forward;
1012 _helpDlg->setHelpText( _qHelpText );
1018 _helpDlg->activateWindow();
1025 YDialog::showRelNotesText();
1031 if ( _sideBar && _stepsPanel )
1033 _sideBar->setCurrentWidget( _stepsPanel );
1040 if ( _sideBar && _treePanel )
1042 _sideBar->setCurrentWidget( _treePanel );
1048 const std::string &
id )
1052 QMenu * menu =
new QMenu( _menuBar );
1053 YUI_CHECK_NEW( menu );
1055 _menuIDs.insert( fromUTF8(
id ), menu );
1056 _menuBar->addMenu( menu );
1057 menu->setTitle( fromUTF8( text ) );
1059 connect( menu, &pclass(menu)::triggered,
1068 const std::string & text,
1069 const std::string &
id )
1071 QMenu* parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
1075 QMenu * menu =
new QMenu( _menuBar );
1076 YUI_CHECK_NEW( menu );
1078 _menuIDs.insert( fromUTF8(
id ), menu );
1081 connect( menu, &pclass(menu)::triggered,
1086 yuiError() <<
"Can't find menu with ID " << parentMenuID << std::endl;
1092 const std::string & text,
1093 const std::string & idString )
1095 QMenu * parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
1100 int id = _menuEntryIDs.size();
1103 action = parentMenu->addAction( fromUTF8( text ) );
1104 _menuEntryIDs[ action ] = idString ;
1109 yuiError() <<
"Can't find menu with ID " << parentMenuID << std::endl;
1116 QMenu * parentMenu = _menuIDs[ fromUTF8( parentMenuID ) ];
1120 parentMenu->addSeparator();
1124 yuiError() <<
"Can't find menu with ID " << parentMenuID << std::endl;
1136 _menuEntryIDs.clear();
1143 if ( _menuEntryIDs.contains( action ) )
1149 yuiError() <<
"Invalid menu ID " << std::endl;
1162 return sizeHint().width();
1168 return sizeHint().height();
1174 resize( newWidth, newHeight );
1180 QSize contentsRect = _clientArea->contentsRect().size();
1181 _contents->
setSize( contentsRect.width(), contentsRect.height() );
1186 if ( ev->type() == QEvent::Resize && obj == _contents )
1192 if ( ev->type() == QEvent::Resize && obj == _sideBar && main_wizard ==
this && _stepsPanel )
1198 return QWidget::eventFilter( obj, ev );
1204 button->setLabel( newLabel );
1205 YDialog::currentDialog()->checkShortcuts();
1209 if ( wizardButton ) {
1211 if ( newLabel.empty() )
1212 wizardButton->
hide();
1214 wizardButton->
show();
1221 if ( ! _releaseNotesButton )
1223 yuiError() <<
"NULL Release Notes button" << std::endl;
1225 if ( ! _stepsPanel )
1226 yuiError() <<
"This works only if there is a \"steps\" panel!" << std::endl;
1232 _releaseNotesButton->setText( fromUTF8( YShortcut::cleanShortcutString( label ) ) );
1233 _releaseNotesButtonId = id;
1235 _releaseNotesButton->show();
1241 if ( _releaseNotesButton && !_releaseNotesButton->isHidden() )
1242 _releaseNotesButton->hide();
1252 _helpButton->setText( _(
"Help" ) );
1256 _stepsButton->setText( _(
"Steps" ) );
1260 _treeButton->setText( _(
"Tree" ) );
1263 _helpDlg->retranslate();
1268 void YQWizard::Step::deleteLabels()
1270 delete _statusLabel;
1285 if ( !_statusLabel || !_nameLabel || _status == s )
1292 _statusLabel->setProperty(
"class",
"todo-step-status QLabel" );
1293 _nameLabel->setProperty (
"class",
"todo-step-name QLabel" );
1298 _statusLabel->setProperty(
"class",
"done-step-status QLabel" );
1299 _nameLabel->setProperty (
"class",
"done-step-name QLabel" );
1304 _statusLabel->setProperty(
"class",
"current-step-status QLabel" );
1305 _nameLabel->setProperty (
"class",
"current-step-name QLabel" );
1308 _statusLabel->style()->unpolish( _statusLabel );
1309 _statusLabel->style()->polish( _statusLabel );
1310 _nameLabel->style()->unpolish( _nameLabel );
1311 _nameLabel->style()->polish( _nameLabel );
1314 #include "YQWizard.moc"
virtual std::string currentTreeSelection()
virtual void setSortByInsertionSequence(bool sortByInsertionSequence)
virtual void setCurrentStep(const std::string &id)
virtual void setDialogIcon(const std::string &iconName)
void setSideBarWidth(int width)
virtual void deleteTreeItems()
void sendTreeEvent(QTreeWidgetItem *item)
virtual std::string debugLabel() const
virtual void setHelpText(const std::string &helpText)
virtual void setButtonLabel(YPushButton *button, const std::string &newLabel)
virtual void setSize(int newWidth, int newHeight)
void connectNotify(const char *signal)
virtual void deleteSteps()
QString applicationTitle()
virtual void showReleaseNotesButton(const std::string &label, const std::string &id)
virtual bool eventFilter(QObject *obj, QEvent *ev)
virtual void selectTreeItem(const std::string &id)
YQWizard(YWidget *parent, const std::string &backButtonLabel, const std::string &abortButtonLabel, const std::string &nextButtonLabel, YWizardMode wizardMode=YWizardMode_Standard)
void copySteps(YQWizard *wizard)
virtual void addStepHeading(const std::string &text)
void treeSelectionChanged()
virtual void setDialogHeading(const std::string &headingText)
void resizeVisibleChild()
virtual void setDialogTitle(const std::string &titleText)
virtual void addMenuEntry(const std::string &parentMenuID, const std::string &text, const std::string &id)
static YQMainWinDock * mainWinDock()
YQWizard::TreeItem * findTreeItem(const std::string &id)
virtual void hideReleaseNotesButton()
void sendEvent(YEvent *event)
virtual void retranslateInternalButtons()
virtual void addMenuSeparator(const std::string &parentMenuID)
virtual void addStep(const std::string &text, const std::string &id)
virtual void deleteMenus()
virtual void addSubMenu(const std::string &parentMenuID, const std::string &text, const std::string &id)
YQWizard::Step * findStep(const QString &id)
virtual int preferredHeight()
void sendEvent(const std::string &id)
virtual void addMenu(const std::string &text, const std::string &id)
QList< YQWizard::Step * > stepsList()
virtual void addTreeItem(const std::string &parentID, const std::string &text, const std::string &id)
void disconnectNotify(const char *signal)
void sendMenuEvent(QAction *action)
virtual int preferredWidth()
static void setTextdomain(const char *domain)
virtual void setSize(int newWidth, int newHeight)
virtual void updateSteps()