1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2020 Uwe Kindler 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of Qt Creator. 7 ** 8 ** Commercial License Usage 9 ** Licensees holding valid commercial Qt licenses may use this file in 10 ** accordance with the commercial license agreement provided with the 11 ** Software or, alternatively, in accordance with the terms contained in 12 ** a written agreement between you and The Qt Company. For licensing terms 13 ** and conditions see https://www.qt.io/terms-conditions. For further 14 ** information use the contact form at https://www.qt.io/contact-us. 15 ** 16 ** GNU Lesser General Public License Usage 17 ** Alternatively, this file may be used under the terms of the GNU Lesser 18 ** General Public License version 2.1 or (at your option) any later version. 19 ** The licenses are as published by the Free Software Foundation 20 ** and appearing in the file LICENSE.LGPLv21 included in the packaging 21 ** of this file. Please review the following information to ensure 22 ** the GNU Lesser General Public License version 2.1 requirements 23 ** will be met: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 3 or (at your option) any later version 28 ** approved by the KDE Free Qt Foundation. The licenses are as published by 29 ** the Free Software Foundation and appearing in the file LICENSE.GPL3 30 ** included in the packaging of this file. Please review the following 31 ** information to ensure the GNU General Public License requirements will 32 ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 33 ** 34 ****************************************************************************/ 35 36 #include "dockwidgettab.h" 37 38 #include "ads_globals.h" 39 #include "dockareawidget.h" 40 #include "dockmanager.h" 41 #include "dockoverlay.h" 42 #include "dockwidget.h" 43 #include "elidinglabel.h" 44 #include "floatingdockcontainer.h" 45 #include "floatingdragpreview.h" 46 #include "iconprovider.h" 47 48 #include <utils/theme/theme.h> 49 50 #include <QApplication> 51 #include <QBoxLayout> 52 #include <QLabel> 53 #include <QLoggingCategory> 54 #include <QMenu> 55 #include <QMouseEvent> 56 #include <QPushButton> 57 #include <QSplitter> 58 #include <QStyle> 59 #include <QStyleOption> 60 #include <QToolButton> 61 #include <QPainter> 62 #include <QStylePainter> 63 64 #include <iostream> 65 66 static Q_LOGGING_CATEGORY(adsLog, "qtc.qmldesigner.advanceddockingsystem", QtWarningMsg) 67 68 namespace ADS 69 { 70 using TabLabelType = ElidingLabel; 71 72 /** 73 * Private data class of DockWidgetTab class (pimpl) 74 */ 75 class DockWidgetTabPrivate 76 { 77 public: 78 DockWidgetTab *q; 79 DockWidget *m_dockWidget = nullptr; 80 QLabel *m_iconLabel = nullptr; 81 TabLabelType *m_titleLabel = nullptr; 82 QPoint m_globalDragStartMousePosition; 83 QPoint m_dragStartMousePosition; 84 bool m_isActiveTab = false; 85 DockAreaWidget *m_dockArea = nullptr; 86 eDragState m_dragState = DraggingInactive; 87 AbstractFloatingWidget *m_floatingWidget = nullptr; 88 QIcon m_icon; 89 TabButton *m_closeButton = nullptr; 90 QPoint m_tabDragStartPosition; 91 92 /** 93 * Private data constructor 94 */ 95 DockWidgetTabPrivate(DockWidgetTab *parent); 96 97 /** 98 * Creates the complete layout including all controls 99 */ 100 void createLayout(); 101 102 /** 103 * Moves the tab depending on the position in the given mouse event 104 */ 105 void moveTab(QMouseEvent *event); 106 107 /** 108 * Test function for current drag state 109 */ isDraggingState(eDragState dragState) const110 bool isDraggingState(eDragState dragState) const { return this->m_dragState == dragState; } 111 112 /** 113 * Starts floating of the dock widget that belongs to this title bar 114 * Returns true, if floating has been started and false if floating 115 * is not possible for any reason 116 */ 117 bool startFloating(eDragState draggingState = DraggingFloatingWidget); 118 119 /** 120 * Returns true if the given config flag is set 121 */ testConfigFlag(DockManager::eConfigFlag flag) const122 bool testConfigFlag(DockManager::eConfigFlag flag) const 123 { 124 return DockManager::testConfigFlag(flag); 125 } 126 127 /** 128 * Creates the close button as QPushButton or as QToolButton 129 */ createCloseButton() const130 TabButton *createCloseButton() const 131 { 132 /* 133 if (testConfigFlag(DockManager::TabCloseButtonIsToolButton)) { 134 auto button = new QToolButton(); 135 button->setAutoRaise(true); 136 return button; 137 } else { 138 return new QPushButton(); 139 } 140 */ 141 return new TabButton(); 142 } 143 144 template<typename T> createFloatingWidget(T * widget,bool opaqueUndocking)145 AbstractFloatingWidget *createFloatingWidget(T *widget, bool opaqueUndocking) 146 { 147 if (opaqueUndocking) { 148 return new FloatingDockContainer(widget); 149 } else { 150 auto w = new FloatingDragPreview(widget); 151 QObject::connect(w, &FloatingDragPreview::draggingCanceled, q, [=]() { 152 m_dragState = DraggingInactive; 153 }); 154 return w; 155 } 156 } 157 158 /** 159 * Saves the drag start position in global and local coordinates 160 */ saveDragStartMousePosition(const QPoint & globalPos)161 void saveDragStartMousePosition(const QPoint &globalPos) 162 { 163 m_globalDragStartMousePosition = globalPos; 164 m_dragStartMousePosition = q->mapFromGlobal(globalPos); 165 } 166 }; // class DockWidgetTabPrivate 167 DockWidgetTabPrivate(DockWidgetTab * parent)168 DockWidgetTabPrivate::DockWidgetTabPrivate(DockWidgetTab *parent) 169 : q(parent) 170 {} 171 createLayout()172 void DockWidgetTabPrivate::createLayout() 173 { 174 m_titleLabel = new TabLabelType(); 175 m_titleLabel->setElideMode(Qt::ElideRight); 176 m_titleLabel->setText(m_dockWidget->windowTitle()); 177 m_titleLabel->setObjectName("dockWidgetTabLabel"); 178 m_titleLabel->setAlignment(Qt::AlignCenter); 179 QObject::connect(m_titleLabel, 180 &ElidingLabel::elidedChanged, 181 q, 182 &DockWidgetTab::elidedChanged); 183 184 m_closeButton = createCloseButton(); 185 m_closeButton->setObjectName("tabCloseButton"); 186 internal::setButtonIcon(m_closeButton, 187 QStyle::SP_TitleBarCloseButton, 188 TabCloseIcon); 189 m_closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); 190 m_closeButton->setIconSize(QSize(11, 11)); 191 m_closeButton->setFixedSize(QSize(17, 17)); 192 q->onDockWidgetFeaturesChanged(); 193 internal::setToolTip(m_closeButton, QObject::tr("Close Tab")); 194 QObject::connect(m_closeButton, 195 &QAbstractButton::clicked, 196 q, 197 &DockWidgetTab::closeRequested); 198 199 QFontMetrics fontMetrics(m_titleLabel->font()); 200 int spacing = qRound(fontMetrics.height() / 4.0); 201 202 // Fill the layout 203 QBoxLayout *boxLayout = new QBoxLayout(QBoxLayout::LeftToRight); 204 boxLayout->setContentsMargins(2 * spacing, 0, 0, 0); 205 boxLayout->setSpacing(0); 206 q->setLayout(boxLayout); 207 boxLayout->addWidget(m_titleLabel, 1, Qt::AlignVCenter); 208 boxLayout->addSpacing(qRound(spacing * 4.0 / 3.0)); 209 boxLayout->addWidget(m_closeButton, 0, Qt::AlignVCenter); 210 boxLayout->addSpacing(1); 211 boxLayout->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); 212 213 if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) 214 m_closeButton->setCheckable(true); 215 216 m_titleLabel->setVisible(true); 217 } 218 moveTab(QMouseEvent * event)219 void DockWidgetTabPrivate::moveTab(QMouseEvent *event) 220 { 221 event->accept(); 222 QPoint distance = event->globalPos() - m_globalDragStartMousePosition; 223 distance.setY(0); 224 auto targetPos = distance + m_tabDragStartPosition; 225 targetPos.rx() = qMax(targetPos.x(), 0); 226 targetPos.rx() = qMin(q->parentWidget()->rect().right() - q->width() + 1, targetPos.rx()); 227 q->move(targetPos); 228 q->raise(); 229 } 230 startFloating(eDragState draggingState)231 bool DockWidgetTabPrivate::startFloating(eDragState draggingState) 232 { 233 auto dockContainer = m_dockWidget->dockContainer(); 234 qCInfo(adsLog) << "isFloating " << dockContainer->isFloating(); 235 qCInfo(adsLog) << "areaCount " << dockContainer->dockAreaCount(); 236 qCInfo(adsLog) << "widgetCount " << m_dockWidget->dockAreaWidget()->dockWidgetsCount(); 237 // if this is the last dock widget inside of this floating widget, 238 // then it does not make any sense, to make it floating because 239 // it is already floating 240 if (dockContainer->isFloating() && (dockContainer->visibleDockAreaCount() == 1) 241 && (m_dockWidget->dockAreaWidget()->dockWidgetsCount() == 1)) { 242 return false; 243 } 244 245 qCInfo(adsLog) << "startFloating"; 246 m_dragState = draggingState; 247 AbstractFloatingWidget *floatingWidget = nullptr; 248 bool opaqueUndocking = DockManager::testConfigFlag(DockManager::OpaqueUndocking) 249 || (DraggingFloatingWidget != draggingState); 250 251 // If section widget has multiple tabs, we take only one tab 252 // If it has only one single tab, we can move the complete 253 // dock area into floating widget 254 QSize size; 255 if (m_dockArea->dockWidgetsCount() > 1) { 256 floatingWidget = createFloatingWidget(m_dockWidget, opaqueUndocking); 257 size = m_dockWidget->size(); 258 } else { 259 floatingWidget = createFloatingWidget(m_dockArea, opaqueUndocking); 260 size = m_dockArea->size(); 261 } 262 263 if (DraggingFloatingWidget == draggingState) { 264 floatingWidget->startFloating(m_dragStartMousePosition, size, DraggingFloatingWidget, q); 265 auto Overlay = m_dockWidget->dockManager()->containerOverlay(); 266 Overlay->setAllowedAreas(OuterDockAreas); 267 this->m_floatingWidget = floatingWidget; 268 } else { 269 floatingWidget->startFloating(m_dragStartMousePosition, size, DraggingInactive, nullptr); 270 } 271 272 return true; 273 } 274 275 TabButton(QWidget * parent)276 TabButton::TabButton(QWidget *parent) 277 : TabButtonType(parent) 278 , m_active(false) 279 , m_focus(false) 280 {} 281 setActive(bool value)282 void TabButton::setActive(bool value) { m_active = value; } setFocus(bool value)283 void TabButton::setFocus(bool value) { m_focus = value; } 284 paintEvent(QPaintEvent * event)285 void TabButton::paintEvent(QPaintEvent *event) 286 { 287 Q_UNUSED(event) 288 289 QStylePainter p(this); 290 QStyleOptionToolButton opt; 291 initStyleOption(&opt); 292 opt.icon = QIcon(); // set to null icon otherwise it is drawn twice 293 p.drawComplexControl(QStyle::CC_ToolButton, opt); 294 295 QIcon::Mode mode = QIcon::Mode::Normal; 296 if (m_active) 297 mode = QIcon::Mode::Active; 298 if (m_focus) 299 mode = QIcon::Mode::Selected; 300 301 const QPoint iconPosition = rect().center() - QPoint(iconSize().width() * 0.5, 302 iconSize().height() * 0.5); 303 304 p.drawPixmap(iconPosition, icon().pixmap(iconSize(), mode)); 305 } 306 307 DockWidgetTab(DockWidget * dockWidget,QWidget * parent)308 DockWidgetTab::DockWidgetTab(DockWidget *dockWidget, QWidget *parent) 309 : QFrame(parent) 310 , d(new DockWidgetTabPrivate(this)) 311 { 312 setAttribute(Qt::WA_NoMousePropagation, true); 313 d->m_dockWidget = dockWidget; 314 d->createLayout(); 315 if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) 316 setFocusPolicy(Qt::ClickFocus); 317 } 318 ~DockWidgetTab()319 DockWidgetTab::~DockWidgetTab() 320 { 321 qCInfo(adsLog) << Q_FUNC_INFO; 322 delete d; 323 } 324 mousePressEvent(QMouseEvent * event)325 void DockWidgetTab::mousePressEvent(QMouseEvent *event) 326 { 327 if (event->button() == Qt::LeftButton) { 328 event->accept(); 329 d->saveDragStartMousePosition(event->globalPos()); 330 d->m_dragState = DraggingMousePressed; 331 emit clicked(); 332 return; 333 } 334 Super::mousePressEvent(event); 335 } 336 mouseReleaseEvent(QMouseEvent * event)337 void DockWidgetTab::mouseReleaseEvent(QMouseEvent *event) 338 { 339 if (event->button() == Qt::LeftButton) { 340 auto currentDragState = d->m_dragState; 341 d->m_globalDragStartMousePosition = QPoint(); 342 d->m_dragStartMousePosition = QPoint(); 343 d->m_dragState = DraggingInactive; 344 345 switch (currentDragState) { 346 case DraggingTab: 347 // End of tab moving, emit signal 348 if (d->m_dockArea) { 349 emit moved(event->globalPos()); 350 } 351 break; 352 353 case DraggingFloatingWidget: 354 d->m_floatingWidget->finishDragging(); 355 break; 356 357 default:; // do nothing 358 } 359 } 360 361 Super::mouseReleaseEvent(event); 362 } 363 mouseMoveEvent(QMouseEvent * event)364 void DockWidgetTab::mouseMoveEvent(QMouseEvent *event) 365 { 366 if (!(event->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) { 367 d->m_dragState = DraggingInactive; 368 Super::mouseMoveEvent(event); 369 return; 370 } 371 372 // move floating window 373 if (d->isDraggingState(DraggingFloatingWidget)) { 374 d->m_floatingWidget->moveFloating(); 375 Super::mouseMoveEvent(event); 376 return; 377 } 378 379 // move tab 380 if (d->isDraggingState(DraggingTab)) { 381 // Moving the tab is always allowed because it does not mean moving the 382 // dock widget around 383 d->moveTab(event); 384 } 385 386 auto mappedPos = mapToParent(event->pos()); 387 bool mouseOutsideBar = (mappedPos.x() < 0) || (mappedPos.x() > parentWidget()->rect().right()); 388 // Maybe a fixed drag distance is better here ? 389 int dragDistanceY = qAbs(d->m_globalDragStartMousePosition.y() - event->globalPos().y()); 390 if (dragDistanceY >= DockManager::startDragDistance() || mouseOutsideBar) { 391 // If this is the last dock area in a dock container with only 392 // one single dock widget it does not make sense to move it to a new 393 // floating widget and leave this one empty 394 if (d->m_dockArea->dockContainer()->isFloating() 395 && d->m_dockArea->openDockWidgetsCount() == 1 396 && d->m_dockArea->dockContainer()->visibleDockAreaCount() == 1) { 397 return; 398 } 399 400 // Floating is only allowed for widgets that are floatable 401 // If we do non opaque undocking, then can create the drag preview 402 // if the widget is movable. 403 auto features = d->m_dockWidget->features(); 404 if (features.testFlag(DockWidget::DockWidgetFloatable) 405 || (features.testFlag(DockWidget::DockWidgetMovable) 406 && !DockManager::testConfigFlag(DockManager::OpaqueUndocking))) { 407 // If we undock, we need to restore the initial position of this 408 // tab because it looks strange if it remains on its dragged position 409 if (d->isDraggingState(DraggingTab) 410 && !DockManager::testConfigFlag(DockManager::OpaqueUndocking)) 411 parentWidget()->layout()->update(); 412 413 d->startFloating(); 414 } 415 return; 416 } else if (d->m_dockArea->openDockWidgetsCount() > 1 417 && (event->globalPos() - d->m_globalDragStartMousePosition).manhattanLength() 418 >= QApplication::startDragDistance()) // Wait a few pixels before start moving 419 { 420 // If we start dragging the tab, we save its initial position to 421 // restore it later 422 if (DraggingTab != d->m_dragState) 423 d->m_tabDragStartPosition = this->pos(); 424 425 d->m_dragState = DraggingTab; 426 return; 427 } 428 429 Super::mouseMoveEvent(event); 430 } 431 contextMenuEvent(QContextMenuEvent * event)432 void DockWidgetTab::contextMenuEvent(QContextMenuEvent *event) 433 { 434 event->accept(); 435 if (d->isDraggingState(DraggingFloatingWidget)) 436 return; 437 438 d->saveDragStartMousePosition(event->globalPos()); 439 QMenu menu(this); 440 441 const bool isFloatable = d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable); 442 const bool isNotOnlyTabInContainer = !d->m_dockArea->dockContainer()->hasTopLevelDockWidget(); 443 const bool isDetachable = isFloatable && isNotOnlyTabInContainer; 444 445 auto action = menu.addAction(tr("Detach"), this, &DockWidgetTab::detachDockWidget); 446 action->setEnabled(isDetachable); 447 menu.addSeparator(); 448 action = menu.addAction(tr("Close"), this, &DockWidgetTab::closeRequested); 449 action->setEnabled(isClosable()); 450 menu.addAction(tr("Close Others"), this, &DockWidgetTab::closeOtherTabsRequested); 451 menu.exec(event->globalPos()); 452 } 453 isActiveTab() const454 bool DockWidgetTab::isActiveTab() const { return d->m_isActiveTab; } 455 setActiveTab(bool active)456 void DockWidgetTab::setActiveTab(bool active) 457 { 458 bool dockWidgetClosable = d->m_dockWidget->features().testFlag( 459 DockWidget::DockWidgetClosable); 460 bool activeTabHasCloseButton = d->testConfigFlag(DockManager::ActiveTabHasCloseButton); 461 bool allTabsHaveCloseButton = d->testConfigFlag(DockManager::AllTabsHaveCloseButton); 462 bool tabHasCloseButton = (activeTabHasCloseButton && active) | allTabsHaveCloseButton; 463 d->m_closeButton->setVisible(dockWidgetClosable && tabHasCloseButton); 464 465 d->m_closeButton->setActive(active); 466 467 // Focus related stuff 468 if (DockManager::testConfigFlag(DockManager::FocusHighlighting) 469 && !d->m_dockWidget->dockManager()->isRestoringState()) { 470 bool updateFocusStyle = false; 471 if (active && !hasFocus()) { 472 setFocus(Qt::OtherFocusReason); 473 updateFocusStyle = true; 474 } 475 if (d->m_isActiveTab == active) { 476 if (updateFocusStyle) 477 updateStyle(); 478 return; 479 } 480 } else if (d->m_isActiveTab == active) { 481 return; 482 } 483 484 d->m_isActiveTab = active; 485 updateStyle(); 486 update(); 487 updateGeometry(); 488 489 emit activeTabChanged(); 490 } 491 dockWidget() const492 DockWidget *DockWidgetTab::dockWidget() const { return d->m_dockWidget; } 493 setDockAreaWidget(DockAreaWidget * dockArea)494 void DockWidgetTab::setDockAreaWidget(DockAreaWidget *dockArea) { d->m_dockArea = dockArea; } 495 dockAreaWidget() const496 DockAreaWidget *DockWidgetTab::dockAreaWidget() const { return d->m_dockArea; } 497 setIcon(const QIcon & icon)498 void DockWidgetTab::setIcon(const QIcon &icon) 499 { 500 QBoxLayout *boxLayout = qobject_cast<QBoxLayout *>(layout()); 501 if (!d->m_iconLabel && icon.isNull()) 502 return; 503 504 if (!d->m_iconLabel) { 505 d->m_iconLabel = new QLabel(); 506 d->m_iconLabel->setAlignment(Qt::AlignVCenter); 507 d->m_iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); 508 internal::setToolTip(d->m_iconLabel, d->m_titleLabel->toolTip()); 509 boxLayout->insertWidget(0, d->m_iconLabel, Qt::AlignVCenter); 510 boxLayout->insertSpacing(1, qRound(1.5 * boxLayout->contentsMargins().left() / 2.0)); 511 } else if (icon.isNull()) { 512 // Remove icon label and spacer item 513 boxLayout->removeWidget(d->m_iconLabel); 514 boxLayout->removeItem(boxLayout->itemAt(0)); 515 delete d->m_iconLabel; 516 d->m_iconLabel = nullptr; 517 } 518 519 d->m_icon = icon; 520 if (d->m_iconLabel) { 521 d->m_iconLabel->setPixmap( 522 icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this))); 523 d->m_iconLabel->setVisible(true); 524 } 525 } 526 icon() const527 const QIcon &DockWidgetTab::icon() const { return d->m_icon; } 528 text() const529 QString DockWidgetTab::text() const { return d->m_titleLabel->text(); } 530 mouseDoubleClickEvent(QMouseEvent * event)531 void DockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event) 532 { 533 // If this is the last dock area in a dock container it does not make 534 // sense to move it to a new floating widget and leave this one empty 535 if ((!d->m_dockArea->dockContainer()->isFloating() || d->m_dockArea->dockWidgetsCount() > 1) 536 && d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable)) { 537 d->saveDragStartMousePosition(event->globalPos()); 538 d->startFloating(DraggingInactive); 539 } 540 541 Super::mouseDoubleClickEvent(event); 542 } 543 setVisible(bool visible)544 void DockWidgetTab::setVisible(bool visible) 545 { 546 // Just here for debugging to insert debug output 547 Super::setVisible(visible); 548 } 549 setText(const QString & title)550 void DockWidgetTab::setText(const QString &title) { d->m_titleLabel->setText(title); } isTitleElided() const551 bool DockWidgetTab::isTitleElided() const { return d->m_titleLabel->isElided(); } 552 isClosable() const553 bool DockWidgetTab::isClosable() const 554 { 555 return d->m_dockWidget 556 && d->m_dockWidget->features().testFlag(DockWidget::DockWidgetClosable); 557 } 558 detachDockWidget()559 void DockWidgetTab::detachDockWidget() 560 { 561 if (!d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable)) 562 return; 563 564 d->saveDragStartMousePosition(QCursor::pos()); 565 d->startFloating(DraggingInactive); 566 } 567 event(QEvent * event)568 bool DockWidgetTab::event(QEvent *event) 569 { 570 #ifndef QT_NO_TOOLTIP 571 if (event->type() == QEvent::ToolTipChange) { 572 const auto text = toolTip(); 573 d->m_titleLabel->setToolTip(text); 574 } 575 #endif 576 577 return Super::event(event); 578 } 579 onDockWidgetFeaturesChanged()580 void DockWidgetTab::onDockWidgetFeaturesChanged() 581 { 582 auto features = d->m_dockWidget->features(); 583 auto sizePolicy = d->m_closeButton->sizePolicy(); 584 sizePolicy.setRetainSizeWhenHidden( 585 features.testFlag(DockWidget::DockWidgetClosable) 586 && d->testConfigFlag(DockManager::RetainTabSizeWhenCloseButtonHidden)); 587 d->m_closeButton->setSizePolicy(sizePolicy); 588 } 589 setElideMode(Qt::TextElideMode mode)590 void DockWidgetTab::setElideMode(Qt::TextElideMode mode) 591 { 592 d->m_titleLabel->setElideMode(mode); 593 } 594 updateStyle()595 void DockWidgetTab::updateStyle() 596 { 597 if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) 598 d->m_closeButton->setFocus(property("focused").toBool()); 599 600 internal::repolishStyle(this, internal::RepolishDirectChildren); 601 } 602 603 } // namespace ADS 604