/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qquicktextarea_p.h"
#include "qquicktextarea_p_p.h"
#include "qquickcontrol_p.h"
#include "qquickcontrol_p_p.h"
#include "qquickscrollview_p.h"
#include "qquickdeferredexecute_p_p.h"

#include <QtQml/qqmlinfo.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickclipnode_p.h>
#include <QtQuick/private/qquickflickable_p.h>

#if QT_CONFIG(accessibility)
#include <QtQuick/private/qquickaccessibleattached_p.h>
#endif

QT_BEGIN_NAMESPACE

/*!
    \qmltype TextArea
    \inherits TextEdit
//!     \instantiates QQuickTextArea
    \inqmlmodule QtQuick.Controls
    \since 5.7
    \ingroup qtquickcontrols2-input
    \brief Multi-line text input area.

    TextArea is a multi-line text editor. TextArea extends TextEdit with
    a \l {placeholderText}{placeholder text} functionality, and adds decoration.

    \image qtquickcontrols2-textarea.png

    \code
    TextArea {
        placeholderText: qsTr("Enter description")
    }
    \endcode

    TextArea is not scrollable by itself. Especially on screen-size constrained
    platforms, it is often preferable to make entire application pages scrollable.
    On such a scrollable page, a non-scrollable TextArea might behave better than
    nested scrollable controls. Notice, however, that in such a scenario, the background
    decoration of the TextArea scrolls together with the rest of the scrollable
    content.

    \section2 Scrollable TextArea

    If you want to make a TextArea scrollable, for example, when it covers
    an entire application page, it can be placed inside a \l ScrollView.

    \image qtquickcontrols2-textarea-scrollable.png

    \snippet qtquickcontrols2-textarea-scrollable.qml 1

    A TextArea that is placed inside a \l ScrollView does the following:

    \list
    \li Sets the content size automatically
    \li Ensures that the background decoration stays in place
    \li Clips the content
    \endlist

    \section2 Tab Focus

    By default, pressing the tab key while TextArea has
    \l {Item::activeFocus}{active focus} results in a tab character being input
    into the control itself. To make tab pass active focus onto another item,
    use the attached \l KeyNavigation properties:

    \code
    TextField {
        id: textField
    }

    TextArea {
        KeyNavigation.priority: KeyNavigation.BeforeItem
        KeyNavigation.tab: textField
    }
    \endcode

    \sa TextField, {Customizing TextArea}, {Input Controls}
*/

/*!
    \qmlsignal QtQuick.Controls::TextArea::pressAndHold(MouseEvent event)

    This signal is emitted when there is a long press (the delay depends on the platform plugin).
    The \a event parameter provides information about the press, including the x and y
    coordinates of the press, and which button is pressed.

    \sa pressed, released
*/

/*!
    \qmlsignal QtQuick.Controls::TextArea::pressed(MouseEvent event)
    \since QtQuick.Controls 2.1 (Qt 5.8)

    This signal is emitted when the text area is pressed by the user.
    The \a event parameter provides information about the press,
    including the x and y coordinates of the press, and which button is pressed.

    \sa released, pressAndHold
*/

/*!
    \qmlsignal QtQuick.Controls::TextArea::released(MouseEvent event)
    \since QtQuick.Controls 2.1 (Qt 5.8)

    This signal is emitted when the text area is released by the user.
    The \a event parameter provides information about the release,
    including the x and y coordinates of the press, and which button
    is pressed.

    \sa pressed, pressAndHold
*/

QQuickTextAreaPrivate::QQuickTextAreaPrivate()
{
#if QT_CONFIG(accessibility)
    QAccessible::installActivationObserver(this);
#endif
}

QQuickTextAreaPrivate::~QQuickTextAreaPrivate()
{
#if QT_CONFIG(accessibility)
    QAccessible::removeActivationObserver(this);
#endif
}

void QQuickTextAreaPrivate::setTopInset(qreal value, bool reset)
{
    Q_Q(QQuickTextArea);
    const QMarginsF oldInset = getInset();
    extra.value().topInset = value;
    extra.value().hasTopInset = !reset;
    if (!qFuzzyCompare(oldInset.top(), value)) {
        emit q->topInsetChanged();
        q->insetChange(getInset(), oldInset);
    }
}

void QQuickTextAreaPrivate::setLeftInset(qreal value, bool reset)
{
    Q_Q(QQuickTextArea);
    const QMarginsF oldInset = getInset();
    extra.value().leftInset = value;
    extra.value().hasLeftInset = !reset;
    if (!qFuzzyCompare(oldInset.left(), value)) {
        emit q->leftInsetChanged();
        q->insetChange(getInset(), oldInset);
    }
}

