Re[4]: Rsdn.Editor
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.01.06 22:35
Оценка: +1
Здравствуйте, alsemm, Вы писали:

VD>>Чтобы сделать точный скролинг и точное отображение позиции в документе.

A>Вернее чтобы упростить реализацию этих функций

Я в последнее время вообще стараюсь не делать вещи сложенее чем нужно. Но тут это не причем.
При редактировании текстов с большими абзацами (вроде текста этого сообщения) скролинг должен быть не менее удобным чем при редактировании файла с кодом, где стоки почти не переносятся. Отсюда надо заранее рассчитывать переносы строк. Темболее, что это относительно недолго.

VD>>И каждый раз бегать по тексту рассчитывая строку? А смысл? Тормоза от этого конечно увеличатся, а вот бенефиты...

A>Если юзать string[] для хранения текста, то да, смысла нет, не спорю.

Я не понимаю о чем ты говоришь. Что еще можно "юзать"? Массивы символов? Ну, и какая разница?
Объясни мне доходчиво.

A>Загрузили в редактор большой текст и стали его с головы редактировать.


И? Размер файла будет влиять только на время загрузки, ну, и на время изменения размера окна если включен перенос по его границе. А на редактирование это никак не скажется. Стой ты хоть в начале текста, хоть в конце.

A> Ограничения стурктуры данных (в данном случае string[]) не будут видны пока мощности железа хватает, но рано или поздно они вылезут. Вообще IMHO использование Position<Document> для адресации сомволов очень напоминает старничную память с кошмариками в виде long и short pointer-ов.


Ограничения string[]? Ты о чем? В редакторе вообще нет никаких string[]. Строки хранятся в специальном классе храняещем по одному string-гу на строку редактируемого файла.


A>...

VD>>1. Так плохой идеей было использовать дотнетный Font. Это не позволяет менять в стилях отдельные атрибуты шрифта. Например, чтобы сделать жирным ключевые слова. Это же не дает реализовать простое масштабирование шрифтов. Мне очень нравится как в Сцинтиле или ИЕ можно менять размер ширфтов просто покрутив колесико мыши удерживая при этом Ctrl.
A>Думаю это не проблема шрифта, а не совсем удачный дизайн класса Style. Если пользователи захотят что-то большее кроме как рисовать вместо текста картинки? Например обводить подстроку в рамку. Что делать будете? Добавлять поле _drawRectAroundText в Style?

А какие проблемы? Стиль == класс. Создавай наследника и храни хоть черта лысого. Другое дело, что прийдется отрисовку менять. Над расширением процесса отрисовки я даже не думал, так как не нужно. Проект с открытым кодом. Всякие плагины для него не особо то актуальный. Хотя если понадобится, то прикрутить будет не долго.

Тут же речь не о том. Речь о банальном удобстве. Человек решивший создать подсветку для некоторого формата не должен трахаться создвая стили для всех пересечений, или как ты предлагашь писать какой-то код вместо того, чтобы декларативно задать нужные ему свойства.

A>IMHO коряво.


Каждый имеет право на лево. Я считаю корявы знаниматься программированием там где можно без него обойтись.

A>class IDecoratorListener
A>{
A>public:
A>    virtual ~IDecoratorListener() {}
A>public:
A>    virtual bool
A>    onSubstringDecorated(
A>        unsigned                    line, 
A>        const char_type*            str,
A>        unsigned                    strLen, 
A>        const char_type*            substr,
A>        unsigned                    substrLen, 
A>        const TextStyle&            ts) = 0;

A>    virtual bool
A>    onSubstringDecorated(
A>        unsigned                    line,
A>        const char_type*            str,
A>        unsigned                    strLen, 
A>        const char_type*            substr,
A>        unsigned                    substrLen, 
A>        const IDecoratedSubstring&  ds) = 0;
A>};


И как это поможет тебе с рисованием той же рамки?

A>Вот, например, как можно сделать изменение размера шрифта "как в Сцинтиле или ИЕ":

A>
A>...
A>    virtual bool
A>    onSubstringDecorated(
A>        unsigned         line, 
A>        const char_type* str,
A>        unsigned         strLen, 
A>        const char_type* substr,
A>        unsigned         substrLen, 
A>        const TextStyle& ts)
A>    {
A>        HDC dc = getTempDC(); // каким-то образом получить HDC
A>        ::SelectFont(dc, ts.font);
A>        TEXTMETRICS tm;
A>        ::GetTextMetrics(dc, &tm);
A>        LOGFONT lf = textMetrics2LogFont(tm);  // как-то сконвертировали
A>        lf.height += (lf.height * 10) / 100; // увеличить шрифт на 10%
        
A>        TextStyle newTs(ts);
A>        newTs.font = ::CreateFontIndirect(lf);

A>        // передать в листенер измененный шрифт
A>        listener_.onSubstringDecorated(line, str, strLen, substr, substrLen, newTs);
A>    }
A>};
A>


