From eb525d583868c2c3d819cf6c085acb0b6faf8e19 Mon Sep 17 00:00:00 2001 From: Shun Wang Date: Thu, 5 Sep 2024 23:18:13 +0800 Subject: [PATCH] feat: R syntax highlighter in analysis panel controls (#5538) * init r language highlighter * rename lavaan bound contorls to r lang * add special number case * also enable highlighter for R syntax text area * fix strings format and also styles * add rsyntaxhighlighter quickitem, to make non jasp textareas highlighted easily --- .../JASP/Widgets/ComputeColumnWindow.qml | 7 + .../components/JASP/Widgets/FilterWindow.qml | 11 ++ .../JASP/Widgets/RCommanderWindow.qml | 12 ++ Desktop/mainwindow.cpp | 5 +- .../boundcontrols/boundcontrolcsemtextarea.h | 6 +- ...area.cpp => boundcontrolrlangtextarea.cpp} | 16 +-- ...textarea.h => boundcontrolrlangtextarea.h} | 14 +- .../components/JASP/Controls/Form.qml | 1 + .../controls/lavaansyntaxhighlighter.cpp | 64 --------- .../controls/lavaansyntaxhighlighter.h | 43 ------ QMLComponents/controls/rsyntaxhighlighter.cpp | 123 ++++++++++++++++++ QMLComponents/controls/rsyntaxhighlighter.h | 74 +++++++++++ QMLComponents/controls/textareabase.cpp | 5 +- 13 files changed, 252 insertions(+), 129 deletions(-) rename QMLComponents/boundcontrols/{boundcontrollavaantextarea.cpp => boundcontrolrlangtextarea.cpp} (86%) rename QMLComponents/boundcontrols/{boundcontrollavaantextarea.h => boundcontrolrlangtextarea.h} (78%) delete mode 100644 QMLComponents/controls/lavaansyntaxhighlighter.cpp delete mode 100644 QMLComponents/controls/lavaansyntaxhighlighter.h create mode 100644 QMLComponents/controls/rsyntaxhighlighter.cpp create mode 100644 QMLComponents/controls/rsyntaxhighlighter.h diff --git a/Desktop/components/JASP/Widgets/ComputeColumnWindow.qml b/Desktop/components/JASP/Widgets/ComputeColumnWindow.qml index 5ab87cced6..4f32ffe940 100644 --- a/Desktop/components/JASP/Widgets/ComputeColumnWindow.qml +++ b/Desktop/components/JASP/Widgets/ComputeColumnWindow.qml @@ -2,6 +2,7 @@ import QtQuick 2.7 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.3 import JASP.Controls 1.0 as JaspControls +import JASP import "FilterConstructor" @@ -103,6 +104,12 @@ FocusScope TextArea { id: computeColumnEdit + + RSyntaxHighlighterQuick + { + textDocument: computeColumnEdit.textDocument + } + anchors.top: parent.top anchors.left: parent.left diff --git a/Desktop/components/JASP/Widgets/FilterWindow.qml b/Desktop/components/JASP/Widgets/FilterWindow.qml index f908f3e79b..af2116b8f5 100644 --- a/Desktop/components/JASP/Widgets/FilterWindow.qml +++ b/Desktop/components/JASP/Widgets/FilterWindow.qml @@ -2,6 +2,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import JASP.Controls 1.0 as JaspControls import "FilterConstructor" +import JASP FocusScope { @@ -302,6 +303,11 @@ FocusScope TextArea { + RSyntaxHighlighterQuick + { + textDocument: filterGeneratedEdit.textDocument + } + id: filterGeneratedEdit anchors.top: filterGeneratedBox.top anchors.left: resetAllGeneratedFilters.right @@ -347,6 +353,11 @@ FocusScope TextArea { + RSyntaxHighlighterQuick + { + textDocument: filterEdit.textDocument + } + id: filterEdit height: contentHeight + 30 selectByMouse: true diff --git a/Desktop/components/JASP/Widgets/RCommanderWindow.qml b/Desktop/components/JASP/Widgets/RCommanderWindow.qml index 134b16be52..9d3a051085 100644 --- a/Desktop/components/JASP/Widgets/RCommanderWindow.qml +++ b/Desktop/components/JASP/Widgets/RCommanderWindow.qml @@ -110,6 +110,11 @@ Window TextArea { + RSyntaxHighlighterQuick + { + textDocument: outputWindow.textDocument + } + id: outputWindow text: rCmd.output font: jaspTheme.fontRCode @@ -192,6 +197,13 @@ Window TextArea { + + RSyntaxHighlighterQuick + { + textDocument: codeEntry.textDocument + } + + id: codeEntry font: jaspTheme.fontRCode color: jaspTheme.textEnabled diff --git a/Desktop/mainwindow.cpp b/Desktop/mainwindow.cpp index 391c173a5f..cd3464fc90 100644 --- a/Desktop/mainwindow.cpp +++ b/Desktop/mainwindow.cpp @@ -32,12 +32,11 @@ #include #include "log.h" -#include "dirs.h" #include "timers.h" #include "appinfo.h" #include "tempfiles.h" #include "processinfo.h" -#include "columnutils.h" + #include "mainwindow.h" #include "analysisform.h" @@ -46,6 +45,7 @@ #include "controls/comboboxbase.h" #include "controls/textinputbase.h" #include "controls/componentslistbase.h" +#include "controls/rsyntaxhighlighter.h" #include "controls/factorsformbase.h" #include "controls/inputlistbase.h" #include "controls/textareabase.h" @@ -180,6 +180,7 @@ MainWindow::MainWindow(QApplication * application) : QObject(application), _appl qmlRegisterType ("JASP", 1, 0, "ComboBoxBase" ); qmlRegisterType ("JASP", 1, 0, "RadioButtonBase" ); qmlRegisterType ("JASP", 1, 0, "RadioButtonsGroupBase" ); + qmlRegisterType ("JASP", 1, 0, "RSyntaxHighlighterQuick" ); qmlRegisterType ("JASP", 1, 0, "ComponentsListBase" ); qmlRegisterType ("JASP", 1, 0, "FactorsFormBase" ); qmlRegisterType ("JASP", 1, 0, "InputListBase" ); diff --git a/QMLComponents/boundcontrols/boundcontrolcsemtextarea.h b/QMLComponents/boundcontrols/boundcontrolcsemtextarea.h index 2476702760..1209d3aa2c 100644 --- a/QMLComponents/boundcontrols/boundcontrolcsemtextarea.h +++ b/QMLComponents/boundcontrols/boundcontrolcsemtextarea.h @@ -1,12 +1,12 @@ #ifndef BOUNDCONTROLCSEMTEXTAREA_H #define BOUNDCONTROLCSEMTEXTAREA_H -#include "boundcontrollavaantextarea.h" +#include "boundcontrolrlangtextarea.h" -class BoundControlCSemTextArea : public BoundControlLavaanTextArea +class BoundControlCSemTextArea : public BoundControlRlangTextArea { public: - using BoundControlLavaanTextArea::BoundControlLavaanTextArea; + using BoundControlRlangTextArea::BoundControlRlangTextArea; protected: const char * _checkSyntaxRFunctionName() override { return "jaspSem:::checkCSemModel"; } diff --git a/QMLComponents/boundcontrols/boundcontrollavaantextarea.cpp b/QMLComponents/boundcontrols/boundcontrolrlangtextarea.cpp similarity index 86% rename from QMLComponents/boundcontrols/boundcontrollavaantextarea.cpp rename to QMLComponents/boundcontrols/boundcontrolrlangtextarea.cpp index 4de9bdc5ed..ba8a502b3f 100644 --- a/QMLComponents/boundcontrols/boundcontrollavaantextarea.cpp +++ b/QMLComponents/boundcontrols/boundcontrolrlangtextarea.cpp @@ -16,14 +16,14 @@ // . // -#include "boundcontrollavaantextarea.h" +#include "boundcontrolrlangtextarea.h" #include "controls/textareabase.h" #include "log.h" #include "columnencoder.h" #include "analysisform.h" #include -BoundControlLavaanTextArea::BoundControlLavaanTextArea(TextAreaBase *textArea) +BoundControlRlangTextArea::BoundControlRlangTextArea(TextAreaBase *textArea) : BoundControlTextArea(textArea) { @@ -32,14 +32,14 @@ BoundControlLavaanTextArea::BoundControlLavaanTextArea(TextAreaBase *textArea) if (textDocumentQQuick) { QTextDocument* doc = textDocumentQQuick->textDocument(); - _lavaanHighlighter = new LavaanSyntaxHighlighter(doc); + _rLangHighlighter = new RSyntaxHighlighter(doc); //connect(doc, &QTextDocument::contentsChanged, this, &BoundQMLTextArea::contentsChangedHandler); } else Log::log() << "No document object found!" << std::endl; } -void BoundControlLavaanTextArea::bindTo(const Json::Value &value) +void BoundControlRlangTextArea::bindTo(const Json::Value &value) { if (value.type() != Json::objectValue) return; BoundControlBase::bindTo(value); @@ -50,7 +50,7 @@ void BoundControlLavaanTextArea::bindTo(const Json::Value &value) } -Json::Value BoundControlLavaanTextArea::createJson() const +Json::Value BoundControlRlangTextArea::createJson() const { Json::Value result; std::string text = _textArea->text().toStdString(); @@ -62,7 +62,7 @@ Json::Value BoundControlLavaanTextArea::createJson() const return result; } -bool BoundControlLavaanTextArea::isJsonValid(const Json::Value &value) const +bool BoundControlRlangTextArea::isJsonValid(const Json::Value &value) const { if (!value.isObject()) return false; if (!value["modelOriginal"].isString()) return false; @@ -73,7 +73,7 @@ bool BoundControlLavaanTextArea::isJsonValid(const Json::Value &value) const return true; } -void BoundControlLavaanTextArea::checkSyntax() +void BoundControlRlangTextArea::checkSyntax() { QString text = _textArea->text(); @@ -103,7 +103,7 @@ void BoundControlLavaanTextArea::checkSyntax() } -QString BoundControlLavaanTextArea::rScriptDoneHandler(const QString & result) +QString BoundControlRlangTextArea::rScriptDoneHandler(const QString & result) { if (!result.isEmpty()) return result; diff --git a/QMLComponents/boundcontrols/boundcontrollavaantextarea.h b/QMLComponents/boundcontrols/boundcontrolrlangtextarea.h similarity index 78% rename from QMLComponents/boundcontrols/boundcontrollavaantextarea.h rename to QMLComponents/boundcontrols/boundcontrolrlangtextarea.h index bdcc78e79d..07600b2ffe 100644 --- a/QMLComponents/boundcontrols/boundcontrollavaantextarea.h +++ b/QMLComponents/boundcontrols/boundcontrolrlangtextarea.h @@ -16,16 +16,16 @@ // . // -#ifndef BOUNDCONTROLLAVAANTEXTAREA_H -#define BOUNDCONTROLLAVAANTEXTAREA_H +#ifndef BOUNDCONTROLRLANGTEXTAREA_H +#define BOUNDCONTROLRLANGTEXTAREA_H #include "boundcontroltextarea.h" -#include "controls/lavaansyntaxhighlighter.h" +#include "controls/rsyntaxhighlighter.h" -class BoundControlLavaanTextArea : public BoundControlTextArea +class BoundControlRlangTextArea : public BoundControlTextArea { public: - BoundControlLavaanTextArea(TextAreaBase* textArea); + BoundControlRlangTextArea(TextAreaBase* textArea); bool isJsonValid(const Json::Value& optionValue) const override; Json::Value createJson() const override; @@ -35,7 +35,7 @@ class BoundControlLavaanTextArea : public BoundControlTextArea QString rScriptDoneHandler(const QString &result) override; protected: - LavaanSyntaxHighlighter* _lavaanHighlighter = nullptr; + RSyntaxHighlighter* _rLangHighlighter = nullptr; std::set _usedColumnNames; QString _textEncoded; @@ -43,4 +43,4 @@ class BoundControlLavaanTextArea : public BoundControlTextArea }; -#endif // BOUNDCONTROLLAVAANTEXTAREA_H +#endif // BOUNDCONTROLRLANGTEXTAREA_H diff --git a/QMLComponents/components/JASP/Controls/Form.qml b/QMLComponents/components/JASP/Controls/Form.qml index 36cf1a3b35..4e19f5dd90 100644 --- a/QMLComponents/components/JASP/Controls/Form.qml +++ b/QMLComponents/components/JASP/Controls/Form.qml @@ -240,6 +240,7 @@ AnalysisForm width: parent.width height: visible ? 100 * preferencesModel.uiScale : 0 text: form.rSyntaxText + textType: JASPControl.TextTypeRcode isBound: false onApplyRequest: form.sendRSyntax(text) diff --git a/QMLComponents/controls/lavaansyntaxhighlighter.cpp b/QMLComponents/controls/lavaansyntaxhighlighter.cpp deleted file mode 100644 index cc0424a5f1..0000000000 --- a/QMLComponents/controls/lavaansyntaxhighlighter.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (C) 2013-2018 University of Amsterdam -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public -// License along with this program. If not, see -// . -// - -#include "lavaansyntaxhighlighter.h" - -LavaanSyntaxHighlighter::LavaanSyntaxHighlighter(QTextDocument *parent) - : QSyntaxHighlighter(parent) -{ - - HighlightingRule rule; - - // operators - operatorFormat.setForeground(Qt::darkGreen); - QStringList operatorPatterns; - operatorPatterns << "\\=" << "\\~" << "\\<" - << "\\*" << "\\>" << "\\:" - << "\\%" << "\\|" << "\\+"; - for (const QString &pattern : operatorPatterns) { - rule.pattern = QRegularExpression(pattern); - rule.format = operatorFormat; - highlightingRules.append(rule); - } - - // variables - variableFormat.setToolTip("variable"); - rule.pattern = QRegularExpression("\\b\\w*\\b"); - rule.format = variableFormat; - highlightingRules.append(rule); - - // comments - commentFormat.setForeground(Qt::darkGray); - commentFormat.setFontItalic(true); - rule.pattern = QRegularExpression("#[^\n]*"); - rule.format = commentFormat; - highlightingRules.append(rule); -} - -void LavaanSyntaxHighlighter::highlightBlock(const QString &text) -{ - for (const HighlightingRule &rule : highlightingRules) - { - QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); - while (matchIterator.hasNext()) - { - QRegularExpressionMatch match = matchIterator.next(); - setFormat(match.capturedStart(), match.capturedLength(), rule.format); - } - } -} diff --git a/QMLComponents/controls/lavaansyntaxhighlighter.h b/QMLComponents/controls/lavaansyntaxhighlighter.h deleted file mode 100644 index badfcb1b9e..0000000000 --- a/QMLComponents/controls/lavaansyntaxhighlighter.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (C) 2013-2018 University of Amsterdam -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public -// License along with this program. If not, see -// . -// - -#ifndef LAVAANSYNTAXHIGHLIGHTER_H -#define LAVAANSYNTAXHIGHLIGHTER_H - -#include -#include -#include - -class LavaanSyntaxHighlighter : public QSyntaxHighlighter -{ -public: - LavaanSyntaxHighlighter(QTextDocument *parent); - virtual void highlightBlock(const QString &text) override; -private: - struct HighlightingRule - { - QRegularExpression pattern; - QTextCharFormat format; - }; - QVector highlightingRules; - QTextCharFormat operatorFormat; - QTextCharFormat variableFormat; - QTextCharFormat commentFormat; -}; - -#endif // LAVAANSYNTAXHIGHLIGHTER_H diff --git a/QMLComponents/controls/rsyntaxhighlighter.cpp b/QMLComponents/controls/rsyntaxhighlighter.cpp new file mode 100644 index 0000000000..3b0787e63f --- /dev/null +++ b/QMLComponents/controls/rsyntaxhighlighter.cpp @@ -0,0 +1,123 @@ +// +// Copyright (C) 2013-2018 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with this program. If not, see +// . +// + +#include "rsyntaxhighlighter.h" + +RSyntaxHighlighter::RSyntaxHighlighter(QTextDocument *parent) + : QSyntaxHighlighter(parent) +{ + + HighlightingRule rule; + // all these R regExp are copied from: https://github.com/PrismJS/prism/blob/master/components/prism-r.js + + // operators + operatorFormat.setForeground(Qt::red); + rule.pattern = QRegularExpression(R"(->?>?|<(?:=|=!]=?|::?|&&?|\|\|?|[+*\/^$@~]|%[^%\s]*%)"); + rule.format = operatorFormat; + highlightingRules.append(rule); + + // variables + variableFormat.setToolTip("variable"); + rule.pattern = QRegularExpression(R"(\b\w*\b)"); + rule.format = variableFormat; + highlightingRules.append(rule); + + // string + stringFormat.setForeground(Qt::darkGreen); + rule.pattern = QRegularExpression(R"((['"])(?:\\.|(?!\1)[^\\\r\n])*\1)"); + rule.format = stringFormat; + highlightingRules.append(rule); + + // keyword + keywordFormat.setForeground(Qt::darkCyan); + rule.pattern = QRegularExpression(R"(\b(?:NA|NA_character_|NA_complex_|NA_integer_|NA_real_|NULL|break|else|for|function|if|in|next|repeat|while)\b)"); + rule.format = keywordFormat; + highlightingRules.append(rule); + + // boolean and special number + booleanFormat.setForeground(Qt::magenta); + rule.pattern = QRegularExpression(R"(\b(?:FALSE|TRUE|Inf|NaN)\b)"); + rule.format = booleanFormat; + highlightingRules.append(rule); + + // number + numberFormat.setForeground(Qt::darkMagenta); + rule.pattern = QRegularExpression(R"((?:\b0x[\dA-Fa-f]+(?:\.\d*)?|\b\d+(?:\.\d*)?|\B\.\d+)(?:[EePp][+-]?\d+)?[iL]?)"); + rule.format = numberFormat; + highlightingRules.append(rule); + + // punctuation + punctuationFormat.setForeground(Qt::blue); + rule.pattern = QRegularExpression(R"([(){}\[\],;])"); + rule.format = punctuationFormat; + highlightingRules.append(rule); + + // comments + commentFormat.setForeground(Qt::darkGray); + commentFormat.setFontItalic(true); + rule.pattern = QRegularExpression(R"(#.*)"); + rule.format = commentFormat; + highlightingRules.append(rule); +} + +void RSyntaxHighlighter::highlightBlock(const QString &text) +{ + for (const HighlightingRule &rule : highlightingRules) + { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + + while (matchIterator.hasNext()) + { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + setStringsFormat(text, '"'); + setStringsFormat(text, '\''); + } + } +} + +void RSyntaxHighlighter::setStringsFormat(const QString &text, QChar c) +{ + int start = -1; + for (int i = 0; i < text.size(); ++i) + { + if (text[i] == c && (i == 0 || text[i - 1] != '\\')) + { + if (start == -1) + start = i; + else + { + setFormat(start, i - start + 1, stringFormat); + start = -1; + } + } + } +} + +void RSyntaxHighlighterQuick::setTextDocument(QQuickTextDocument *textDocument) +{ + if(_textDocument == textDocument) + return; + + _textDocument = textDocument; + + if(_textDocument) + _highlighter = new RSyntaxHighlighter(_textDocument->textDocument()); + + emit textDocumentChanged(); +} diff --git a/QMLComponents/controls/rsyntaxhighlighter.h b/QMLComponents/controls/rsyntaxhighlighter.h new file mode 100644 index 0000000000..19236f46d7 --- /dev/null +++ b/QMLComponents/controls/rsyntaxhighlighter.h @@ -0,0 +1,74 @@ +// +// Copyright (C) 2013-2018 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with this program. If not, see +// . +// + +#ifndef RLANGSYNTAXHIGHLIGHTER_H +#define RLANGSYNTAXHIGHLIGHTER_H + +#include +#include +#include +#include +#include + +class RSyntaxHighlighter : public QSyntaxHighlighter +{ +public: + RSyntaxHighlighter(QTextDocument *parent); + + void highlightBlock(const QString &text) override; + void setStringsFormat(const QString &text, QChar c); + +private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + + QVector highlightingRules; + QTextCharFormat operatorFormat, + variableFormat, + commentFormat, + keywordFormat, + stringFormat, + booleanFormat, + numberFormat, + punctuationFormat; +}; + +class RSyntaxHighlighterQuick : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QQuickTextDocument* textDocument READ textDocument WRITE setTextDocument NOTIFY textDocumentChanged) + +public: + RSyntaxHighlighterQuick(QQuickItem * parent = nullptr) : QQuickItem(parent) {} + + QQuickTextDocument * textDocument() { return _textDocument; } + + void setTextDocument(QQuickTextDocument * textDocument); + +signals: + void textDocumentChanged(); + +private: + RSyntaxHighlighter * _highlighter = nullptr; + QQuickTextDocument * _textDocument = nullptr; +}; + +#endif // RLANGSYNTAXHIGHLIGHTER_H diff --git a/QMLComponents/controls/textareabase.cpp b/QMLComponents/controls/textareabase.cpp index 3394c08ae5..8c43f69b55 100644 --- a/QMLComponents/controls/textareabase.cpp +++ b/QMLComponents/controls/textareabase.cpp @@ -20,7 +20,7 @@ #include "analysisform.h" #include "boundcontrols/boundcontrolsourcetextarea.h" #include "boundcontrols/boundcontroljagstextarea.h" -#include "boundcontrols/boundcontrollavaantextarea.h" +#include "boundcontrols/boundcontrolrlangtextarea.h" #include "boundcontrols/boundcontrolcsemtextarea.h" @@ -53,7 +53,8 @@ void TextAreaBase::setUp() switch (_textType) { case TextType::TextTypeSource: _boundControl = new BoundControlSourceTextArea(this); break; - case TextType::TextTypeLavaan: _boundControl = new BoundControlLavaanTextArea(this); break; + case TextType::TextTypeLavaan: _boundControl = new BoundControlRlangTextArea(this); break; + case TextType::TextTypeRcode: _boundControl = new BoundControlRlangTextArea(this); break; case TextType::TextTypeJAGSmodel: _boundControl = new BoundControlJAGSTextArea(this); break; case TextType::TextTypeCSem: _boundControl = new BoundControlCSemTextArea(this); break; default: _boundControl = new BoundControlTextArea(this); break;