qwt_plot.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
  2. * Qwt Widget Library
  3. * Copyright (C) 1997 Josef Wilgen
  4. * Copyright (C) 2002 Uwe Rathmann
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Qwt License, Version 1.0
  8. *****************************************************************************/
  9. #include "qwt_plot.h"
  10. #include "qwt_plot_dict.h"
  11. #include "qwt_plot_layout.h"
  12. #include "qwt_scale_widget.h"
  13. #include "qwt_scale_engine.h"
  14. #include "qwt_text_label.h"
  15. #include "qwt_legend.h"
  16. #include "qwt_dyngrid_layout.h"
  17. #include "qwt_plot_canvas.h"
  18. #include <qpainter.h>
  19. #include <qpointer.h>
  20. #include <qpaintengine.h>
  21. #include <qapplication.h>
  22. #include <qevent.h>
  23. class QwtPlot::PrivateData
  24. {
  25. public:
  26. QPointer<QwtTextLabel> lblTitle;
  27. QPointer<QwtPlotCanvas> canvas;
  28. QPointer<QwtLegend> legend;
  29. QwtPlotLayout *layout;
  30. bool autoReplot;
  31. };
  32. /*!
  33. \brief Constructor
  34. \param parent Parent widget
  35. */
  36. QwtPlot::QwtPlot( QWidget *parent ):
  37. QFrame( parent )
  38. {
  39. initPlot( QwtText() );
  40. }
  41. /*!
  42. \brief Constructor
  43. \param title Title text
  44. \param parent Parent widget
  45. */
  46. QwtPlot::QwtPlot( const QwtText &title, QWidget *parent ):
  47. QFrame( parent )
  48. {
  49. initPlot( title );
  50. }
  51. //! Destructor
  52. QwtPlot::~QwtPlot()
  53. {
  54. detachItems( QwtPlotItem::Rtti_PlotItem, autoDelete() );
  55. delete d_data->layout;
  56. deleteAxesData();
  57. delete d_data;
  58. }
  59. /*!
  60. \brief Initializes a QwtPlot instance
  61. \param title Title text
  62. */
  63. void QwtPlot::initPlot( const QwtText &title )
  64. {
  65. d_data = new PrivateData;
  66. d_data->layout = new QwtPlotLayout;
  67. d_data->autoReplot = false;
  68. d_data->lblTitle = new QwtTextLabel( title, this );
  69. d_data->lblTitle->setFont( QFont( fontInfo().family(), 14, QFont::Bold ) );
  70. QwtText text( title );
  71. text.setRenderFlags( Qt::AlignCenter | Qt::TextWordWrap );
  72. d_data->lblTitle->setText( text );
  73. d_data->legend = NULL;
  74. initAxesData();
  75. d_data->canvas = new QwtPlotCanvas( this );
  76. d_data->canvas->setFrameStyle( QFrame::Panel | QFrame::Sunken );
  77. d_data->canvas->setLineWidth( 2 );
  78. updateTabOrder();
  79. setSizePolicy( QSizePolicy::MinimumExpanding,
  80. QSizePolicy::MinimumExpanding );
  81. }
  82. /*!
  83. \brief Adds handling of layout requests
  84. */
  85. bool QwtPlot::event( QEvent *e )
  86. {
  87. bool ok = QFrame::event( e );
  88. switch ( e->type() )
  89. {
  90. case QEvent::LayoutRequest:
  91. updateLayout();
  92. break;
  93. case QEvent::PolishRequest:
  94. polish();
  95. break;
  96. default:;
  97. }
  98. return ok;
  99. }
  100. //! Replots the plot if QwtPlot::autoReplot() is \c true.
  101. void QwtPlot::autoRefresh()
  102. {
  103. if ( d_data->autoReplot )
  104. replot();
  105. }
  106. /*!
  107. \brief Set or reset the autoReplot option
  108. If the autoReplot option is set, the plot will be
  109. updated implicitly by manipulating member functions.
  110. Since this may be time-consuming, it is recommended
  111. to leave this option switched off and call replot()
  112. explicitly if necessary.
  113. The autoReplot option is set to false by default, which
  114. means that the user has to call replot() in order to make
  115. changes visible.
  116. \param tf \c true or \c false. Defaults to \c true.
  117. \sa replot()
  118. */
  119. void QwtPlot::setAutoReplot( bool tf )
  120. {
  121. d_data->autoReplot = tf;
  122. }
  123. //! \return true if the autoReplot option is set.
  124. bool QwtPlot::autoReplot() const
  125. {
  126. return d_data->autoReplot;
  127. }
  128. /*!
  129. Change the plot's title
  130. \param title New title
  131. */
  132. void QwtPlot::setTitle( const QString &title )
  133. {
  134. if ( title != d_data->lblTitle->text().text() )
  135. {
  136. d_data->lblTitle->setText( title );
  137. updateLayout();
  138. }
  139. }
  140. /*!
  141. Change the plot's title
  142. \param title New title
  143. */
  144. void QwtPlot::setTitle( const QwtText &title )
  145. {
  146. if ( title != d_data->lblTitle->text() )
  147. {
  148. d_data->lblTitle->setText( title );
  149. updateLayout();
  150. }
  151. }
  152. //! \return the plot's title
  153. QwtText QwtPlot::title() const
  154. {
  155. return d_data->lblTitle->text();
  156. }
  157. //! \return the plot's title
  158. QwtPlotLayout *QwtPlot::plotLayout()
  159. {
  160. return d_data->layout;
  161. }
  162. //! \return the plot's titel label.
  163. const QwtPlotLayout *QwtPlot::plotLayout() const
  164. {
  165. return d_data->layout;
  166. }
  167. //! \return the plot's titel label.
  168. QwtTextLabel *QwtPlot::titleLabel()
  169. {
  170. return d_data->lblTitle;
  171. }
  172. /*!
  173. \return the plot's titel label.
  174. */
  175. const QwtTextLabel *QwtPlot::titleLabel() const
  176. {
  177. return d_data->lblTitle;
  178. }
  179. /*!
  180. \return the plot's legend
  181. \sa insertLegend()
  182. */
  183. QwtLegend *QwtPlot::legend()
  184. {
  185. return d_data->legend;
  186. }
  187. /*!
  188. \return the plot's legend
  189. \sa insertLegend()
  190. */
  191. const QwtLegend *QwtPlot::legend() const
  192. {
  193. return d_data->legend;
  194. }
  195. /*!
  196. \return the plot's canvas
  197. */
  198. QwtPlotCanvas *QwtPlot::canvas()
  199. {
  200. return d_data->canvas;
  201. }
  202. /*!
  203. \return the plot's canvas
  204. */
  205. const QwtPlotCanvas *QwtPlot::canvas() const
  206. {
  207. return d_data->canvas;
  208. }
  209. //! Polish
  210. void QwtPlot::polish()
  211. {
  212. replot();
  213. }
  214. /*!
  215. Return sizeHint
  216. \sa minimumSizeHint()
  217. */
  218. QSize QwtPlot::sizeHint() const
  219. {
  220. int dw = 0;
  221. int dh = 0;
  222. for ( int axisId = 0; axisId < axisCnt; axisId++ )
  223. {
  224. if ( axisEnabled( axisId ) )
  225. {
  226. const int niceDist = 40;
  227. const QwtScaleWidget *scaleWidget = axisWidget( axisId );
  228. const QwtScaleDiv &scaleDiv = scaleWidget->scaleDraw()->scaleDiv();
  229. const int majCnt = scaleDiv.ticks( QwtScaleDiv::MajorTick ).count();
  230. if ( axisId == yLeft || axisId == yRight )
  231. {
  232. int hDiff = ( majCnt - 1 ) * niceDist
  233. - scaleWidget->minimumSizeHint().height();
  234. if ( hDiff > dh )
  235. dh = hDiff;
  236. }
  237. else
  238. {
  239. int wDiff = ( majCnt - 1 ) * niceDist
  240. - scaleWidget->minimumSizeHint().width();
  241. if ( wDiff > dw )
  242. dw = wDiff;
  243. }
  244. }
  245. }
  246. return minimumSizeHint() + QSize( dw, dh );
  247. }
  248. /*!
  249. \brief Return a minimum size hint
  250. */
  251. QSize QwtPlot::minimumSizeHint() const
  252. {
  253. QSize hint = d_data->layout->minimumSizeHint( this );
  254. hint += QSize( 2 * frameWidth(), 2 * frameWidth() );
  255. return hint;
  256. }
  257. /*!
  258. Resize and update internal layout
  259. \param e Resize event
  260. */
  261. void QwtPlot::resizeEvent( QResizeEvent *e )
  262. {
  263. QFrame::resizeEvent( e );
  264. updateLayout();
  265. }
  266. /*!
  267. \brief Redraw the plot
  268. If the autoReplot option is not set (which is the default)
  269. or if any curves are attached to raw data, the plot has to
  270. be refreshed explicitly in order to make changes visible.
  271. \sa setAutoReplot()
  272. \warning Calls canvas()->repaint, take care of infinite recursions
  273. */
  274. void QwtPlot::replot()
  275. {
  276. bool doAutoReplot = autoReplot();
  277. setAutoReplot( false );
  278. updateAxes();
  279. /*
  280. Maybe the layout needs to be updated, because of changed
  281. axes labels. We need to process them here before painting
  282. to avoid that scales and canvas get out of sync.
  283. */
  284. QApplication::sendPostedEvents( this, QEvent::LayoutRequest );
  285. d_data->canvas->replot();
  286. setAutoReplot( doAutoReplot );
  287. }
  288. /*!
  289. \brief Adjust plot content to its current size.
  290. \sa resizeEvent()
  291. */
  292. void QwtPlot::updateLayout()
  293. {
  294. d_data->layout->activate( this, contentsRect() );
  295. QRect titleRect = d_data->layout->titleRect().toRect();
  296. QRect scaleRect[QwtPlot::axisCnt];
  297. for ( int axisId = 0; axisId < axisCnt; axisId++ )
  298. scaleRect[axisId] = d_data->layout->scaleRect( axisId ).toRect();
  299. QRect legendRect = d_data->layout->legendRect().toRect();
  300. QRect canvasRect = d_data->layout->canvasRect().toRect();
  301. //
  302. // resize and show the visible widgets
  303. //
  304. if ( !d_data->lblTitle->text().isEmpty() )
  305. {
  306. d_data->lblTitle->setGeometry( titleRect );
  307. if ( !d_data->lblTitle->isVisible() )
  308. d_data->lblTitle->show();
  309. }
  310. else
  311. d_data->lblTitle->hide();
  312. for ( int axisId = 0; axisId < axisCnt; axisId++ )
  313. {
  314. if ( axisEnabled( axisId ) )
  315. {
  316. axisWidget( axisId )->setGeometry( scaleRect[axisId] );
  317. if ( axisId == xBottom || axisId == xTop )
  318. {
  319. QRegion r( scaleRect[axisId] );
  320. if ( axisEnabled( yLeft ) )
  321. r = r.subtract( QRegion( scaleRect[yLeft] ) );
  322. if ( axisEnabled( yRight ) )
  323. r = r.subtract( QRegion( scaleRect[yRight] ) );
  324. r.translate( -d_data->layout->scaleRect( axisId ).x(),
  325. -scaleRect[axisId].y() );
  326. axisWidget( axisId )->setMask( r );
  327. }
  328. if ( !axisWidget( axisId )->isVisible() )
  329. axisWidget( axisId )->show();
  330. }
  331. else
  332. axisWidget( axisId )->hide();
  333. }
  334. if ( d_data->legend &&
  335. d_data->layout->legendPosition() != ExternalLegend )
  336. {
  337. if ( d_data->legend->itemCount() > 0 )
  338. {
  339. d_data->legend->setGeometry( legendRect );
  340. d_data->legend->show();
  341. }
  342. else
  343. d_data->legend->hide();
  344. }
  345. d_data->canvas->setGeometry( canvasRect );
  346. }
  347. /*!
  348. Update the focus tab order
  349. The order is changed so that the canvas will be in front of the
  350. first legend item, or behind the last legend item - depending
  351. on the position of the legend.
  352. */
  353. void QwtPlot::updateTabOrder()
  354. {
  355. if ( d_data->canvas->focusPolicy() == Qt::NoFocus )
  356. return;
  357. if ( d_data->legend.isNull()
  358. || d_data->layout->legendPosition() == ExternalLegend
  359. || d_data->legend->legendItems().count() == 0 )
  360. {
  361. return;
  362. }
  363. // Depending on the position of the legend the
  364. // tab order will be changed that the canvas is
  365. // next to the last legend item, or before
  366. // the first one.
  367. const bool canvasFirst =
  368. d_data->layout->legendPosition() == QwtPlot::BottomLegend ||
  369. d_data->layout->legendPosition() == QwtPlot::RightLegend;
  370. QWidget *previous = NULL;
  371. QWidget *w = d_data->canvas;
  372. while ( ( w = w->nextInFocusChain() ) != d_data->canvas )
  373. {
  374. bool isLegendItem = false;
  375. if ( w->focusPolicy() != Qt::NoFocus
  376. && w->parent() && w->parent() == d_data->legend->contentsWidget() )
  377. {
  378. isLegendItem = true;
  379. }
  380. if ( canvasFirst )
  381. {
  382. if ( isLegendItem )
  383. break;
  384. previous = w;
  385. }
  386. else
  387. {
  388. if ( isLegendItem )
  389. previous = w;
  390. else
  391. {
  392. if ( previous )
  393. break;
  394. }
  395. }
  396. }
  397. if ( previous && previous != d_data->canvas )
  398. setTabOrder( previous, d_data->canvas );
  399. }
  400. /*!
  401. Redraw the canvas.
  402. \param painter Painter used for drawing
  403. \warning drawCanvas calls drawItems what is also used
  404. for printing. Applications that like to add individual
  405. plot items better overload drawItems()
  406. \sa drawItems()
  407. */
  408. void QwtPlot::drawCanvas( QPainter *painter )
  409. {
  410. QwtScaleMap maps[axisCnt];
  411. for ( int axisId = 0; axisId < axisCnt; axisId++ )
  412. maps[axisId] = canvasMap( axisId );
  413. drawItems( painter, d_data->canvas->contentsRect(), maps );
  414. }
  415. /*!
  416. Redraw the canvas items.
  417. \param painter Painter used for drawing
  418. \param canvasRect Bounding rectangle where to paint
  419. \param map QwtPlot::axisCnt maps, mapping between plot and paint device coordinates
  420. */
  421. void QwtPlot::drawItems( QPainter *painter, const QRectF &canvasRect,
  422. const QwtScaleMap map[axisCnt] ) const
  423. {
  424. const QwtPlotItemList& itmList = itemList();
  425. for ( QwtPlotItemIterator it = itmList.begin();
  426. it != itmList.end(); ++it )
  427. {
  428. QwtPlotItem *item = *it;
  429. if ( item && item->isVisible() )
  430. {
  431. painter->save();
  432. painter->setRenderHint( QPainter::Antialiasing,
  433. item->testRenderHint( QwtPlotItem::RenderAntialiased ) );
  434. item->draw( painter,
  435. map[item->xAxis()], map[item->yAxis()],
  436. canvasRect );
  437. painter->restore();
  438. }
  439. }
  440. }
  441. /*!
  442. \param axisId Axis
  443. \return Map for the axis on the canvas. With this map pixel coordinates can
  444. translated to plot coordinates and vice versa.
  445. \sa QwtScaleMap, transform(), invTransform()
  446. */
  447. QwtScaleMap QwtPlot::canvasMap( int axisId ) const
  448. {
  449. QwtScaleMap map;
  450. if ( !d_data->canvas )
  451. return map;
  452. map.setTransformation( axisScaleEngine( axisId )->transformation() );
  453. const QwtScaleDiv *sd = axisScaleDiv( axisId );
  454. map.setScaleInterval( sd->lowerBound(), sd->upperBound() );
  455. if ( axisEnabled( axisId ) )
  456. {
  457. const QwtScaleWidget *s = axisWidget( axisId );
  458. if ( axisId == yLeft || axisId == yRight )
  459. {
  460. double y = s->y() + s->startBorderDist() - d_data->canvas->y();
  461. double h = s->height() - s->startBorderDist() - s->endBorderDist();
  462. map.setPaintInterval( y + h, y );
  463. }
  464. else
  465. {
  466. double x = s->x() + s->startBorderDist() - d_data->canvas->x();
  467. double w = s->width() - s->startBorderDist() - s->endBorderDist();
  468. map.setPaintInterval( x, x + w );
  469. }
  470. }
  471. else
  472. {
  473. int margin = 0;
  474. if ( !plotLayout()->alignCanvasToScales() )
  475. margin = plotLayout()->canvasMargin( axisId );
  476. const QRect &canvasRect = d_data->canvas->contentsRect();
  477. if ( axisId == yLeft || axisId == yRight )
  478. {
  479. map.setPaintInterval( canvasRect.bottom() - margin,
  480. canvasRect.top() + margin );
  481. }
  482. else
  483. {
  484. map.setPaintInterval( canvasRect.left() + margin,
  485. canvasRect.right() - margin );
  486. }
  487. }
  488. return map;
  489. }
  490. /*!
  491. Change the margin of the plot. The margin is the space
  492. around all components.
  493. \param margin new margin
  494. \sa QwtPlotLayout::setMargin(), margin(), plotLayout()
  495. */
  496. void QwtPlot::setMargin( int margin )
  497. {
  498. if ( margin < 0 )
  499. margin = 0;
  500. if ( margin != d_data->layout->margin() )
  501. {
  502. d_data->layout->setMargin( margin );
  503. updateLayout();
  504. }
  505. }
  506. /*!
  507. \return margin
  508. \sa setMargin(), QwtPlotLayout::margin(), plotLayout()
  509. */
  510. int QwtPlot::margin() const
  511. {
  512. return d_data->layout->margin();
  513. }
  514. /*!
  515. \brief Change the background of the plotting area
  516. Sets c to QPalette::Window of all colorgroups of
  517. the palette of the canvas. Using canvas()->setPalette()
  518. is a more powerful way to set these colors.
  519. \param c new background color
  520. */
  521. void QwtPlot::setCanvasBackground( const QColor &c )
  522. {
  523. QPalette p = d_data->canvas->palette();
  524. for ( int i = 0; i < QPalette::NColorGroups; i++ )
  525. p.setColor( ( QPalette::ColorGroup )i, QPalette::Window, c );
  526. canvas()->setPalette( p );
  527. }
  528. /*!
  529. Nothing else than: canvas()->palette().color(
  530. QPalette::Normal, QPalette::Window);
  531. \return the background color of the plotting area.
  532. */
  533. const QColor &QwtPlot::canvasBackground() const
  534. {
  535. return canvas()->palette().color(
  536. QPalette::Normal, QPalette::Window );
  537. }
  538. /*!
  539. \brief Change the border width of the plotting area
  540. Nothing else than canvas()->setLineWidth(w),
  541. left for compatibility only.
  542. \param w new border width
  543. */
  544. void QwtPlot::setCanvasLineWidth( int w )
  545. {
  546. canvas()->setLineWidth( w );
  547. updateLayout();
  548. }
  549. /*!
  550. Nothing else than: canvas()->lineWidth(),
  551. left for compatibility only.
  552. \return the border width of the plotting area
  553. */
  554. int QwtPlot::canvasLineWidth() const
  555. {
  556. return canvas()->lineWidth();
  557. }
  558. /*!
  559. \return \c true if the specified axis exists, otherwise \c false
  560. \param axisId axis index
  561. */
  562. bool QwtPlot::axisValid( int axisId )
  563. {
  564. return ( ( axisId >= QwtPlot::yLeft ) && ( axisId < QwtPlot::axisCnt ) );
  565. }
  566. /*!
  567. Called internally when the legend has been clicked on.
  568. Emits a legendClicked() signal.
  569. */
  570. void QwtPlot::legendItemClicked()
  571. {
  572. if ( d_data->legend && sender()->isWidgetType() )
  573. {
  574. QwtPlotItem *plotItem =
  575. ( QwtPlotItem* )d_data->legend->find( ( QWidget * )sender() );
  576. if ( plotItem )
  577. Q_EMIT legendClicked( plotItem );
  578. }
  579. }
  580. /*!
  581. Called internally when the legend has been checked
  582. Emits a legendClicked() signal.
  583. */
  584. void QwtPlot::legendItemChecked( bool on )
  585. {
  586. if ( d_data->legend && sender()->isWidgetType() )
  587. {
  588. QwtPlotItem *plotItem =
  589. ( QwtPlotItem* )d_data->legend->find( ( QWidget * )sender() );
  590. if ( plotItem )
  591. Q_EMIT legendChecked( plotItem, on );
  592. }
  593. }
  594. /*!
  595. \brief Insert a legend
  596. If the position legend is \c QwtPlot::LeftLegend or \c QwtPlot::RightLegend
  597. the legend will be organized in one column from top to down.
  598. Otherwise the legend items will be placed in a table
  599. with a best fit number of columns from left to right.
  600. If pos != QwtPlot::ExternalLegend the plot widget will become
  601. parent of the legend. It will be deleted when the plot is deleted,
  602. or another legend is set with insertLegend().
  603. \param legend Legend
  604. \param pos The legend's position. For top/left position the number
  605. of colums will be limited to 1, otherwise it will be set to
  606. unlimited.
  607. \param ratio Ratio between legend and the bounding rect
  608. of title, canvas and axes. The legend will be shrinked
  609. if it would need more space than the given ratio.
  610. The ratio is limited to ]0.0 .. 1.0]. In case of <= 0.0
  611. it will be reset to the default ratio.
  612. The default vertical/horizontal ratio is 0.33/0.5.
  613. \sa legend(), QwtPlotLayout::legendPosition(),
  614. QwtPlotLayout::setLegendPosition()
  615. */
  616. void QwtPlot::insertLegend( QwtLegend *legend,
  617. QwtPlot::LegendPosition pos, double ratio )
  618. {
  619. d_data->layout->setLegendPosition( pos, ratio );
  620. if ( legend != d_data->legend )
  621. {
  622. if ( d_data->legend && d_data->legend->parent() == this )
  623. delete d_data->legend;
  624. d_data->legend = legend;
  625. if ( d_data->legend )
  626. {
  627. if ( pos != ExternalLegend )
  628. {
  629. if ( d_data->legend->parent() != this )
  630. d_data->legend->setParent( this );
  631. }
  632. const QwtPlotItemList& itmList = itemList();
  633. for ( QwtPlotItemIterator it = itmList.begin();
  634. it != itmList.end(); ++it )
  635. {
  636. ( *it )->updateLegend( d_data->legend );
  637. }
  638. QLayout *l = d_data->legend->contentsWidget()->layout();
  639. if ( l && l->inherits( "QwtDynGridLayout" ) )
  640. {
  641. QwtDynGridLayout *tl = ( QwtDynGridLayout * )l;
  642. switch ( d_data->layout->legendPosition() )
  643. {
  644. case LeftLegend:
  645. case RightLegend:
  646. tl->setMaxCols( 1 ); // 1 column: align vertical
  647. break;
  648. case TopLegend:
  649. case BottomLegend:
  650. tl->setMaxCols( 0 ); // unlimited
  651. break;
  652. case ExternalLegend:
  653. break;
  654. }
  655. }
  656. }
  657. updateTabOrder();
  658. }
  659. updateLayout();
  660. }