void QQuickTextAreaPrivate::setRightInset(qreal value, bool reset)
{
    Q_Q(QQuickTextArea);
    const QMarginsF oldInset = getInset();
    extra.value().rightInset = value;
    extra.value().hasRightInset = !reset;
    if (!qFuzzyCompare(oldInset.right(), value)) {
        emit q->rightInsetChanged();
        q->insetChange(getInset(), oldInset);
    }
}

void QQuickTextAreaPrivate::setBottomInset(qreal value, bool reset)
{
    Q_Q(QQuickTextArea);
    const QMarginsF oldInset = getInset();
    extra.value().bottomInset = value;
    extra.value().hasBottomInset = !reset;
    if (!qFuzzyCompare(oldInset.bottom(), value)) {
        emit q->bottomInsetChanged();
        q->insetChange(getInset(), oldInset);
    }
}

void QQuickTextAreaPrivate::resizeBackground()
{
    if (!background)
        return;

    resizingBackground = true;

    // When using the attached property TextArea.flickable, we reparent the background out
    // of TextArea and into the Flickable since we don't want the background to move while
    // flicking. This means that the size of the background should also follow the size of
    // the Flickable rather than the size of the TextArea.
    const auto flickable = qobject_cast<QQuickFlickable *>(background->parentItem());

    QQuickItemPrivate *p = QQuickItemPrivate::get(background);
    if (((!p->widthValid || !extra.isAllocated() || !extra->hasBackgroundWidth) && qFuzzyIsNull(background->x()))
            || (extra.isAllocated() && (extra->hasLeftInset || extra->hasRightInset))) {
        const qreal bgWidth = flickable ? flickable->width() : width;
        background->setX(getLeftInset());
        background->setWidth(bgWidth - getLeftInset() - getRightInset());
    }

    if (((!p->heightValid || !extra.isAllocated() || !extra->hasBackgroundHeight) && qFuzzyIsNull(background->y()))
            || (extra.isAllocated() && (extra->hasTopInset || extra->hasBottomInset))) {
        const qreal bgHeight = flickable ? flickable->height() : height;
        background->setY(getTopInset());
        background->setHeight(bgHeight - getTopInset() - getBottomInset());
    }

    resizingBackground = false;
}

/*!
    \internal

    Determine which font is implicitly imposed on this control by its ancestors
    and QGuiApplication::font, resolve this against its own font (attributes from
    the implicit font are copied over). Then propagate this font to this
    control's children.
*/
void QQuickTextAreaPrivate::resolveFont()
{
    Q_Q(QQuickTextArea);
    inheritFont(QQuickControlPrivate::parentFont(q));
}

void QQuickTextAreaPrivate::inheritFont(const QFont &font)
{
    QFont parentFont = extra.isAllocated() ? extra->requestedFont.resolve(font) : font;
    parentFont.resolve(extra.isAllocated() ? extra->requestedFont.resolve() | font.resolve() : font.resolve());

    const QFont defaultFont = QQuickTheme::font(QQuickTheme::TextArea);
    QFont resolvedFont = parentFont.resolve(defaultFont);
    // See comment in QQuickControlPrivate::inheritFont
    if (defaultFont.families().isEmpty())
        resolvedFont.setFamilies(QStringList());

    setFont_helper(resolvedFont);
}

/*!
    \internal

    Assign \a font to this control, and propagate it to all children.
*/
void QQuickTextAreaPrivate::updateFont(const QFont &font)
{
    Q_Q(QQuickTextArea);
    QFont oldFont = sourceFont;
    q->QQuickTextEdit::setFont(font);

    QQuickControlPrivate::updateFontRecur(q, font);

    if (oldFont != font)
        emit q->fontChanged();
}

/*!
    \internal

    Determine which palette is implicitly imposed on this control by its ancestors
    and QGuiApplication::palette, resolve this against its own palette (attributes from
    the implicit palette are copied over). Then propagate this palette to this
    control's children.
*/
void QQuickTextAreaPrivate::resolvePalette()
{
    Q_Q(QQuickTextArea);
    inheritPalette(QQuickControlPrivate::parentPalette(q));
}

void QQuickTextAreaPrivate::inheritPalette(const QPalette &palette)
{
    QPalette parentPalette = extra.isAllocated() ? extra->requestedPalette.resolve(palette) : palette;
    parentPalette.resolve(extra.isAllocated() ? extra->requestedPalette.resolve() | palette.resolve() : palette.resolve());

    const QPalette defaultPalette = QQuickTheme::palette(QQuickTheme::TextArea);
    const QPalette resolvedPalette = parentPalette.resolve(defaultPalette);

    setPalette_helper(resolvedPalette);
}

