Видимо, авторы TLF, как всегда, забыли, что Flash Player при отрисовке чего-то, заданного float (а underlineOffset может быть равен 0.451171875) subpixel rendering не осуществляет.
Видимо, авторы TLF, как всегда, забыли, что Flash Player при отрисовке чего-то, заданного float (а underlineOffset может быть равен 0.451171875) subpixel rendering не осуществляет.
есть какой-нить другой способ прикрепить кастомное поле к ссылке?
#1179963 ?
Технически инженер из Adobe прав ( forums.adobe.com ). Прав на 100%.
Есть только два нюансы — мы, черт возьми, люди.
Два вопроса:
1) Какого черта оно после прокрутки до упора вниз (key down) и прокрутки взад до упора вверх (key up) не восстанавливает позицию (текст будет прилеплен)?
2) АУ! На дворе чертов 2011 год, романтика программирования ушла и канула в лету, откройте тот же Interface Builder да накидайте вы TextView и посмотрите как оно себя ведет. Что, тоже торкает как оно аккуратно рассчитывает середину текста и плавно откручивает при достижении viewHeight ровнехонько на -viewHeight/2 с сохранением позиции курсора (вопрос номер три – какого черта оно при достижении конца переносит мой курсор в конец строки (все правильно) и потом забывает вернуть взад?).
Между прочим, TinyTLF скоро будет поддерживать редактирование, а уже сейчас дает с в разы меньшими вложениями в разы более нормальное (читай как в твоей ОСи, а не как в мозгу обкуренных не той травой "инженеров" Adobe) поведение (+как плюшка производительность, но в нашей то ситуации дай бог сделать нормально и в срок).
Кто-нибудь еще сомневается, что можно иметь что-то общее с этими отмороженными дебилами (медицинский термин, ага) Технически инженер из Adobe прав ( forums.adobe.com ). Прав на 100%.
Есть только два нюансы — мы, черт возьми, люди.
Два вопроса:
1) Какого черта оно после прокрутки до упора вниз (key down) и прокрутки взад до упора вверх (key up) не восстанавливает позицию (текст будет прилеплен)?
2) АУ! На дворе чертов 2011 год, романтика программирования ушла и канула в лету, откройте тот же Interface Builder да накидайте вы TextView и посмотрите как оно себя ведет. Что, тоже торкает как оно аккуратно рассчитывает середину текста и плавно откручивает при достижении viewHeight ровнехонько на -viewHeight/2 с сохранением позиции курсора (вопрос номер три – какого черта оно при достижении конца переносит мой курсор в конец строки (все правильно) и потом забывает вернуть взад?).
Между прочим, TinyTLF скоро будет поддерживать редактирование, а уже сейчас дает с в разы меньшими вложениями в разы более нормальное (читай как в твоей ОСи, а не как в мозгу обкуренных не той травой "инженеров" Adobe) поведение (+как плюшка производительность, но в нашей то ситуации дай бог сделать нормально и в срок).
Combine this operation with another operation if the result can
be represented as a single operation. In general, operations cannot be
merged. But sequential inserts or deletes may be mergeable.
Ну не суки ли написать такой важный коммент там, где можно прочитать лишь если залезть в код? :(
#1106352 о пиздатости дизайна TLF и Flex.
Ну вот я решил отнаследовать RichEditableTextContainerManager и, конечно, отнаследовать RichEditableText, в котором этот отнаследованный менеджер будет использоваться. Все, вроде, здорово. Мне даже не надо отнаследоваться от TextArea так как у нас есть механизм скинов, в котором мы можем легко и просто подменить наш RichEditableText на RichEditableTextExt. Конечно, тут тоже не все пучком. Ибо скин приходится полностью копировать, но это уже баян и не смешно.
Но метод создания RichEditableTextContainerManager в RichEditableText, который мне надо переопределить, состоит из одной строчки:
При этом staticConfiguration — это приватное статическое поле. Понятно, что код его создания придется копировать тоже. Ну вот ничего у Адобов нельзя сделать быстро просто и красиво. А ведь когда-то так не было. Как-то проще все было…
В продолжение Ну вот я решил отнаследовать RichEditableTextContainerManager и, конечно, отнаследовать RichEditableText, в котором этот отнаследованный менеджер будет использоваться. Все, вроде, здорово. Мне даже не надо отнаследоваться от TextArea так как у нас есть механизм скинов, в котором мы можем легко и просто подменить наш RichEditableText на RichEditableTextExt. Конечно, тут тоже не все пучком. Ибо скин приходится полностью копировать, но это уже баян и не смешно.
Но метод создания RichEditableTextContainerManager в RichEditableText, который мне надо переопределить, состоит из одной строчки:
return new RichEditableTextContainerManager(this, staticConfiguration)
При этом staticConfiguration — это приватное статическое поле. Понятно, что код его создания придется копировать тоже. Ну вот ничего у Адобов нельзя сделать быстро просто и красиво. А ведь когда-то так не было. Как-то проще все было…
Тем не менее, этот TextContainerManager решает вопросы перехвата событий мыши в виде событий, когда ContainerController предполагает наследование и переопределение соответствующих обработчиков. Решение кривоватое (обращение только через контейнер), но решение. А теперь такой момент, что контекстное меню они решили из этого класса исключить. Ничего страшного. Сделаем свой ContainerController, в котором переопределим menuSelectHandler. Но в итоге оказывается, что старый ContainerController в TextFlow уже не заменить столь безболезненно, особенно ничего не зная о нашем контейнере и оперируя лишь TextFlow (как нам этого бы и хотелось).
Дело в том: что этот TextContainerManager имеет внутренний класс, отнаследованный от ContainerController, на который жестко, а не по родителям или интерфейсу завязан. То есть распутать их нельзя. NPE обеспечено. Они ссылаются друг на друга и ввиду того, что TMContainerController — класс внутренний, он не наследуется и не подменяется.
В итоге сейчас пойду наследовать TextContainerManager, что все равно предполагает, что придется общаться с контейнером.
Ух, Адобы, кривые вы уроды! И все это на фоне чрезмерной усложненности TLF, который почему-то должен быть MVC. Хотя никто не может в точности сказать, где там M, где V, а где C. Ибо роли нечетки размазаны тонким слоем по хлебу :(
Я высказался :)
guyinthechair.com Model Agnosticism). При этом вы не обязаны предоставить движку (да, да, движку, что невозможно сказать в отношении TLF, то в случае tinytlf именно text engine) сразу всю модель — можно как поток, посредством реализации ITextBlockFactory — спросили у вас nextBlock — отдали. Это абсолютно не имеет смысла, если вам нужно просто отобразить некий статический текст, но ведь, черт возьми, это ведь text engine — оно должно давать удобный API в том случае, если текст у вас строится динамически.
Еще одним несомненным плюсом tinytlf является отсутствие такого маразма как TextFlow. Моделью выступают непосредственно классы Flash Player — ContentElement (see Понятный и удобный API (если мне нужно установить только ширину, я explicitWidth = newW, а не setCompositionSize(newW, NaN)).
Минусы только по оформлению кода — явно видно, что автор пользуется блокнотом/Flash Builder, а не IntelliJ IDEA.
Черт возьми, впервые за 5 лет испытал удовольствие от работы со сторонней библиотекой на ActionScript (mate не в счет). По привычке порывался при использовании писать свое, но чудо — интерфейсы тут не только для галочки. И даже абстрактные классы можно использовать как базовые (с Flex SDK и TLF это невозможно — интерфейсы не используются, типы параметров/свойств конкретные, а в случае с tlf добавляется еще и tlf_internal). Да — если в неком коде используются пространства имен — разработчика кастрировать, а также всех сопричастных (в моей библиотеке Cocoa используется пространство имен ui для ui component skin parts, но это лишь от бедности — все время не найду написать compiler extension для ast генерации в compile time — то бишь в runtime этот namespace никак не является частью API/рабочего кода). Использование пространств имен это отличный индикатор убожества архитектуры. Потому что с ними все эти высокотеоретические выкладки об ООП смываются и размываются — это даже не прострелить себе ногу. И отсутствие поддержки пространств имен для интерфейсов это показатель, да.
Помимо пула для textLine (reuse на уровне плеера, добавление/удаление из пула на уровне as), также есть пул для textBlock (только на уровне as, при написании своей реализации ITextBlockFactory, нужно знать об этом пуле и использовать его) — вот этого в tlf нет.
Есть хитрый момент с инвалидацией. TextEngine принимает необязательный параметр stage. Stage ему нужен как раз для валидации — как во флексе, отрисовка происходит не на каждое изменение данных, а в определенный момент времени. И tinytlf вешается на ENTER_FRAME и RENDER (какой раньше придет — пришел — отписались от обоих и render). Если мы используем tinytlf во флекс-приложении, где уже есть свой LayoutManager, делающий ту же работу, то нужно ли нам передавать tinytlf stage? Если текст не интерактивный — можно всю валидацию осуществлять в host component — он на updateDisplayList вызывает у textEngine render и все (тема встраивания text engine во flex component lifecycle (типа measure) обширна и в этот топик не входит, могу лишь сказать, что тут tlf sucks, а tinytlf берет пирожок). А вот если интерактивный — то ничего работать не будет (то бишь никакой отрисовки в ответ на действия пользователя) — ведь он будет ждать, пока его отвалидируют. Интересно, что в реализации RichTextField данный момент никак не решен (тупо передается stage — то есть возможен сценарий гонки — когда оно отрисуется до updateDisplayList). Решается написанием своего (патч автору еще не отправил).
А gestures — это песня. Вам не нужен ParagraphSelectionBehavior? Ну так не мапьте его — оставьте только CharacterSelectionBehavior и WordSelectionBehavior. Впрочем — управление курсором вкупе со ссылками из разных блоков — получается порнография. Потому что стека курсора нет, получается гонка и как результат вы на второй ссылке получите auto вместо button/ibeam. Вряд ли автор tinytlf поправит это (невоспроизводимо на обычных текстах), пока что на это забил.
Нерваное выделение текста, как и должно быть в Mac OS X — juick.com
Черт возьми, оно умеет отрисовывать подчеркивания не как путь всегда обкуренных сотрудников Adobe домой — то прилеплено к глифам, то нет, а нормально — всегда с отступом.
И, да, кайфую от того, что когда-то исправил компилятор таким образом, что вектор созданный в виде литерала, является фиксированным ( juick.com ).
guyinthechair.com You can grab mavenized project github.com (just open in IntelliJ IDEA and get configured ide project).
Еще не работал, но уже чувствую, что Adobe должна уволить весь TLF team и нанять
juick.com FB профайлер тормозной (IDEA берет те же данные гораздо быстрее, вот только показывает она их не так удобно — видимо, тут ошибка Adobe в том, что они перенесли/реализовали часть вычисления на сторону flash player, а по сути правильно отправить лишние несколько метров на сторону java и пусть она сама считает) — при наведении на ссылку он подвисает, а потом можно видеть в таблице результатов — TLF честно полностью композирует весь TextFlow (flowComposer.updateAllControllers()). В моем случае оно честно вызывает 198 раз createTextLine. Правильно, а вдруг в новом формате ссылки новый fontSize? Только, сцуко, не в их наркотическом бреду, а в реальной жизни у нас меняется только и только цвет у ссылки (а то и вовсе — подчеркивание, то есть даже и одного вызова recreateTextLine не будет — тупо удостовериться, что sprite для отрисовки уже добавлен в существующий textLine, и отрисоваться в нем) — и нет никаких проблем проверить эти два условия (и только в худшем случае recompose all)).
Профилировал
repository.flyti.org
Опубликовал немного дополненную 2.0.189-de1 (192 билд). У FlowGroupElement
public function set children(chidlren:Vector.<FlowElement>):void
и
public function set child(child:FlowElement):void
Для чего? Если вам надо добавить в параграф 100 span, то использование addChild (100 раз) повлечет за собой вызов replaceChildren. А там мама роди меня обратно. Логичнее иметь некий инициализирующий сеттер для childArray.
И у textFlow свойство skipNormalization. Если у вас руки не дрожат и вы сами инициализируете textFlow и оно не editable, то даром не нужно нормализовывать. Тем более, что оно там есть интересные моменты — если вы установите interactionManager до добавления контента, то оно... отнормализует его — добавит span в пустой параграф (а вы будете мучиться паранойей, откуда в новом параграфе дети и почему numChildren не равен 0 изначально).
Сборки TLF для мавена, как уже писалось, можно брать тут — Опубликовал немного дополненную 2.0.189-de1 (192 билд). У FlowGroupElement
public function set children(chidlren:Vector.<FlowElement>):void
и
public function set child(child:FlowElement):void
Для чего? Если вам надо добавить в параграф 100 span, то использование addChild (100 раз) повлечет за собой вызов replaceChildren. А там мама роди меня обратно. Логичнее иметь некий инициализирующий сеттер для childArray.
И у textFlow свойство skipNormalization. Если у вас руки не дрожат и вы сами инициализируете textFlow и оно не editable, то даром не нужно нормализовывать. Тем более, что оно там есть интересные моменты — если вы установите interactionManager до добавления контента, то оно... отнормализует его — добавит span в пустой параграф (а вы будете мучиться паранойей, откуда в новом параграфе дети и почему numChildren не равен 0 изначально).
И не надо потом спрашивать, а почему вы не используете флекс напрямую, а только как базу для собственых компонент — juick.com .
tlf_internal override function getEventMirror():EventDispatcher
Вроде, ничего страшного. А теперь ASDoc к этому методу:
Gets the EventDispatcher associated with this FlowElement. Use the functions
of EventDispatcher such as setEventHandler() and removeEventHandler()
to capture events that happen over this FlowLeafElement object. The
event handler that you specify will be called after this FlowElement object does
the processing it needs to do.
Ну вы поняли? Человек, писавший этот код, считает, что у EventDispatcher есть методы setEventHandler и removeEventHandler. И эти люди запрещают мне ковыряться в носу!
Выяснить закономерность у меня не получатеся %(, но обычно это происходит при инициализации компонента.
#1010011 Даже те хаки, что предлагаются, расчитаны на Flex 4, в то время как TLF типа не привязана к Flex. Вот и получается, что ни встраиваемых шрифтов искаропки, ни решений/хаков, которые подошли бы просто в любой ситуации :( Мудаки, хуле. Правая рука не знает, на что дрочит левая.
И все же инженеры из Adobe мудаки :( Все по поводу этого вот
@Constantiner ;) Поэтому будем радоваться просто, что мы все олени. Все-таки зима скоро.
За три дня от разных производителей ненужного информационного шума (и по направлению) куча постов WTF о шрифтах (как вершина айсберга, лакмусовая бумажка) и убогости текстовой подсистемы флеша (+tlf, как бы идиотам в Adobe не хотелось отгородить его). Да. Adobe умеют доставить. Но я уже проникся философией
forums.adobe.com и куски говна в сторону Adobe какбе подтверждают мои непонятки #1012377
Срач в комментах
juick.com — трава — "The factory and the composer produce slightly different results which can confuse the scroller." — если для RichEditableText есть скроллер, то он в любом случае будет конвертировать текст в textFlow. По логике, надо было разбираться почему slightly different results.
В тему
juick.com . Предположим, вы решили не патчить TLF для решения этого идиотизма, а грустно вспомнили что вы проститутка и решили просто таскать с собой textFlow. Вы думаете, все проблемы решены? Трава. Если вы установили textFlow для RichEditableText, то не надо думать, что вам позволят сохранить ссылку на него — вы обязаны всегда теперь таскаться с instance RichEditableText, потому что в textContainerManager_damageHandler он может тупо _textFlow = textContainerManager.getTextFlow(); — то есть если вы у вашего textFlow смените fontFamily, то ничего не произойдет, так как TLF оперирует уже другим. Adobe, когда ты сменишь поставщика травы?
В тему if (_format is TextLayoutFormat || _format is TextLayoutFormat)
useFormat = _format;
else
useFormat = new TextLayoutFormat(_format);
_computedPrototypeFormat = FlowElement.createTextLayoutFormatPrototype(useFormat,null);
То есть вы никак не можете динамически стилизовать textFlow. Чтобы установить новый font family, у вас есть два пути — 1) непосредственно у textFlow установить свойство fontFamily 2) клонировать свой формат (тот же instance не покатит) и присвоить ему новое значение (на perfomance мы уже давно положили болт и о нем даже речи нет). Казалось бы, — установи ты свойство напрямую у textFlow и не выпендривайся. Это покатит в простом приложении. В сложном возникает ряд нюансов — этот формат нужен не только TLF, но и высокоуровневому ui-control textArea для расчета char metrics (посчитать тот же height in lines). Если вы делаете Font Panel (то есть даете пользователю некий тул типа как в MS Office для кастомизации шрифта, цвета и прочего), то для Font Panel в разы удобнее работать именно с некой моделью простой, а не с textFlow (тем более, что она не должна быть зависима от TLF — может мне хватит формата и я отрисую текст посредством flash text engine напрямую). Черт возьми, ну как можно так проектировать? Какие к черту митинги и обсуждения, если это не rocket science?
TextLayoutFormat instead of an ITextLayoutFormat. This change is backwards compatible with current code because TextLayoutFormat
implements ITextLayoutFormat." Правильно, интерфейсы эта такая штука, она для красоты.