, но в процессе возникают вопросы, на которые не удается найти однозначного ответа.
Проект достаточно объемный, поэтому сразу сделать "как надо" не получается — на первом этапе хотелось бы добиться хотя бы компиляции в том виде, в котором оно реализовано у нас на HTMLayout (т.е. без переноса behavior'ов на скрипты как минимум). Особенность проекта — обилие отдельных API / WTL панелек, модальных и немодальных диалогов со встроенным в них html-движком. Со встраиванием, в принципе, разобрался, а вот дальше не всё так гладко.
Подскажите, пожалуйста, как действовать по следующим пунктам (всё касается native кода).
Метод dom::element::get_attribute(const char* name) раньше возвращал LPCWSTR, и этот указатель очень удобно было использовать для проверки наличия атрибута. Сейчас же получается (если я правильно понимаю), что и при отсутствии атрибута у элемента и при наличии атрибута без значения вернется sciter::string нулевой длины. Как можно однозначно проверить наличие атрибута у элемента по имени в Sciter?
Некоторые значения в BEHAVIOR_EVENTS пропали. И если с TABLE_HEADER_CLICK, TABLE_ROW_CLICK, TABLE_ROW_DBL_CLICKболее менее понятно, что делать, то вот с CONTEXT_MENU_SETUP — нет.
Правильно ли я понимаю, что на первом этапе миграции можно адаптировать behavior'ы из HTMLayout к реалиям Sciter'а и использовать их? В частности, если вернуться к BEHAVIOR_EVENTS TABLE_*_CLICK из предыдущего пункта, то их какое-то время может слать адаптированный native-behavior grid, а потом уже что-то придумать со скриптом.
Может какие-то behavior'ы вообще нет смысла перетаскивать из HTMLayout и они будут работать "из коробки", не подскажите?
в проекте явно подключены следующие:
behavior_accesskeys.cpp
behavior_collapsible_by_icon.cpp
behavior_editable_select.cpp
behavior_grid.cpp behavior_hyperlink.cpp — есть в документации — видимо, переносить не нужно
behavior_path.cpp
behavior_popup.cpp
behavior_select_checkmark.cpp
behavior_sizer.cpp
behavior_splitter.cpp
И пока самый неочевидный момент — это адаптация htmlayout::gui_task и htmlayout::queue к sciter::gui_thread_ctx. Если с HTMLayout в каждом API/WTL-окне со встроенным html-движком модифицировался цикл выборки сообщений (добавлялся вызов htmlayout::queue::execute()) и где-то в логике накапливались задания в виде gui_task, то как правильно поступать со Sciter — напомню, что в приложении всегда больше одного окна/панельки/диалога с работающим в них движком.
Здравствуйте, Scorpion1105, Вы писали:
S>Метод dom::element::get_attribute(const char* name) раньше возвращал LPCWSTR, и этот указатель очень удобно было использовать для проверки наличия атрибута. Сейчас же получается (если я правильно понимаю), что и при отсутствии атрибута у элемента и при наличии атрибута без значения вернется sciter::string нулевой длины. Как можно однозначно проверить наличие атрибута у элемента по имени в Sciter?
При отсутсивии атрибута SciterGetAttributeByNameCB возвращает SCDOM_OK_NOT_HANDLED результат, можно как-то с этим поработать.
dom::element::get_attribute используется например так
std::wstring val = el.get_attribute("contenteditable", L"false");
if( val != L"false" )
...
Можно как-то по другому это сделать наверное, предлагай.
S>Некоторые значения в BEHAVIOR_EVENTS пропали. И если с TABLE_HEADER_CLICK, TABLE_ROW_CLICK, TABLE_ROW_DBL_CLICKболее менее понятно, что делать, то вот с CONTEXT_MENU_SETUP — нет.
CONTEXT_MENU_SETUP событие генерируется и поддерживается. С тем же кодом. Добавлю в header.
S>Правильно ли я понимаю, что на первом этапе миграции можно адаптировать behavior'ы из HTMLayout к реалиям Sciter'а и использовать их? В частности, если вернуться к BEHAVIOR_EVENTS TABLE_*_CLICK из предыдущего пункта, то их какое-то время может слать адаптированный native-behavior grid, а потом уже что-то придумать со скриптом.
Да, имеет смысл. Так и предполагалось изначально. Вообще native и script behaviors взаимозаменяемы. Пример \sdk\include\behaviors\behavior_tabs.cpp и sdk\widgets\tabs\tabs.tis
S>Может какие-то behavior'ы вообще нет смысла перетаскивать из HTMLayout и они будут работать "из коробки", не подскажите? S>[cut=в проекте явно подключены следующие:] S>behavior_accesskeys.cpp
Из коробки. accesskey функциональность встроена. Не требует behavior.
S>behavior_collapsible_by_icon.cpp
Можно использовать как есть а можно заменить на
function collapsibleByIcon() {
var me = this;
this.on("mousedown,mousedclick", ".icon" function() {
me.attributes["state"] = me.attributes["state"] == "close" ? "open" : "close";
return true;
});
};
и CSS:
div.collapsible { aspect: collapsibleByIcon; }
S>behavior_editable_select.cpp
из коробки.
S>behavior_grid.cpp
Или как есть использовать или sdk\samples\ideas\grid\ — это scripting порт оного.
S>behavior_hyperlink.cpp — есть в документации — видимо, переносить не нужно
не нужно.
S>behavior_path.cpp
встроенный <frameset>
S>И пока самый неочевидный момент — это адаптация htmlayout::gui_task и htmlayout::queue к sciter::gui_thread_ctx. Если с HTMLayout в каждом API/WTL-окне со встроенным html-движком модифицировался цикл выборки сообщений (добавлялся вызов htmlayout::queue::execute()) и где-то в логике накапливались задания в виде gui_task, то как правильно поступать со Sciter — напомню, что в приложении всегда больше одного окна/панельки/диалога с работающим в них движком.
Ничего этого не требуется. Даже если используется несколько GUI потоков.
Здравствуйте, c-smile, Вы писали:
CS>При отсутствии атрибута SciterGetAttributeByNameCB возвращает SCDOM_OK_NOT_HANDLED результат, можно как-то с этим поработать.
Вот, это именно та информация, которой не хватало (предполагал, что так и есть, но уверенности не было).
Вариант с проверкой значения по умолчанию был первым, что пришло в голову, но он может оказаться неудобен, если значение атрибута совпадает с этим значением по умолчанию. Второй вариант — обертка, вызывающая SciterGetAttributeByNameCB для элемента и проверяющая возвращаемое значение — т.к. про него теперь точно известно, то этот вариант и буду использовать.
CS>Можно как-то по другому это сделать наверное, предлагай.
А идеальный вариант — это добавить метод в dom::element. Примерно такой:
/**Check attribute existence by name.
* \param name \b const \b char*, name of the attribute
* \return true if element has attribute specified, false otherwise
**/bool has_attribute( const char* name ) const
{
SCDOM_RESULT r = SciterGetAttributeByNameCB(he, name, &_NULL_LPCWSTR_RECEIVER, nullptr);
return r != SCDOM_OK_NOT_HANDLED;
}
CS>CONTEXT_MENU_SETUP событие генерируется и поддерживается. С тем же кодом. Добавлю в header.
Отлично, спасибо.
CS>Да, имеет смысл. Так и предполагалось изначально. Вообще native и script behaviors взаимозаменяемы. Пример \sdk\include\behaviors\behavior_tabs.cpp и sdk\widgets\tabs\tabs.tis
По behavior'ам информацию принял, еще раз спасибо. Здесь, значит, проблем возникнуть уже не должно.
S>>И пока самый неочевидный момент — это адаптация htmlayout::gui_task и htmlayout::queue к sciter::gui_thread_ctx. Если с HTMLayout в каждом API/WTL-окне со встроенным html-движком модифицировался цикл выборки сообщений (добавлялся вызов htmlayout::queue::execute()) и где-то в логике накапливались задания в виде gui_task, то как правильно поступать со Sciter — напомню, что в приложении всегда больше одного окна/панельки/диалога с работающим в них движком.
CS>Ничего этого не требуется. Даже если используется несколько GUI потоков.
Не требуется — в смысле, что не нужно адаптировать? Или же, что gui_task'и можно теперь выполнять, не дожидаясь попадания в цикл выборки сообщений?
P.S. А вообще, то ли я совсем сам себя запутал, то ли старый queue и новый gui_thread_ctx — суть абслоютно разные вещи и для разных целей, а аналога queue теперь просто нет.
---
Появился еще один вопрос. Будет уже, получается, пунктом 5.
5. Есть ли полные аналоги (или полный охват хотя бы) для флагов UPDATE_ELEMENT_FLAGS. С REDRAW_NOW понятно — использовать update(true), но по коду активно используются еще, например, RESET_STYLE_THIS. А без варианта el.update(MEASURE_DEEP | REDRAW_NOW) в одном месте так вообще ничего сделать не могли, код переписывался раз с десяток и в итоге пришли к варианту вот с таким комментарием:
/* При изменении содержимого секции с большой долей вероятности
меняется её размер. В некоторых случаях (после работы
автопроцедур, например) при отсутствии активности мыши обычный
update с параметром типа bool не давал должного результата.
Поэтому теперь используется update с принудительной моментальной
перерисовкой и пересчетом размера элемента. */
el.update(MEASURE_DEEP | REDRAW_NOW);
SciterUpdateElement(el, TRUE), насколько я понимаю, не будет ничем отличаться от el.update(true) (если в реализации, конечно, ничего нового не появилось) — для каких флагов тогда имеет смысл дергать напрямую SciterUpdateWindow(), чтобы сохранить поведение? Для всех кроме REDRAW_NOW?
Здравствуйте, Scorpion1105, Вы писали:
CS>>Ничего этого не требуется. Даже если используется несколько GUI потоков.
S>Не требуется — в смысле, что не нужно адаптировать? Или же, что gui_task'и можно теперь выполнять, не дожидаясь попадания в цикл выборки сообщений? S>P.S. А вообще, то ли я совсем сам себя запутал, то ли старый queue и новый gui_thread_ctx — суть абслоютно разные вещи и для разных целей, а аналога queue теперь просто нет.
htmlayout::queue это сугубо multithreading feature. Нужно было например когда из рабочих потоков (worker threads) нужно было что-то сделать в UI.
Если код исполняется нормальным образом из GUI потока то этого всего не нужно было и в HTMLayout.
В Sciter это вообще всё не нужно — весь API thread safe.
В принциае sciter-x-threads.h header можно из SDK убрать — это уже legacy.
S>--- S>Появился еще один вопрос. Будет уже, получается, пунктом 5.
S>5. Есть ли полные аналоги (или полный охват хотя бы) для флагов UPDATE_ELEMENT_FLAGS. С REDRAW_NOW понятно — использовать update(true), но по коду активно используются еще, например, RESET_STYLE_THIS. А без варианта el.update(MEASURE_DEEP | REDRAW_NOW) в одном месте так вообще ничего сделать не могли, код переписывался раз с десяток и в итоге пришли к варианту вот с таким комментарием: S>
S> /* При изменении содержимого секции с большой долей вероятности
S> меняется её размер. В некоторых случаях (после работы
S> автопроцедур, например) при отсутствии активности мыши обычный
S> update с параметром типа bool не давал должного результата.
S> Поэтому теперь используется update с принудительной моментальной
S> перерисовкой и пересчетом размера элемента. */
S> el.update(MEASURE_DEEP | REDRAW_NOW);
S>
S>SciterUpdateElement(el, TRUE), насколько я понимаю, не будет ничем отличаться от el.update(true) (если в реализации, конечно, ничего нового не появилось) — для каких флагов тогда имеет смысл дергать напрямую SciterUpdateWindow(), чтобы сохранить поведение? Для всех кроме REDRAW_NOW?
На самом деле SciterUpdateElement и Element.update() это уже анахронизм — не используется в общем случае — просто вызывай методы API и Element — engine разберется. В HTMLayout с этим были проблемы поэтому эти подпорки нужны были.
SciterUpdateWindow() и view.update() используются редко но бывают нужны в определенных случаях.
Например когда после изменений DOM нужно сразу узнать позицию и размещение элемента. Но всё равно лучше исполнять код требующий знания позиции в обработчике Element.onSize.
Здравствуйте, c-smile, Вы писали:
CS>В Sciter это вообще всё не нужно — весь API thread safe. CS>В принциае sciter-x-threads.h header можно из SDK убрать — это уже legacy. CS>... CS>На самом деле SciterUpdateElement и Element.update() это уже анахронизм — не используется в общем случае — просто вызывай методы API и Element — engine разберется. В HTMLayout с этим были проблемы поэтому эти подпорки нужны были.
С этим всем теперь понятнее, спасибо. Код станет полегче
И вот еще парочка вопросов некритичных появилась.
6. Касательно флагов функции SciterScrollToView. Насколько актуален флаг SCROLL_SMOOTH? В методе Element я его вижу (параметр), а в методе dom::element — нет (в HTMLayout был и использовался). При адаптации обращения к методу с флагом smooth заменять на прямой вызов SciterScrollToView с установленным SCROLL_SMOOTH или в этом нет смысла?
7. Вся работа по преобразованию отображаемого текста теперь переложена на CSS?
Имелся отдельный behavior для вывода вертикального текста на боковых вкладках, теперь же graphics лишен функции по рисованию текста, а в скриптовой версии нет параметров для задания угла.
Вариант про вывод вертикального текста нашел и в примерах SDK и здесь на форуме
Здравствуйте, Scorpion1105, Вы писали:
S>6. Касательно флагов функции SciterScrollToView. Насколько актуален флаг SCROLL_SMOOTH? В методе Element я его вижу (параметр), а в методе dom::element — нет (в HTMLayout был и использовался). При адаптации обращения к методу с флагом smooth заменять на прямой вызов SciterScrollToView с установленным SCROLL_SMOOTH или в этом нет смысла?
в след. SDK он будет в этом виде.
S>7. Вся работа по преобразованию отображаемого текста теперь переложена на CSS?
Да.
S>Имелся отдельный behavior для вывода вертикального текста на боковых вкладках, теперь же graphics лишен функции по рисованию текста, а в скриптовой версии нет параметров для задания угла.
Ну дык это ж вот:
gfx.rotate(angle);
S>Вариант про вывод вертикального текста нашел и в примерах SDK и здесь на форуме
— применю (проблем с Subpixel Accuracy ведь не должно быть?, а то повозились немного с этим делом в behavior'е с graphin'ом).
S>P.S. Нашел тут странное различие в бинарниках x86 и x64: Image: sciter-x86-x64.png (x64 справа)
Первый шаг миграции завершился — проект компилируется.
Возникла еще пара вопросов уже по этапу выполнения.
sciter64.dll и sciter32.dll насколько сильно завязаны на свои собственные имена? Можно ли обойти эти завязки снаружи?
В частности, хотелось бы пользоваться одним именем — sciter.dll, а соответствующую по разрядности библиотеку "подкладывать" к бинарникам при сборке.
Поменял SCITER_DLL_NAME на "sciter.dll", получаю вот такое при вызове SciterSelectElements:
Unhandled exception at 0x00007FF9DAAEFE34 (ntdll.dll) in .exe: 0xC000041D: Во время обратного вызова пользователя обнаружено необработанное исключение.
в OnLoadData приходили значения LPNMHL_LOAD_DATA->uri"font.css" и "folder.png" соответственно.
Для Sciter в on_load_data приходят значения LPSCN_LOAD_DATA->uri"file://font.css" и "file://folder.png".
Загрузчик ресурсов (sciter::load_resource_data), понятное дело, с таким префиксом из ресурсов файл подтянуть не может.
Как поступить (или может просто что-то настроить можно)?
Прописывать во всех url() префикс res: — не очень радужная перспектива.
Считать, что file: сознательно использоваться не будет, и интерпретировать его аналогично res: — веселее, но правильно ли?
Здравствуйте, Scorpion1105, Вы писали:
S>Андрей, добрый день!
S>Первый шаг миграции завершился — проект компилируется.
S>Возникла еще пара вопросов уже по этапу выполнения.
S>В частности, хотелось бы пользоваться одним именем — sciter.dll, а соответствующую по разрядности библиотеку "подкладывать" к бинарникам при сборке.
Не понятно зачем это делать.
S>@import url(font.css);
"font.css" это relative URL. Резолвитя в полный URL используя root URL (документа).
Здравствуйте, c-smile, Вы писали: CS>Не понятно зачем это делать.
Исключительно из эстетических соображений (разрядность не фигурирует в именах dll как проектных, так и 3rd party) и, как практическая польза от эстетики, для унификации списка файлов в дистрибутивах разной разрядности.
Да и при самой сборке активно одинаковостью имен пользуемся — целевая платформа влияет только на пути (что в студии удалось вполне удобно реализовать макросами MSBuild), а имена библиотек всегда неизменны — проще читать *.vcxproj глазами, когда нужно, например. CS>"font.css" это relative URL. Резолвитя в полный URL используя root URL (документа).
Ага, вот оно как, спасибо.
Сам root URL на что-нибудь еще кроме резолва relative URL влияет?
Просто поэкспериментировал — для получения res:font.css оказалось достаточно загрузить документ из ресурсов так: ::SciterLoadHtml(..., L"res:");, что меня вполне бы устроило.
При загрузке документа, в on_load_data приходит пустое значение LPSCN_LOAD_DATA->uri (L""). Так и задумано?
В HTMLayout не наблюдалось. Замечено только на первом загружаемом в приложении html.
---
И еще один. Пожалуй, наиболее интересный на данный момент.
Сложилось ощущение, что что-то серьезно изменилось со времен HTMLayout в интерпретации разметки и некоторых основных стилей (или может в box-модели, или в стилях по умолчанию).
Была, например, страничка со вкладками — пока не добавил для вкладок width: auto; отказывалось работать как раньше.
Или вот пример легенький, с полной разметкой и картинками
Здравствуйте, Scorpion1105, Вы писали:
S>Где можно почитать, что же на самом деле изменилось, чтобы понимать, какие конкретно правки потребуются в верстке?
Здравствуйте, c-smile, Вы писали: CS>В общем и целом HTML/CSS более совместим со стандартом. И вот http://sciter.com/docs/sciter3.pptx CS>Т.е. если ты использовал стандартную разметку то проблем не должно быть.
Андрей, поддержка атрибута bgcolor пропала намерено или по недосмотру? Или в угоду HTML 5?
Перестал работать пример под катом. Да и logfile.htm из SDK (или cssmap, например) в самом скайтере отображается без фона у ячеек таблицы.
Понятно, что можно реализовать стилями, как в samples\ideas\color-chooser, но сейчас не хотелось бы переделывать...
И в этом же примере вопрос относительно тэга <td> (там всякие варианты есть в коде) — по стандарту закрывающий тэг необязателен, но Sciter ругается: <td> element is not allowed at (file://.../color_pick.html(46))
Как предполагается правильно оформлять пустые <td>: <td /> или <td></td> или оба варианта? Или можно таки закрывающий тэг пропускать?
Пример с разными вариантами задания атрибута bgcolor и тэга td
Это чуть измененная версия примера: \HTMLayoutSDK\html_samples\css-plus\tree-view-lines.htm
Тэг <options> — используется как папка, <option> — как файл.
У меня стоит задача наладить множественное выделение элементов этого дерева(уточняю, папки и файлы могут быть в одной выделенной группе) по клавише shift. Выглядеть это должно так: сначала MOUSE_CLICK по одному элементу дерева, затем MOUSE_DOWN + SHIFT_KEY_PRESSED по другому элементу дерева(оба этих элемента могут лежать на разных уровнях), в итоге эти элементы, как и те которые находятся в "вилке" между ними — должны быть выделены. На данный момент этого сделать не выходит, т.к элементы <options>(в отличии от <option>) которые лежат между крайними элементами, не входят в состояние :checked. При одиночном выделении элемента(или множественном с помощью клавиши ctrl) — все отлично. Как выйти из этой ситуации? Проект, над которым я работаю, мигрирует с htmlayout на sciter, сохранится ли эта ситуация и там? Я нашел информацию о том, что в sciter'е появился новый behavior, завязанный на работу с подобными древовидными структурами. Может его использование решит проблему?
... по стандарту закрывающий тэг необязателен, но Sciter ругается
Как предполагается правильно оформлять пустые <td>: <td /> или <td></td> или оба варианта? Или можно таки закрывающий тэг пропускать?
Sciter тебе warning говорит, но markup отрабатывает по стандарту. Используй <td />.
В Sciter <options> элемент не использзуется. Только <option>.
Проблему выделения MOUSE_CLICK/SHIFT не понял если честно.
Примитивный state automata:
function selectRange(select, optFirst, optLast) {
var insideRange = false;
// linear list of all option's:for(var option in $$(select option))
{
if( insideRange ) {
option.state.checked = true; // mark selected options by :checked flag if( option === optFirst || option === optLast ) {
insideRange = false;
}
} else { // not in range yet:if( option === optFirst || option === optLast ) {
insideRange = true;
option.state.checked = true; // first element in range, mark it
} else {
option.state.checked = false; // mark as not selected
}
}
}
}
selectRange() снимает предыдущее выделение и ставит новое на всех элементах в [optFirst ... optLast] range.
Если optFirst и optLast оба null то просто снимает выдкление.
CS>selectRange() снимает предыдущее выделение и ставит новое на всех элементах в [optFirst ... optLast] range. CS>Если optFirst и optLast оба null то просто снимает выдкление.
CS>Вроде как просто, нет?
Андрей, проблема лишь в том, что я не могу получить этот "// linear list of all option's: " для своего случая.
Например как его получить, когда элементы подлежащие выделению лежат на разных уровнях:
Ваш же код, на сколько я понял, предназначен для таких случаев:
Здравствуйте, yuriy_b, Вы писали:
CS>>selectRange() снимает предыдущее выделение и ставит новое на всех элементах в [optFirst ... optLast] range. CS>>Если optFirst и optLast оба null то просто снимает выдкление.
CS>>Вроде как просто, нет?
_>Андрей, проблема лишь в том, что я не могу получить этот "// linear list of all option's: " для своего случая. _>Например как его получить, когда элементы подлежащие выделению лежат на разных уровнях:
Не понимаю твою проблему если честно. Это как бы тривиальный обход дерева, нет?
Эта вот функцтя:
var arrayOfOptions = select.$$(option);
Вернет список всех <option> элементов внутри select. На любом уровне. И в DOM order.
Андрей, обнаружил весьма странную штуку, относительно функции SciterSortElements — результат её работы никак не отображается в GUI.
При этом компаратор вызывается исправно для сортируемых элементов.
При этом get_html() до её вызова на элементе и после возвращает разное содержимое (после — отсортированное).
При этом скриптовая версия работает исправно (в том же grid в сэмплах).
Получается, что после сортировки нужно вызывать что-то еще? Что? Т.к. update, refresh, SciterUpdateWindow уже перепробовал — эффекта нет.
P.S. Есть пример с воспроизводимостью проблемы на базе plain-win.exe, если нужно.
Здравствуйте, Scorpion1105, Вы писали:
S>Здравствуйте, c-smile, Вы писали:
S>Андрей, обнаружил весьма странную штуку, относительно функции SciterSortElements — результат её работы никак не отображается в GUI.
Вполне может быть. SciterSortElements как native API никому не нужен. Вообще первый раз слышу что его кто-то использует.
Поэтому и не тестировался по всей видимости ни разу, да и накладно. script DOM тестировать проще гораздо поэтому и работает.
Здравствуйте, c-smile, Вы писали:
CS>Вполне может быть. SciterSortElements как native API никому не нужен. Вообще первый раз слышу что его кто-то использует. CS>Поэтому и не тестировался по всей видимости ни разу, да и накладно. script DOM тестировать проще гораздо поэтому и работает.
У нас, получается, что это legacy от HTMLayout — grid'ы с различными кастомными сортировками.
Есть шанс, что найдется время пофиксить?
Workaround с подменой html-внутренностей через set_html не очень подходит — сбиваются DOM-ссылки, как следствтие не прокрутить к выбранному до сортировки элементу и т.д. и т.п.
Единственный выход — это скриптовый behavior, который бы дергал нативную функцию сравнения, но это пока слишком объемно переводить всё...
P.S. behavior: column-resizer; работает теперь исключительно с <thead>?
Вообще, как я понимаю — использование <thead> и <tbody> это правильно и стоит делать только так? По всему проекту таблицы с fixedrows и своими специальными атрибутами, определяющими заголовки — ресайзер на них не работает, да и grid.tis ожидает наличие <tbody> — единственный выход всё переделать на <table><thead>...</thead><tbody>...</tbody></table>?