void QQuickTextAreaPrivate::updatePalette(const QPalette &palette)
{
    Q_Q(QQuickTextArea);
    QPalette oldPalette = resolvedPalette;
    resolvedPalette = palette;

    QQuickControlPrivate::updatePaletteRecur(q, palette);

    if (oldPalette != palette)
        emit q->paletteChanged();
}

#if QT_CONFIG(quicktemplates2_hover)
void QQuickTextAreaPrivate::updateHoverEnabled(bool enabled, bool xplicit)
{
    Q_Q(QQuickTextArea);
    if (!xplicit && explicitHoverEnabled)
        return;

    bool wasEnabled = q->isHoverEnabled();
    explicitHoverEnabled = xplicit;
    if (wasEnabled != enabled) {
        q->setAcceptHoverEvents(enabled);
        QQuickControlPrivate::updateHoverEnabledRecur(q, enabled);
        emit q->hoverEnabledChanged();
    }
}
#endif

void QQuickTextAreaPrivate::attachFlickable(QQuickFlickable *item)
{
    Q_Q(QQuickTextArea);
    flickable = item;
    q->setParentItem(flickable->contentItem());

    if (background)
        background->setParentItem(flickable);

    QObjectPrivate::connect(q, &QQuickTextArea::contentSizeChanged, this, &QQuickTextAreaPrivate::resizeFlickableContent);
    QObjectPrivate::connect(q, &QQuickTextEdit::cursorRectangleChanged, this, &QQuickTextAreaPrivate::ensureCursorVisible);

    QObject::connect(flickable, &QQuickFlickable::contentXChanged, q, &QQuickItem::update);
    QObject::connect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update);

    QQuickItemPrivate::get(flickable)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size);
    QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);
    QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);

    resizeFlickableControl();
}

void QQuickTextAreaPrivate::detachFlickable()
{
    Q_Q(QQuickTextArea);
    q->setParentItem(nullptr);
    if (background && background->parentItem() == flickable)
        background->setParentItem(q);

    QObjectPrivate::disconnect(q, &QQuickTextArea::contentSizeChanged, this, &QQuickTextAreaPrivate::resizeFlickableContent);
    QObjectPrivate::disconnect(q, &QQuickTextEdit::cursorRectangleChanged, this, &QQuickTextAreaPrivate::ensureCursorVisible);

    QObject::disconnect(flickable, &QQuickFlickable::contentXChanged, q, &QQuickItem::update);
    QObject::disconnect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update);

    QQuickItemPrivate::get(flickable)->updateOrRemoveGeometryChangeListener(this, QQuickGeometryChange::Nothing);
    QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);
    QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl);

    flickable = nullptr;

    resizeBackground();
}

void QQuickTextAreaPrivate::ensureCursorVisible()
{
    Q_Q(QQuickTextArea);
    if (!flickable)
        return;

    const qreal cx = flickable->contentX();
    const qreal cy = flickable->contentY();
    const qreal w = flickable->width();
    const qreal h = flickable->height();

    const qreal tp = q->topPadding();
    const qreal lp = q->leftPadding();
    const QRectF cr = q->cursorRectangle();

    if (cr.left() <= cx + lp) {
        flickable->setContentX(cr.left() - lp);
    } else {
        // calculate the rectangle of the next character and ensure that
        // it's visible if it's on the same line with the cursor
        const qreal rp = q->rightPadding();
        const QRectF nr = q->cursorPosition() < q->length() ? q->positionToRectangle(q->cursorPosition() + 1) : QRectF();
        if (qFuzzyCompare(nr.y(), cr.y()) && nr.right() >= cx + lp + w - rp)
            flickable->setContentX(nr.right() - w + rp);
        else if (cr.right() >= cx + lp + w - rp)
            flickable->setContentX(cr.right() - w + rp);
    }

    if (cr.top() <= cy + tp) {
        flickable->setContentY(cr.top() - tp);
    } else {
        const qreal bp = q->bottomPadding();
        if (cr.bottom() >= cy + tp + h - bp)
            flickable->setContentY(cr.bottom() - h + bp);
    }
}

void QQuickTextAreaPrivate::resizeFlickableControl()
{
    Q_Q(QQuickTextArea);
    if (!flickable)
        return;

    const qreal w = wrapMode == QQuickTextArea::NoWrap ? qMax(flickable->width(), flickable->contentWidth()) : flickable->width();
    const qreal h = qMax(flickable->height(), flickable->contentHeight());
    q->setSize(QSizeF(w, h));

    resizeBackground();
}

