, но в процессе возникают вопросы, на которые не удается найти однозначного ответа.
Проект достаточно объемный, поэтому сразу сделать "как надо" не получается — на первом этапе хотелось бы добиться хотя бы компиляции в том виде, в котором оно реализовано у нас на 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>?
Здравствуйте, Scorpion1105, Вы писали:
S>Здравствуйте, c-smile, Вы писали:
CS>>Вполне может быть. SciterSortElements как native API никому не нужен. Вообще первый раз слышу что его кто-то использует. CS>>Поэтому и не тестировался по всей видимости ни разу, да и накладно. script DOM тестировать проще гораздо поэтому и работает.
S>У нас, получается, что это legacy от HTMLayout — grid'ы с различными кастомными сортировками. S>Есть шанс, что найдется время пофиксить?
Я уже починил у себя.
S>P.S. behavior: column-resizer; работает теперь исключительно с <thead>? S>Вообще, как я понимаю — использование <thead> и <tbody> это правильно и стоит делать только так? По всему проекту таблицы с fixedrows и своими специальными атрибутами, определяющими заголовки — ресайзер на них не работает, да и grid.tis ожидает наличие <tbody> — единственный выход всё переделать на <table><thead>...</thead><tbody>...</tbody></table>?
thead/tbody это way to go.
scrollable tbody это единственный натуральный способ делать scrollable tables.
Здравствуйте, c-smile, Вы писали: CS>thead/tbody это way to go. CS>scrollable tbody это единственный натуральный способ делать scrollable tables.
Атрибут fixedlayout еще актуален для таблиц? Если да, как он теперь работает? Если нет, чем можно (если нужно) "заменить"?
Относительно fixedrows более менее ясно — это теперь, как я понимаю, чисто behavior-атрибут?
--
Вот такой вопрос еще — ума не приложу, в какую сторону копать... Может по симптомам (см. гифку под катом) удастся хотя бы подсказать, что можно проверить?
Гиф паразитного ресайза
Суть проблемы: открывается модальный диалог (внутри всё по науке — сообщения отдаются SciterProcND, свой цикл выборки и т.п.), рендерится содержимое, всё в порядке. Но стоит только изменить размер диалога, любое движение мыши "перерендеривает" содержимое с некой фиксированной шириной.
Для body задан стиль body { height:100%%; width:100%%; }
Здравствуйте, Scorpion1105, Вы писали:
S>Здравствуйте, c-smile, Вы писали:
CS>>thead/tbody это way to go. CS>>scrollable tbody это единственный натуральный способ делать scrollable tables.
S>Атрибут fixedlayout еще актуален для таблиц? Если да, как он теперь работает? Если нет, чем можно (если нужно) "заменить"? S>Относительно fixedrows более менее ясно — это теперь, как я понимаю, чисто behavior-атрибут?
<table fixedlayout> актуален.
В CSS :
table { flow:table-fixed; }
S>Суть проблемы: открывается модальный диалог (внутри всё по науке — сообщения отдаются SciterProcND, свой цикл выборки и т.п.), рендерится содержимое, всё в порядке. Но стоит только изменить размер диалога, любое движение мыши "перерендеривает" содержимое с некой фиксированной шириной. S>Для body задан стиль body { height:100%%; width:100%%; }
Здравствуйте, Scorpion1105, Вы писали:
S>Здравствуйте, c-smile, Вы писали:
CS>>А для html элемента какой стиль?
S>Явно габариты никакие не заданы. Инспектор показывает height: 1* и width: 1*
Такое вечатление что где-то указан width:max-content или max-width: max-content. Что-то на эту тему короче.
Без CSS сказать сложно.
Здравствуйте, c-smile, Вы писали: CS>Такое впечатление что где-то указан width:max-content или max-width: max-content. Что-то на эту тему короче. CS>Без CSS сказать сложно.
Перелопатил все CSS-файлы, max-content оказался только у кнопок, убрал кнопки, эффект остался.
В итоге получился вот такой минимальный пример, на котором проблема воспроизводится у меня (см. гифку под катом):
Так неправильно?
Как тогда? Сохранить результат и не запрашивать его на каждое сообщение?
И как так получается, что константная, по сути, функция влияет на рендер?
P.S. Ну и в обработчике WM_INITDIALOG есть, но там-то должно быть точно по делу
P.P.S. Вопрос по инспектору — он совсем не умеет показывать markup для контента, загруженного через SciterLoadHtml? Или можно как-то?
Так получается, что всё показывает — DOM, внешние css, картинки и пр., а саму страницу нет.
Здравствуйте, Scorpion1105, Вы писали:
S>Здравствуйте, c-smile, Вы писали:
CS>>Такое впечатление что у тебя где-то вызов SciterGetMin/MaxWidth/Height() где-то воткнут не по делу.
S>Воткнут, да. Но казалось бы, что по делу — реакция на WM_GETMINMAXINFO для ограничения минимального размера диалога:
А почему этот код у тебя вызывается по mouse move?
Здравствуйте, c-smile, Вы писали:
CS>>>Такое впечатление что у тебя где-то вызов SciterGetMin/MaxWidth/Height() где-то воткнут не по делу.
S>>Воткнут, да. Но казалось бы, что по делу — реакция на WM_GETMINMAXINFO для ограничения минимального размера диалога:
CS>А почему этот код у тебя вызывается по mouse move?
Так в том-то и дело, что не вызывается
Под отладчиком проверил — в SciterGetMinWidth попадаем только при инициализации диалога плюс пару раз в процессе из обработчика WM_GETMINMAXINFO (пока делаются MoveWindow и т.п.).
Дальше, ресайз диалога, опять попадаем в SciterGetMinWidth (через WM_GETMINMAXINFO), отключаю брейк-поинты, заврешается ресайз, включаю обратно.
Как только курсор попадает в область widget / table получается обсуждаемый эффект, но точки останова в SciterGetMinWidth ни разу не срабатывают при этом.
Вот как-то так.
--
Вырезал всякое лишнее из реализации (по факту — это доработка dilaog из HTMLayout SDK), добавил вот эти два файла в plain-win проект.
Вызов:
--
Есть workaroud, конечно — к SciterGetMinWidth/Height() единственное обращение делается в on_WM_INITDIALOG, значения запоминаются. В on_WM_GETMINMAXINFO используются сохраненные значения, без обращений к SciterGetMinWidth/Height(), тогда паразитных ресайзов не наблюдается. Тем не менее, не понятно, почему так...
-- S>>Вопрос по инспектору — он совсем не умеет показывать markup для контента, загруженного через SciterLoadHtml? Или можно как-то? S>>Так получается, что всё показывает — DOM, внешние css, картинки и пр., а саму страницу нет.
И вот этот вот вопрос еще актуален, если не затруднит.
достаточно тяжелая оперция. В частности этот вот вызов SciterGetMinHeight(hwndDlg, sz.cx);
Фактически делается set_width(new_width) -> relayout -> get_calculated_height(). Т.е. полный relayout содержимого.
Проблема еще в side effect — DOM остается в состоянии new_width layout.
Такое имеет смысл делать только олин раз — после начальной загрузки.
Если же контент динамический (высота зависит от ширины в runtime) то после SciterGetMinHeight нужно "возвращать всё в зад" чтобы восстановить текущий layout:
INT_PTR scdialog::on_WM_GETMINMAXINFO(HWND hwndDlg, WPARAM wParam, LPARAM lParam)
{
RECT rcClient = rcScreen;
...
auto fsctl = self(hwndDlg); assert(fsctl);
MINMAXINFO *pInfo = (MINMAXINFO *)lParam;
POINT Max = fsctl->GetMaxDialogSize();
POINT Min = fsctl->GetMinDialogSize();
Min.x += szBorder.cx;
Min.y += szBorder.cy;
pInfo->ptMinTrackSize = Min; // УСТАНОВИЛИ МИНИМАЛЬНЫЙ РАЗМЕР
pInfo->ptMaxTrackSize = Max; // УСТАНОВИЛИ МАКСИМАЛЬНЫЙ РАЗМЕР
//!!!!!!!!! Restore current normal layout:
GetClientRect(hwndDlg,&rcClient);
BOOL dummy;
SciterProcND(hwndDlg,WM_SIZE,SIZE_RESTORED,MAKELONG(rcClient.right-rcClient.left,rcClient.bottom-rcClient.top),&dummy);
return 0;
}
Т.к. WM_GETMINMAXINFO вызывается на каждый чих то SciterGetMinHeight нужно избегать.
S>-- S>Есть workaroud, конечно — к SciterGetMinWidth/Height() единственное обращение делается в on_WM_INITDIALOG, значения запоминаются. В on_WM_GETMINMAXINFO используются сохраненные значения, без обращений к SciterGetMinWidth/Height(), тогда паразитных ресайзов не наблюдается. Тем не менее, не понятно, почему так...
S>-- S>>>Вопрос по инспектору — он совсем не умеет показывать markup для контента, загруженного через SciterLoadHtml? Или можно как-то? S>>>Так получается, что всё показывает — DOM, внешние css, картинки и пр., а саму страницу нет.
S>И вот этот вот вопрос еще актуален, если не затруднит.
Здравствуйте, c-smile, Вы писали: CS>... CS>Т.к. WM_GETMINMAXINFO вызывается на каждый чих то SciterGetMinHeight нужно избегать.
Большое спасибо за разъяснение!
В подавляющем большинстве случаев контент действительно не динамический (в плане зависимости высоты от ширины), так что от лишней нагрузки избавился. А единичные случаи динамичности можно и отдельно обработать.
-- CS>1. в WinMain
Инспектор активирую для каждого экземпляра отдельно, а не в WinMain — это ведь по сути одно и тоже?
CS>2. В твоем коде исправить багу — dialog у тебя создается с parent = NULL. А нужно parent окно.
Перепроверил, вроде в этом плане всё в порядке — parent задается в конструкторе диалога CS>3. (C запущенным inspector) В окне dialog нажать CTRL+SHIFT+I — увидишь свое окно и markup:
Да, так-то всё работает — инспектор запускается.
Вопрос был немного в другом. Не работает именно вкладка Sources->markup (см. картинку под катом, обведено). И ссылки на стили, объявленные в разделе <style></style> самой html'ки. Все ресурсы (которые через url() заданы), при этом отображаются полностью.
У меня все страницы отдаются в Sciter через SciterLoadHtml(HWINDOW hWndSciter, LPCBYTE html, UINT htmlSize, LPCWSTR baseUrl), а в plain-win, например, через SciterLoadFile(HWINDOW hWndSciter, LPCWSTR filename) — и там вкладка markup показывает саму страницу.
Собственно, вопрос — можно ли добиться отображения исходного кода страницы в инспекторе при её загрузке через SciterLoadHtml?
Здравствуйте, Scorpion1105, Вы писали:
S>Здравствуйте, c-smile, Вы писали:
CS>>1. в WinMain S>Инспектор активирую для каждого экземпляра отдельно, а не в WinMain — это ведь по сути одно и тоже?
Да.
CS>>2. В твоем коде исправить багу — dialog у тебя создается с parent = NULL. А нужно parent окно. S>Перепроверил, вроде в этом плане всё в порядке — parent задается в конструкторе диалога
А да, не увидел parent(hWndParent)
CS>>3. (C запущенным inspector) В окне dialog нажать CTRL+SHIFT+I — увидишь свое окно и markup: S>Да, так-то всё работает — инспектор запускается.
S>Вопрос был немного в другом. Не работает именно вкладка Sources->markup (см. картинку под катом, обведено). И ссылки на стили, объявленные в разделе <style></style> самой html'ки. Все ресурсы (которые через url() заданы), при этом отображаются полностью. S>У меня все страницы отдаются в Sciter через SciterLoadHtml(HWINDOW hWndSciter, LPCBYTE html, UINT htmlSize, LPCWSTR baseUrl), а в plain-win, например, через SciterLoadFile(HWINDOW hWndSciter, LPCWSTR filename) — и там вкладка markup показывает саму страницу. S>Собственно, вопрос — можно ли добиться отображения исходного кода страницы в инспекторе при её загрузке через SciterLoadHtml?
Гляну что можно сделать ...
На пока используй SciterLoadFile(hwnd,"res:main.htm",...) и отдавай "res:main.htm" в SC_LOAD_DATA
Re[4]: Не обновляется содержимое тэга <a> без update()
Здравствуйте, c-smile, Вы писали: CS>На самом деле SciterUpdateElement и Element.update() это уже анахронизм — не используется в общем случае — просто вызывай методы API и Element — engine разберется. В HTMLayout с этим были проблемы поэтому эти подпорки нужны были.
Обнаружился пример, когда не удается обойтись без явного вызова sciter::dom::element::update() в native коде — подробности с версткой и визуальным эффектом ниже.
Интересно то, что никак не удается его воспроизвести, кроме как в одном месте — переносил и верстку и обработку в plain-win — там всё нормально работает.
Суть: при клике на ссылку (<a name="file_src" href="" title="">Выберите файл</a>) вызывается диалог выбора файла, и имя выбранного файла подставляется в содержимое тэга вместо "Выберите файл".
При инициализации диалога (OnInitDialog()) и при клике по ссылке (handle_event() и событие HYPERLINK_CLICK) отрабатывает один и тот же код, но при инициализации текст ссылки обновляется после выбора, а при клике — нет. Помогает только вызов update() для sciter::dom::element, соответствующего этой ссылке.
Текст менять пробовал всякими способами — set_text(), set_value() и даже set_html() с SIH_REPLACE_CONTENT (в этом случае после клика ссылка вообще пропадает).
Инспектор показывает правильное содержимое, а на странице диалога остается старое (см. гифку ниже).
Замечу, что для заголовков таблиц, например, set_text() отрабатывает нормально без update() элемента (всё рядом, в одном и том же обработчике события).
Вроде бы понимаю, что какой-то side effect к такому поведению приводит (т.к., повторюсь, воспроизвести отдельно нигде не удается), но какой, откуда и на что еще может повлиять — определить не удается.
Вопрос: в какую сторону копать и что можно сделать, чтобы выявить источник "помех"? Может уже были подобные случаи?
Верстка только заголовка, где локализована проблема
Здравствуйте, Scorpion1105, Вы писали:
S>Вопрос: в какую сторону копать и что можно сделать, чтобы выявить источник "помех"? Может уже были подобные случаи?
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, Scorpion1105, Вы писали:
CS>bgcolor поддержку добавлю в <td>/<th>
CS>
CS>... по стандарту закрывающий тэг необязателен, но Sciter ругается
CS>Sciter тебе warning говорит, но markup отрабатывает по стандарту. Используй <td />.
Андрей, спасибо за добавленную поддержку bgcolor в 3.3.2.12, к слову!
И, видимо, именно с этим связана вот такая штука:
Нашлась просто еще одна копия выбирателя цветов, тэги <td> в нем остались не закрытыми. Sciter на них больше warning'и не выдает, но ведет себя при этом интересно
А что самое печальное, при получении WM_DESTROYSciterProcND виснет на верстке с такими тэгами намертво — долго искал причину, она именно в этом. Инспектор показывает там бесконечность вложенных друг в друга таблиц.
---
В 3.3.3.2 поведение сохраняется (верстку, понятное дело, у себя поправил, но мало ли)
--
Re[6]: Не обновляется содержимое тэга <a> без update()
Поправил — нет эффекта, но он в рантайме через get_html() и так с закрытыми тэгами возвращается.
Вот такой код в рантайме, с подставленными везде строками:
<html>
<head>
<title>sync header</title>
<style type="text/css">
a popup
{
text-decoration:none;
}
.header1
{
font-size: 16dip;
}
.header_block
{
height: 52dip;
padding-left: 70dip;
background-color: white white InactiveCaption InactiveCaption;
margin: -6dip -10dip 0 -10dip;
foreground: no-repeat top left url(sciter:copy.png);
foreground-position-left: 12dip;
}
</style>
</head>
<body>
<div name="page1" style="height:100%%; width:100%%;">
<div .header_block>
<div name="frw_headerbar_page1">
<span .header1>Выбор файла-источника и установление соответствий</span>
<div style="padding-left:20dip;">
Выберите дизайн для синхронизации и задайте соответствия компонентов и цепей.
</div>
</div>
</div>
<span .header1><span name="file_choose_help">Синхронизировать открытый дизайн с </span><a name="file_src" href="" title="link title">Выберите файл</a></span><br/>
<span .header1>Установление соответствий</span>
</div>
<!-- Там дальше еще много кода, не имеющего отношения к проблеме -->
</body>
</html>
CS>А вообще там все эти spanы лишние. Попробуй упростить.
Спаны, по мимо того, что для стилей, еще и для локализации нужны. Ну а вся проблема сконцентрирована, похоже, только тут:
<span .header1><span name="file_choose_help">Синхронизировать открытый дизайн с </span><a name="file_src" href="" title="link title">Выберите файл</a></span>
Поэкспериментировал, выяснилось вот что. set_text() не обновляет контент ссылки при любом родительском элементе со стилем display: inline; (заданным явно или по умолчанию) на месте <span .header1>
Это, кстати, наводит на мысли о сходстве с багой про visible (ну это я так, просто вспомнил).
Заменяю этот span на p, div или пишу <span.header1 style="display: inline-block;"> — визуальное обновление содержимого ссылки происходит в штатном режиме.
И вот еще какой момент — в 3.3.2.13 что-то с инспектором случилось. Для приведенного выше html получается вот такая картинка (в сравнении с 3.3.2.12) — не отображается стиль для <div .header_block>:
P.S. А инспектор span'ы не подсвечивает by design? И про получение markup
Здравствуйте, Scorpion1105, Вы писали:
S>Поправил — нет эффекта, но он в рантайме через get_html() и так с закрытыми тэгами возвращается.
S>Поэкспериментировал, выяснилось вот что. set_text() не обновляет контент ссылки при любом родительском элементе со стилем display: inline; (заданным явно или по умолчанию) на месте <span .header1> S>Это, кстати, наводит на мысли о сходстве с багой про visible (ну это я так, просто вспомнил). S>Заменяю этот span на p, div или пишу <span.header1 style="display: inline-block;"> — визуальное обновление содержимого ссылки происходит в штатном режиме.
проблемы не вижу. Скорее всего там в update queue что-то еще наличествует. Попробуй оставить только операцию установки этого текста.
S>P.S. А инспектор span'ы не подсвечивает by design?
Здравствуйте, c-smile, Вы писали: CS>проблемы не вижу. Скорее всего там в update queue что-то еще наличествует. Попробуй оставить только операцию установки этого текста.
Такс, действительно, если все операции убрать, обновление происходит нормально.
Выискал конкретные 2 операции, которые заставляют его поломаться, ниже дополненный html
Html c локализацией причин
<html>
<head>
<title>sync header</title>
</head>
<body>
<div name="page1" style="height:100%%; width:100%%;">
<div .header_block>
<div name="frw_headerbar_page1">
<span .header1>Выбор файла-источника и установление соответствий</span>
<div style="padding-left:20dip;">
Выберите дизайн для синхронизации и задайте соответствия компонентов и цепей.
</div>
</div>
</div>
<span .header1><span name="file_choose_help">Синхронизировать открытый дизайн с </span><a name="file_src" href="" title="link title">Выберите файл</a></span><br/>
<span .header1>Установление соответствий</span>
<!-- ДОБАВЛЕННЫЙ КУСОК -->
<div style="margin-left:5dip;">
<table>
<tr .info_cong type="none">
<td>Соответствия компонентов:</td>
<td><span name="count_comp" /> из <span name="count_max_comp" /> <span warning="">(требуется контроль, возможно наличие ошибок)</span></td>
</tr>
<tr .info_cong type="none">
<td>Соответствия цепей:</td>
<td><span name="count_net" /> из <span name="count_max_net" /> <span warning="">(требуется контроль, возможно наличие ошибок)</span></td>
</tr>
</table>
</div>
<!-- ДОБАВЛЕННЫЙ КУСОК -->
</div>
<!-- ... -->
</body>
</html>
И вот эти самые операции (помимо этих еще куча всего — заполнение таблиц, заполнение аналогичного блока "count_net", но влияют исключительно они (если убрать — текст ссылки обновляется):
, случаем, ничего еще не придумалось? CS>SciterLoadHtml просит url, что даете?
Например (с использованием sciter::host), вот так (или как в диалоге, код которого я приводил целиком):
// ЗАГРУЗИТЬ ВСТРАИВАЕМЫЙ HTML ФАЙЛ (ИЗ РЕСУРСОВ) В ПАНЕЛЬ
LPCBYTE pb = nullptr; UINT cb = 0;
if ( !load_resource_data(html_resource(), pb, cb) ) // СТРОКОВЫЙ РЕСУРС
{
if ( !html_resource_id() || // ИЛИ ЧИСЛОВОЙ
!sciter::load_html_resource(get_resource_instance(),
html_resource_id(), pb, cb) )
return -1;
}
static const LPCWSTR sBaseUri = L"res:";
std::wstring uriBase = sBaseUri;
if ( html_resource() ) uriBase += html_resource();
if ( !load_html(pb, cb, uriBase.c_str()) ) // <== зовёт SciterLoadHtmlreturn -1;