Использование ACE с WT

ОБНОВЛЕНИЕ 3 Окончательный рабочий код ниже. ВАМ НУЖЕН ace.js ОТ Src FOLDER! Он не будет работать с libs, вам нужна предварительно упакованная версия с их сайта.

WText *editor = new WText(root());
editor->setText("function(){\n hello.abc();\n}\n");
editor->setInline(false);

Приведенный выше код может установить содержимое окна ACE.

MyClass::MyClass(const WEnvironment& env)
: WApplication(env)
{
wApp->require("ace-builds/src/ace.js");
// A WContainerWidget is rendered as a div
WContainerWidget *editor = new WContainerWidget(root());
editor->resize(500, 500);

std::string editor_ref = editor->jsRef(); // is a text string that will be the element when executed in JS

std::string command = 
  editor_ref + ".editor = ace.edit(" + editor_ref + ");" +
  editor_ref + ".editor.setTheme(\"ace/theme/monokai\");" +
  editor_ref + ".editor.getSession().setMode(\"ace/mode/javascript\");";

editor->doJavaScript(command);


JSignal <std::string> *jsignal = new JSignal<std::string>(editor, "textChanged");
jsignal->connect(this, &MyClass::textChanged);

WPushButton *b = new WPushButton("Save", root());

command = "function(object, event) {" +
  jsignal->createCall(editor_ref + ".editor.getValue()") +
  ";}";

b->clicked().connect(command);
}

void MyClass::textChanged(std::string incoming)
{

}

ОБНОВЛЕНИЕ 2 Вот как выглядит мой проект АТМ, все еще получая белый экран с красным сообщением "Загрузка..." от WT в верхнем правом углу. Больше примечаний ниже.

MyClass::MyClass(const WEnvironment& env)
: WApplication(env)
{
wApp->require("lib/ace/ace.js");
// A WContainerWidget is rendered as a div
WContainerWidget *editor = new WContainerWidget(root());
editor->resize(500, 500);

std::string editor_ref = editor->jsRef(); // is a text string that will be the element when executed in JS

std::string command = 
  editor_ref + ".editor = ace.edit(" + editor_ref + ");" +
  editor_ref + ".editor.setTheme(\"ace/theme/monokai\");" +
  editor_ref + ".editor.getSession().setMode(\"ace/mode/javascript\");";

editor->doJavaScript(command);


JSignal <std::string> *jsignal = new JSignal<std::string>(editor, "textChanged");
jsignal->connect(this, &MyClass::textChanged);

WPushButton *b = new WPushButton("Save", root());

command = "function(object, event) {" +
  jsignal->createCall(editor_ref + ".editor.getValue()") +
  ";}";

b->clicked().connect(command);
}

void MyClass::textChanged(std::string incoming)
{

}

Переменная "command" равна следующей, если она используется для editor->doJavaScript(команда)

"Wt3_3_0.$('oy4ycjy').editor = ace.edit(Wt3_3_0.$('oy4ycjy'));Wt3_3_0.$('oy4ycjy').editor.setTheme('ace/theme/monokai');Wt3_3_0.$('oy4ycjy').editor.getSession().setMode('ace/mode/javascript');"

Переменная "command" равна следующей, если она используется для b->clicked().connect(command);

"function(object, event) {Wt.emit('oy4ycjy','textChanged',Wt3_3_0.$('oy4ycjy').editor.getValue());;}"

ОБНОВЛЕНИЕ 1

Добавил предложенный код в мой конструктор, однако страница не меняется с чистого белого экрана. Я больше ничего не делаю в этом проекте WT, только этот код работает.

wApp->require("lib/ace/ace.js");
// A WContainerWidget is rendered as a div
WContainerWidget *editor = new WContainerWidget(root());
std::string editor_ref = editor->jsRef(); // is a text string that will be the element when executed in JS
editor->doJavaScript(
  editor_ref + ".editor = ace.edit('" + editor_ref + "');" +
  editor_ref + ".editor.setTheme('ace/theme/monokai');" +
  editor_ref + ".editor.getSession().setMode('ace/mode/javascript');"
  );

Значение editor_ref равно "Wt3_3_0.$('Oumvrgm')" минус кавычки.

Также попытался добавить код ниже, и страница все еще не отображается.

JSignal <std::string> *jsignal = new JSignal<std::string>(editor, "textChanged");
jsignal->connect(this, &MyClass::textChanged);

WPushButton *b = new WPushButton("Save", root());
b->clicked().connect("function(object, event) {" +
  jsignal->createCall(editor->jsRef() + ".editor.getValue()") +
  ";}");