void QQuickTextAreaPrivate::resizeFlickableContent()
{
    Q_Q(QQuickTextArea);
    if (!flickable)
        return;

    flickable->setContentWidth(q->contentWidth() + q->leftPadding() + q->rightPadding());
    flickable->setContentHeight(q->contentHeight() + q->topPadding() + q->bottomPadding());
}

void QQuickTextAreaPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
{
    Q_UNUSED(diff);
    if (!resizingBackground && item == background) {
        QQuickItemPrivate *p = QQuickItemPrivate::get(item);
        // Only set hasBackgroundWidth/Height if it was a width/height change,
        // otherwise we're prevented from setting a width/height in the future.
        if (change.widthChange())
            extra.value().hasBackgroundWidth = p->widthValid;
        if (change.heightChange())
            extra.value().hasBackgroundHeight = p->heightValid;
    }

    if (flickable)
        resizeFlickableControl();
    else
        resizeBackground();
}

qreal QQuickTextAreaPrivate::getImplicitWidth() const
{
    return QQuickItemPrivate::getImplicitWidth();
}

qreal QQuickTextAreaPrivate::getImplicitHeight() const
{
    return QQuickItemPrivate::getImplicitHeight();
}

void QQuickTextAreaPrivate::implicitWidthChanged()
{
    Q_Q(QQuickTextArea);
    QQuickItemPrivate::implicitWidthChanged();
    emit q->implicitWidthChanged3();
}

void QQuickTextAreaPrivate::implicitHeightChanged()
{
    Q_Q(QQuickTextArea);
    QQuickItemPrivate::implicitHeightChanged();
    emit q->implicitHeightChanged3();
}

void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly)
{
    Q_UNUSED(isReadOnly);
#if QT_CONFIG(accessibility)
    if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(q_func()))
        accessibleAttached->set_readOnly(isReadOnly);
#endif
#if QT_CONFIG(cursor)
    q_func()->setCursor(isReadOnly ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
}

#if QT_CONFIG(accessibility)
void QQuickTextAreaPrivate::accessibilityActiveChanged(bool active)
{
    if (!active)
        return;

    Q_Q(QQuickTextArea);
    QQuickAccessibleAttached *accessibleAttached = qobject_cast<QQuickAccessibleAttached *>(qmlAttachedPropertiesObject<QQuickAccessibleAttached>(q, true));
    Q_ASSERT(accessibleAttached);
    accessibleAttached->setRole(accessibleRole());
    accessibleAttached->set_readOnly(q->isReadOnly());
    accessibleAttached->setDescription(placeholder);
}

QAccessible::Role QQuickTextAreaPrivate::accessibleRole() const
{
    return QAccessible::EditableText;
}
#endif

static inline QString backgroundName() { return QStringLiteral("background"); }

void QQuickTextAreaPrivate::cancelBackground()
{
    Q_Q(QQuickTextArea);
    quickCancelDeferred(q, backgroundName());
}

void QQuickTextAreaPrivate::executeBackground(bool complete)
{
    Q_Q(QQuickTextArea);
    if (background.wasExecuted())
        return;

    if (!background || complete)
        quickBeginDeferred(q, backgroundName(), background);
    if (complete)
        quickCompleteDeferred(q, backgroundName(), background);
}

void QQuickTextAreaPrivate::itemImplicitWidthChanged(QQuickItem *item)
{
    Q_Q(QQuickTextArea);
    if (item == background)
        emit q->implicitBackgroundWidthChanged();
}

void QQuickTextAreaPrivate::itemImplicitHeightChanged(QQuickItem *item)
{
    Q_Q(QQuickTextArea);
    if (item == background)
        emit q->implicitBackgroundHeightChanged();
}

void QQuickTextAreaPrivate::itemDestroyed(QQuickItem *item)
{
    Q_Q(QQuickTextArea);
    if (item == background) {
        background = nullptr;
        emit q->implicitBackgroundWidthChanged();
        emit q->implicitBackgroundHeightChanged();
    }
}

QQuickTextArea::QQuickTextArea(QQuickItem *parent)
    : QQuickTextEdit(*(new QQuickTextAreaPrivate), parent)
{
    Q_D(QQuickTextArea);
    setActiveFocusOnTab(true);
    setAcceptedMouseButtons(Qt::AllButtons);
    d->setImplicitResizeEnabled(false);
    d->pressHandler.control = this;
#if QT_CONFIG(cursor)
    setCursor(Qt::IBeamCursor);
#endif
    QObjectPrivate::connect(this, &QQuickTextEdit::readOnlyChanged,
                            d, &QQuickTextAreaPrivate::readOnlyChanged);
}

QQuickTextArea::~QQuickTextArea()
{
    Q_D(QQuickTextArea);
    if (d->flickable)
        d->detachFlickable();
    QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
}