Да уж... Прямо как в ИЕ или Сцинтиле... почти! Так как динамическое пересоздание шрифта на каждый токен — это задница для производительности. На относительно старом железе это будет тормозить как АБС.

К тому же изменение размеров шрифта должно быть незаметно для пользователя контрола. Да, и вобще, прямая возня с GDI — это само по себе фигня какая-то. Даже Сцинтила от нее абстрагироуется. Хотя это конечно к делу не относится.

A>Редактор дергает IDecorator::decorate каждый раз когда надо отрисовать строку текста передавая свои реализации интерфейса IDecoratorListener. Есть реализации IDecoratorListener-а которые высчитывают ширину подстроки/целой строки, высоту ну и т.д. Word wrap так же сделан через IDecoratorListener.


Ага. И на каждое вычисление размера токена мы имеем пересоздание шрифата. Плюс его же на отрисовку. Ну, нафиг такие "грамотные решения". К тому же еще и влезание пользовательского кода в низкоуровневые.

Масштибировние шрифта — задача редактора. Это относительно низкоуровневая пробелма и я лично на сегодня вижу ее решение на уровне библиотеки вывода на физическое устройство (ну, нечто вроде замены Graphics из GDI+).

В приложении будет использоваться объект-пустышка который только хранить описание шрифта (что-то вроде высокоуровневого объектно ориентированного LOGFONT). Функции вывода будут получать его и на его основании получать из кэша шрифт. Это будет и быстро, и добноно, и прозрачно для основного кода. Представлние, перед отрисовкой или рассчетом высот строк, будет выставлять свой масштаб, а библиотека отображения будет его отрабатывать.

Что касается прикладного оформления (тех самых стилей), то я считаю совершенно не верным делать какие-то потойные лазейки в данной области. Все форматирование должно определяться стилями. Если нужен новый вид форматировани, то просто добавляй новый стиль.

Я же говорил вообще о том что уже реализовано. Сейчас чтобы создать стилевой набор в котором используется один шрифт у котрого могут меняться характиристики вроде "жирный", "курсив" и т.п. я должен создать новые объекты Font. А ведь некоторые стили могут пересекаться. Если пересекаются стили с разными шрифтами, то возникает проблема. Ведь я не могу логически объеденить описание шрифтов или задать его частично (как это делаетс с цветами). Один шрифт переоределить другой. Вот я и говорю, что это просчет который нужно устранить. Должна быть возможность задавать шрифт частично. Чтобы наложение стилей не перекрывало один шрифт другим, а объеденяло их описания.

A>Бенефиты такого подхода:

A>1. декоратор дергается только для тех строк которые видны на экране — не надо мучать процессор лишней работой;

А как на счет рассчета переноса строк? Забить на него? Лично я против. Мне нужен удобный в использовании редактор, а не набор компромисов.

A>2. легко сделать кэш строк обработанных декоратором, т.к. для этого достаточно просто написать еще одну реализацию IDecoratorListener;


А зачем мне кэш строк? Я и без него отлично живу. Дотнет и так жрет слишком много памти, чтобы забиват ее совершенно не нужными кэшами.

A>3. Визуализация текста не ограничена рисованием текста или рисованием картинки вместо текста, т.к. реализация IDecoratedSubstring ограничена только фантазией юзверя (в разумных пределах конечно ;


Я не заметл, чтобы твой прмер что-то мог изменить в отрисовке. Да и ливно мне это не нужно. Любое расширение дожно быть продумано и ограничено, чтобы оно не мешала остальным частям приложения. Твое предложение убивает к чертям всю диею стилей. Ну, нафиг такие расширения.

A>4. декораторы можно комбинировать. Пример — FontChangeDecorator который изменяет результаты разбора уже существующего декоратора.


А зачем мне вообще заниматься импиратившиной зависящей от последовательности выполнения и приводящей к мутному коду, когда я могу все что нужно вырзить в виде стилей?

На то я их и проектировал, чтобы потом не трахаться с кодированием и не офигивать от побочных эффектов от наложения таких вот расширений.

Мне нужна простота, ясность и скорость.
... << RSDN@Home 1.2.0 alpha rev. 631>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.