Я также обнаружил, что комментируя

editor_ref + ".editor = ace.edit('" + editor_ref + "');" +

заставляет кнопку показываться, но в правом верхнем углу экрана появляется красная надпись "Загрузка...", поэтому WT ​​что-то ждет.

У меня textChanged как функция ничего не делать в данный момент.

ОРИГИНАЛЬНАЯ ПОЧТА

Итак, моя проблема заключается в следующем. Как я могу получить ACE http://ace.ajax.org/ в WT http://www.webtoolkit.eu/wt. Более конкретно, ACE в WT Wt::WTextArea или Wt::WTabWidget, текстовая область будет предпочтительной. Я пытался сделать это в течение нескольких дней и не имел большого успеха.

Я смог без проблем встроить ACE в страницу HTML, поскольку их сайт говорит: "просто скопируйте и вставьте его на свою страницу", и это действительно так просто. Тем не менее, мне нужно загрузить его локально через WT и в контейнер. Я загрузил их репозитории из GIT на свою машину и попытался использовать

require("lib/ace/ace.js");

а также

doJavaScript(...);

с различными командами, но безуспешно... Я не так силен в Java и HTML, как C++, поэтому я буду просить как можно больше подробностей, если это связано с большим количеством Java/HTML. Заранее спасибо товарищи!

1 ответ

Решение

Может быть, это направит вас в правильном направлении:


wApp->require("lib/ace/ace.js")
// A WContainerWidget is rendered as a div
WContainerWidget *editor = new WContainerWidget(parent);
// editor->jsRef() is a text string that will be the element when executed in JS
editor->doJavaScript(
    editor->jsRef() + ".editor = ace.edit(" + editor->jsRef() + ");" +
    editor->jsRef() + ".editor.setTheme('ace/theme/monokai');" +
    editor->jsRef() + ".editor.getSession().setMode('ace/mode/javascript');"
  );

Это должно украсить редактор. Wt не отправляет изменения в div на сервер автоматически, поэтому вы делаете это вручную через JSignal (посылает сигнал из JS в C++):


JSignal <std::string> *jsignal = new JSignal<std::string>(editor, "textChanged");
jsignal->connect(this, MyClass::textChanged);

WPushButton *b = new WPushButton("Save", parent);
b->clicked().connect("function(object, event) {" +
    jsignal->createCall(editor->jsRef() + ".editor.getValue()") +
  ";}");

(приведенный выше код не тестировался, поэтому вам, возможно, придется немного отрегулировать)

Я интегрировал CodeMirror в более ранний проект JWt (Java), например:


import eu.webtoolkit.jwt.WApplication;
import eu.webtoolkit.jwt.WContainerWidget;
import eu.webtoolkit.jwt.WTextArea;

public class CodeMirrorTextArea extends WContainerWidget {
        private WTextArea textArea;
        public CodeMirrorTextArea(WContainerWidget parent) {
                super(parent);

                textArea = new WTextArea(this);

                WApplication app = WApplication.getInstance();

                app.require(app.resolveRelativeUrl("codemirror-2.32/lib/codemirror.js"));
                app.require(app.resolveRelativeUrl("codemirror-2.32/mode/groovy/groovy.js"));

                //TODO:
                //We save the editor state to the text area on each key stroke,
                //it appears to be not a performance issue,
                //however it might very well become one when editing larger fragments of code.
                //A better solution would be to save this state to the text area only when
                //the form is submitted, currently this is not yet possible in Wt???.

                String js =
                        "var e = " + textArea.getJsRef() + ";" +
                        "var cm = CodeMirror.fromTextArea(e, {" +
                        "       onKeyEvent : function (editor, event) {" +
                    "           editor.save();" +
                    "   }," +
                        "       lineNumbers: true" +
                        "       });" +
                        "var self = " + getJsRef() + ";" +
                        "self.cm = cm;";

                this.doJavaScript(js);
        }

        public CodeMirrorTextArea() {
                this(null);
        }

        public void setText(String text) {
                textArea.setText(text);
        }

        public String getText() {
                return textArea.getText();
        }

        public void setMarker(int line, String htmlMarker) {
                String js =
                        "var self = " + getJsRef() + ";" +
                        "self.cm.setMarker(" + line + ", " + jsStringLiteral(htmlMarker +
"%N%") + ");";

                this.doJavaScript(js);
        }

        public void clearMarker(int line) {
                String js =
                        "var self = " + getJsRef() + ";" +
                        "self.cm.clearMarker(" + line + ");";

                this.doJavaScript(js);
        }
}
Другие вопросы по тегам