QQuickTextAreaAttached *QQuickTextArea::qmlAttachedProperties(QObject *object)
{
    return new QQuickTextAreaAttached(object);
}

QFont QQuickTextArea::font() const
{
    return QQuickTextEdit::font();
}

void QQuickTextArea::setFont(const QFont &font)
{
    Q_D(QQuickTextArea);
    if (d->extra.value().requestedFont.resolve() == font.resolve() && d->extra.value().requestedFont == font)
        return;

    d->extra.value().requestedFont = font;
    d->resolveFont();
}

/*!
    \qmlproperty Item QtQuick.Controls::TextArea::background

    This property holds the background item.

    \input qquickcontrol-background.qdocinc notes

    \sa {Customizing TextArea}
*/
QQuickItem *QQuickTextArea::background() const
{
    QQuickTextAreaPrivate *d = const_cast<QQuickTextAreaPrivate *>(d_func());
    if (!d->background)
        d->executeBackground();
    return d->background;
}

void QQuickTextArea::setBackground(QQuickItem *background)
{
    Q_D(QQuickTextArea);
    if (d->background == background)
        return;

    if (!d->background.isExecuting())
        d->cancelBackground();

    const qreal oldImplicitBackgroundWidth = implicitBackgroundWidth();
    const qreal oldImplicitBackgroundHeight = implicitBackgroundHeight();

    if (d->extra.isAllocated()) {
        d->extra.value().hasBackgroundWidth = false;
        d->extra.value().hasBackgroundHeight = false;
    }

    QQuickControlPrivate::removeImplicitSizeListener(d->background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
    QQuickControlPrivate::hideOldItem(d->background);
    d->background = background;

    if (background) {
        QQuickItemPrivate *p = QQuickItemPrivate::get(background);
        if (p->widthValid || p->heightValid) {
            d->extra.value().hasBackgroundWidth = p->widthValid;
            d->extra.value().hasBackgroundHeight = p->heightValid;
        }
        if (d->flickable)
            background->setParentItem(d->flickable);
        else
            background->setParentItem(this);
        if (qFuzzyIsNull(background->z()))
            background->setZ(-1);
        if (isComponentComplete())
            d->resizeBackground();
        QQuickControlPrivate::addImplicitSizeListener(background, d, QQuickControlPrivate::ImplicitSizeChanges | QQuickItemPrivate::Geometry);
    }

    if (!qFuzzyCompare(oldImplicitBackgroundWidth, implicitBackgroundWidth()))
        emit implicitBackgroundWidthChanged();
    if (!qFuzzyCompare(oldImplicitBackgroundHeight, implicitBackgroundHeight()))
        emit implicitBackgroundHeightChanged();
    if (!d->background.isExecuting())
        emit backgroundChanged();
}

/*!
    \qmlproperty string QtQuick.Controls::TextArea::placeholderText

    This property holds the short hint that is displayed in the text area before
    the user enters a value.
*/
QString QQuickTextArea::placeholderText() const
{
    Q_D(const QQuickTextArea);
    return d->placeholder;
}

void QQuickTextArea::setPlaceholderText(const QString &text)
{
    Q_D(QQuickTextArea);
    if (d->placeholder == text)
        return;

    d->placeholder = text;
#if QT_CONFIG(accessibility)
    if (QQuickAccessibleAttached *accessibleAttached = QQuickControlPrivate::accessibleAttached(this))
        accessibleAttached->setDescription(text);
#endif
    emit placeholderTextChanged();
}

/*!
    \qmlproperty color QtQuick.Controls::TextArea::placeholderTextColor
    \since QtQuick.Controls 2.5 (Qt 5.12)

    This property holds the color of placeholderText.

    \sa placeholderText
*/
QColor QQuickTextArea::placeholderTextColor() const
{
    Q_D(const QQuickTextArea);
    return d->placeholderColor;
}

void QQuickTextArea::setPlaceholderTextColor(const QColor &color)
{
    Q_D(QQuickTextArea);
    if (d->placeholderColor == color)
        return;

    d->placeholderColor = color;
    emit placeholderTextColorChanged();
}

/*!
    \qmlproperty enumeration QtQuick.Controls::TextArea::focusReason

    \include qquickcontrol-focusreason.qdocinc
*/
Qt::FocusReason QQuickTextArea::focusReason() const
{
    Q_D(const QQuickTextArea);
    return d->focusReason;
}

void QQuickTextArea::setFocusReason(Qt::FocusReason reason)
{
    Q_D(QQuickTextArea);
    if (d->focusReason == reason)
        return;

    d->focusReason = reason;
    emit focusReasonChanged();
}

bool QQuickTextArea::contains(const QPointF &point) const
{
    Q_D(const QQuickTextArea);
    if (d->flickable && !d->flickable->contains(d->flickable->mapFromItem(this, point)))
        return false;
    return QQuickTextEdit::contains(point);
}

/*!
    \since QtQuick.Controls 2.1 (Qt 5.8)
    \qmlproperty bool QtQuick.Controls::TextArea::hovered
    \readonly

    This property holds whether the text area is hovered.

    \sa hoverEnabled
*/
bool QQuickTextArea::isHovered() const
{
#if QT_CONFIG(quicktemplates2_hover)
    Q_D(const QQuickTextArea);
    return d->hovered;
#else
    return false;
#endif
}

void QQuickTextArea::setHovered(bool hovered)
{
#if QT_CONFIG(quicktemplates2_hover)
    Q_D(QQuickTextArea);
    if (hovered == d->hovered)
        return;

    d->hovered = hovered;
    emit hoveredChanged();
#else
    Q_UNUSED(hovered);
#endif
}

/*!
    \since QtQuick.Controls 2.1 (Qt 5.8)
    \qmlproperty bool QtQuick.Controls::TextArea::hoverEnabled

    This property determines whether the text area accepts hover events. The default value is \c true.

    \sa hovered
*/
bool QQuickTextArea::isHoverEnabled() const
{
#if QT_CONFIG(quicktemplates2_hover)
    Q_D(const QQuickTextArea);
    return d->hoverEnabled;
#else
    return false;
#endif
}

void QQuickTextArea::setHoverEnabled(bool enabled)
{
#if QT_CONFIG(quicktemplates2_hover)
    Q_D(QQuickTextArea);
    if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
        return;

    d->updateHoverEnabled(enabled, true); // explicit=true
#else
    Q_UNUSED(enabled);
#endif
}

void QQuickTextArea::resetHoverEnabled()
{
#if QT_CONFIG(quicktemplates2_hover)
    Q_D(QQuickTextArea);
    if (!d->explicitHoverEnabled)
        return;

    d->explicitHoverEnabled = false;
    d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
#endif
}

/*!
    \since QtQuick.Controls 2.3 (Qt 5.10)
    \qmlproperty palette QtQuick.Controls::TextArea::palette

    This property holds the palette currently set for the text area.

    \sa Control::palette
*/
QPalette QQuickTextArea::palette() const
{
    Q_D(const QQuickTextArea);
    QPalette palette = d->resolvedPalette;
    if (!isEnabled())
        palette.setCurrentColorGroup(QPalette::Disabled);
    return palette;
}

void QQuickTextArea::setPalette(const QPalette &palette)
{
    Q_D(QQuickTextArea);
    if (d->extra.value().requestedPalette.resolve() == palette.resolve() && d->extra.value().requestedPalette == palette)
        return;

    d->extra.value().requestedPalette = palette;
    d->resolvePalette();
}

void QQuickTextArea::resetPalette()
{
    setPalette(QPalette());
}

/*!
    \since QtQuick.Controls 2.5 (Qt 5.12)
    \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundWidth
    \readonly

    This property holds the implicit background width.

    The value is equal to \c {background ? background.implicitWidth : 0}.

    \sa implicitBackgroundHeight
*/
qreal QQuickTextArea::implicitBackgroundWidth() const
{
    Q_D(const QQuickTextArea);
    if (!d->background)
        return 0;
    return d->background->implicitWidth();
}

/*!
    \since QtQuick.Controls 2.5 (Qt 5.12)
    \qmlproperty real QtQuick.Controls::TextArea::implicitBackgroundHeight
    \readonly

    This property holds the implicit background height.

    The value is equal to \c {background ? background.implicitHeight : 0}.

    \sa implicitBackgroundWidth
*/
qreal QQuickTextArea::implicitBackgroundHeight() const
{
    Q_D(const QQuickTextArea);
    if (!d->background)
        return 0;
    return d->background->implicitHeight();
}

/*!
    \since QtQuick.Controls 2.5 (Qt 5.12)
    \qmlproperty real QtQuick.Controls::TextArea::topInset

    This property holds the top inset for the background.

    \sa {Control Layout}, bottomInset
*/
qreal QQuickTextArea::topInset() const
{
    Q_D(const QQuickTextArea);
    return d->getTopInset();
}

void QQuickTextArea::setTopInset(qreal inset)
{
    Q_D(QQuickTextArea);
    d->setTopInset(inset);
}

void QQuickTextArea::resetTopInset()
{
    Q_D(QQuickTextArea);
    d->setTopInset(0, true);
}

/*!
    \since QtQuick.Controls 2.5 (Qt 5.12)
    \qmlproperty real QtQuick.Controls::TextArea::leftInset

    This property holds the left inset for the background.

    \sa {Control Layout}, rightInset
*/
qreal QQuickTextArea::leftInset() const
{
    Q_D(const QQuickTextArea);
    return d->getLeftInset();
}

void QQuickTextArea::setLeftInset(qreal inset)
{
    Q_D(QQuickTextArea);
    d->setLeftInset(inset);
}

void QQuickTextArea::resetLeftInset()
{
    Q_D(QQuickTextArea);
    d->setLeftInset(0, true);
}

/*!
    \since QtQuick.Controls 2.5 (Qt 5.12)
    \qmlproperty real QtQuick.Controls::TextArea::rightInset

    This property holds the right inset for the background.

    \sa {Control Layout}, leftInset
*/
qreal QQuickTextArea::rightInset() const
{
    Q_D(const QQuickTextArea);
    return d->getRightInset();
}

void QQuickTextArea::setRightInset(qreal inset)
{
    Q_D(QQuickTextArea);
    d->setRightInset(inset);
}

void QQuickTextArea::resetRightInset()
{
    Q_D(QQuickTextArea);
    d->setRightInset(0, true);
}

/*!
    \since QtQuick.Controls 2.5 (Qt 5.12)
    \qmlproperty real QtQuick.Controls::TextArea::bottomInset

    This property holds the bottom inset for the background.

    \sa {Control Layout}, topInset
*/
qreal QQuickTextArea::bottomInset() const
{
    Q_D(const QQuickTextArea);
    return d->getBottomInset();
}

void QQuickTextArea::setBottomInset(qreal inset)
{
    Q_D(QQuickTextArea);
    d->setBottomInset(inset);
}

void QQuickTextArea::resetBottomInset()
{
    Q_D(QQuickTextArea);
    d->setBottomInset(0, true);
}

void QQuickTextArea::classBegin()
{
    Q_D(QQuickTextArea);
    QQuickTextEdit::classBegin();
    d->resolveFont();
    d->resolvePalette();
}

void QQuickTextArea::componentComplete()
{
    Q_D(QQuickTextArea);
    d->executeBackground(true);
    QQuickTextEdit::componentComplete();
    d->resizeBackground();
#if QT_CONFIG(quicktemplates2_hover)
    if (!d->explicitHoverEnabled)
        setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
#endif
#if QT_CONFIG(accessibility)
    if (QAccessible::isActive())
        d->accessibilityActiveChanged(true);
#endif
}

void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
{
    Q_D(QQuickTextArea);
    QQuickTextEdit::itemChange(change, value);
    switch (change) {
    case ItemEnabledHasChanged:
        emit paletteChanged();
        break;
    case ItemSceneChange:
    case ItemParentHasChanged:
        if ((change == ItemParentHasChanged && value.item) || (change == ItemSceneChange && value.window)) {
            d->resolveFont();
            d->resolvePalette();
#if QT_CONFIG(quicktemplates2_hover)
            if (!d->explicitHoverEnabled)
                d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
#endif
            if (change == ItemParentHasChanged) {
                QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(value.item->parentItem());
                if (flickable) {
                    QQuickScrollView *scrollView = qobject_cast<QQuickScrollView *>(flickable->parentItem());
                    if (scrollView)
                        d->attachFlickable(flickable);
                }
            }
        }
        break;
    default:
        break;
    }
}

void QQuickTextArea::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    Q_D(QQuickTextArea);
    QQuickTextEdit::geometryChanged(newGeometry, oldGeometry);
    d->resizeBackground();
}

void QQuickTextArea::insetChange(const QMarginsF &newInset, const QMarginsF &oldInset)
{
    Q_D(QQuickTextArea);
    Q_UNUSED(newInset);
    Q_UNUSED(oldInset);
    d->resizeBackground();
}

QSGNode *QQuickTextArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
    Q_D(QQuickTextArea);
    QQuickDefaultClipNode *clipNode = static_cast<QQuickDefaultClipNode *>(oldNode);
    if (!clipNode)
        clipNode = new QQuickDefaultClipNode(QRectF());

    QQuickItem *clipper = this;
    if (d->flickable)
        clipper = d->flickable;

    const QRectF cr = clipper->clipRect().adjusted(leftPadding(), topPadding(), -rightPadding(), -bottomPadding());
    clipNode->setRect(!d->flickable ? cr : cr.translated(d->flickable->contentX(), d->flickable->contentY()));
    clipNode->update();

    QSGNode *textNode = QQuickTextEdit::updatePaintNode(clipNode->firstChild(), data);
    if (!textNode->parent())
        clipNode->appendChildNode(textNode);

    if (d->cursorItem) {
        QQuickDefaultClipNode *cursorNode = QQuickItemPrivate::get(d->cursorItem)->clipNode();
        if (cursorNode)
            cursorNode->setClipRect(d->cursorItem->mapRectFromItem(clipper, cr));
    }

    return clipNode;
}

void QQuickTextArea::focusInEvent(QFocusEvent *event)
{
    QQuickTextEdit::focusInEvent(event);
    setFocusReason(event->reason());
}

void QQuickTextArea::focusOutEvent(QFocusEvent *event)
{
    QQuickTextEdit::focusOutEvent(event);
    setFocusReason(event->reason());
}

#if QT_CONFIG(quicktemplates2_hover)
void QQuickTextArea::hoverEnterEvent(QHoverEvent *event)
{
    Q_D(QQuickTextArea);
    QQuickTextEdit::hoverEnterEvent(event);
    setHovered(d->hoverEnabled);
    event->setAccepted(d->hoverEnabled);
}

void QQuickTextArea::hoverLeaveEvent(QHoverEvent *event)
{
    Q_D(QQuickTextArea);
    QQuickTextEdit::hoverLeaveEvent(event);
    setHovered(false);
    event->setAccepted(d->hoverEnabled);
}
#endif

void QQuickTextArea::mousePressEvent(QMouseEvent *event)
{
    Q_D(QQuickTextArea);
    d->pressHandler.mousePressEvent(event);
    if (d->pressHandler.isActive()) {
        if (d->pressHandler.delayedMousePressEvent) {
            QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent);
            d->pressHandler.clearDelayedMouseEvent();
        }
        // Calling the base class implementation will result in QQuickTextControl's
        // press handler being called, which ignores events that aren't Qt::LeftButton.
        const bool wasAccepted = event->isAccepted();
        QQuickTextEdit::mousePressEvent(event);
        if (wasAccepted)
            event->accept();
    }
}

void QQuickTextArea::mouseMoveEvent(QMouseEvent *event)
{
    Q_D(QQuickTextArea);
    d->pressHandler.mouseMoveEvent(event);
    if (d->pressHandler.isActive()) {
        if (d->pressHandler.delayedMousePressEvent) {
            QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent);
            d->pressHandler.clearDelayedMouseEvent();
        }
        QQuickTextEdit::mouseMoveEvent(event);
    }
}

void QQuickTextArea::mouseReleaseEvent(QMouseEvent *event)
{
    Q_D(QQuickTextArea);
    d->pressHandler.mouseReleaseEvent(event);
    if (d->pressHandler.isActive()) {
        if (d->pressHandler.delayedMousePressEvent) {
            QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent);
            d->pressHandler.clearDelayedMouseEvent();
        }
        QQuickTextEdit::mouseReleaseEvent(event);
    }
}

void QQuickTextArea::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_D(QQuickTextArea);
    if (d->pressHandler.delayedMousePressEvent) {
        QQuickTextEdit::mousePressEvent(d->pressHandler.delayedMousePressEvent);
        d->pressHandler.clearDelayedMouseEvent();
    }
    QQuickTextEdit::mouseDoubleClickEvent(event);
}

void QQuickTextArea::timerEvent(QTimerEvent *event)
{
    Q_D(QQuickTextArea);
    if (event->timerId() == d->pressHandler.timer.timerId())
        d->pressHandler.timerEvent(event);
    else
        QQuickTextEdit::timerEvent(event);
}

class QQuickTextAreaAttachedPrivate : public QObjectPrivate
{
public:
    QQuickTextArea *control = nullptr;
};

QQuickTextAreaAttached::QQuickTextAreaAttached(QObject *parent)
    : QObject(*(new QQuickTextAreaAttachedPrivate), parent)
{
}

/*!
    \qmlattachedproperty TextArea QtQuick.Controls::TextArea::flickable

    This property attaches a text area to a \l Flickable.

    \sa ScrollBar, ScrollIndicator, {Scrollable TextArea}
*/
QQuickTextArea *QQuickTextAreaAttached::flickable() const
{
    Q_D(const QQuickTextAreaAttached);
    return d->control;
}

void QQuickTextAreaAttached::setFlickable(QQuickTextArea *control)
{
    Q_D(QQuickTextAreaAttached);
    QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(parent());
    if (!flickable) {
        qmlWarning(parent()) << "TextArea must be attached to a Flickable";
        return;
    }

    if (d->control == control)
        return;

    if (d->control)
        QQuickTextAreaPrivate::get(d->control)->detachFlickable();

    d->control = control;

    if (control)
        QQuickTextAreaPrivate::get(control)->attachFlickable(flickable);

    emit flickableChanged();
}

QT_END_NAMESPACE
