Гость
Форумы / Delphi [игнор отключен] [закрыт для гостей] / SynEdit и подсветка текущего выделенного слова по документу / 22 сообщений из 22, страница 1 из 1
02.11.2021, 22:21
    #40108860
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Друзья, кто нибудь делал такое:
http://www.freepascal.ru/forum/viewtopic.php?f=44&t=7746&sid=ef6b81c47b1fe6b001bbc706a42111ac

Только в Delphi? Крайне не хочется портировать lazarus вариант, так как зависимостей там сотни и по простому вряд ли получится. Может кто-то уже делал подобное в Delphi?
...
Рейтинг: 0 / 0
02.11.2021, 22:29
    #40108862
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
На вскидку, начал бы искать в 2-ух направлениях:
- какое-нибудь событие, получающее на вход, скажем, очередное слово из сканируемого документа и возвращающее атрибуты текста
- либо, что лучше, возможность добавить зарезервированное слово, которое есть выделяемый текст
...
Рейтинг: 0 / 0
03.11.2021, 00:50
    #40108866
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Тут скорее вопрос в том, есть ли что-то уже готовое и отлаженное. Сделать то велосипед можно, но займет немало времени, так как нужно чтобы работал на больших листингах и не тормозил приложение при постоянных щелчках по тексту туда-сюда. При этом адекватно работало обычное выделение. А это не "просто добавить кейворд" к сожалению.
...
Рейтинг: 0 / 0
03.11.2021, 01:01
    #40108868
Softologic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
DelDelphi
Тут скорее вопрос в том, есть ли что-то уже готовое и отлаженное. Сделать то велосипед можно, но займет немало времени, так как нужно чтобы работал на больших листингах и не тормозил приложение при постоянных щелчках по тексту туда-сюда. При этом адекватно работало обычное выделение. А это не "просто добавить кейворд" к сожалению.

Готовое и отлаженное решение, не тормозит: https://delphihtmlcomponents.com/index.html
Покрывает вашу задачу с легкостью на больших листингах, ну и много чего еще "из каропки". В вашем случае достаточно HTML Component Library, который стоит $349.
...
Рейтинг: 0 / 0
03.11.2021, 01:13
    #40108869
Softologic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Две строчки кода:

Код: pascal
1.
2.
MailView.Doc.HighlightText := AnsiLowerCase(fSearchText);
MailView.Refresh();



Ниже результат - почтовый клиент на базе вышеупомянутого HTML Components (Bundle).
...
Рейтинг: 0 / 0
03.11.2021, 01:18
    #40108870
Softologic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Точнее хотел сказать, что результат выполнения двух строчек кода представлен желтым выделенным фрагментом на скрине проекта. Вот :)
...
Рейтинг: 0 / 0
03.11.2021, 01:38
    #40108873
Softologic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Еще есть вариант подешевле - https://www.trichview.ru/features/trichview.html
Не помню досконально, но вероятнее всего там тоже есть функция выделения повторяющегося фрагмента во всем тексте.
...
Рейтинг: 0 / 0
03.11.2021, 01:43
    #40108874
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Softologic,

К сожалению ваши варианты вообще не к месту, так как в продукте уже реализован SynEdit с кастомно написанными хайлайтерами под разные языки, поддерживаемые нашим продуктом. Плюс море кастомных плюшек типа CodeFolding. Задача стоит добавить подсветку выделенных кейвордов по всему листингу используя именно SynEdit. Смена компонента не рассматривается.
...
Рейтинг: 0 / 0
03.11.2021, 01:54
    #40108875
Softologic
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
DelDelphi
Softologic,

К сожалению ваши варианты вообще не к месту, так как в продукте уже реализован SynEdit с кастомно написанными хайлайтерами под разные языки, поддерживаемые нашим продуктом. Плюс море кастомных плюшек типа CodeFolding. Задача стоит добавить подсветку выделенных кейвордов по всему листингу используя именно SynEdit. Смена компонента не рассматривается.

Ну ок, если так. Просто изначально было не понятно, что все только в пределах SynEdit
...
Рейтинг: 0 / 0
03.11.2021, 05:36
    #40108877
ma1tus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
DelDelphi, пример
...
Рейтинг: 0 / 0
03.11.2021, 11:20
    #40108914
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Softologic
Ну ок, если так. Просто изначально было не понятно, что все только в пределах SynEdit


Я потому сразу ссылку на Lazarus форум дал, так как нужен аналог. Задача в листингах до пары мегабайт щелкать по опкодам и операндам и чтобы аналогичные подсвечивались по всему тексту. Тупой search и подсветка тут непокатят - повиснет все после тысячного найденного eax или ebx (как пример). Надеялся что есть что-то уже отлаженное нативное, которое следит за скроллом, кареткой, перемещениями по тексту и подсвечивает асинхронно блоками динамически.

ma1tus, благодарю. Погляжу.
...
Рейтинг: 0 / 0
03.11.2021, 13:37
    #40108943
kapas
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
В SynEdit для подобных вещей существует спец. класс TSynEditPlugin

С ним работать достаточно просто:

1. Определяем нужный тип
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
    TSelectTextMarkupHighlighter = class(TSynEditPlugin)
    private
        FAttribute: TSyntaxHighlighterAttribute;
        FEnabled: boolean;
        FWholeWordOnly: boolean;
        FCaseSensitivity: boolean;
    protected
      function GetEnabled(): boolean; overload; virtual;
      procedure SetEnabled(const AValue: boolean); overload; virtual;
      function GetWholeWordOnly(): boolean; overload; virtual;
      procedure SetWholeWordOnly(const AValue: boolean); overload; virtual;
      function GetCaseSensitivity(): boolean; overload; virtual;
      procedure SetCaseSensitivity(const AValue: boolean); overload; virtual;
    protected
      procedure AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: Integer); override;
    public
      procedure AfterConstruction(); override;
      destructor Destroy(); override;
    published
        property Attribute: TSyntaxHighlighterAttribute read FAttribute write FAttribute;
        property Enabled: boolean read GetEnabled write SetEnabled;
        property WholeWordOnly: boolean read GetWholeWordOnly write SetWholeWordOnly;
        property CaseSensitivity: boolean read GetCaseSensitivity write SetCaseSensitivity;
    end;


или
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
    TBlockMarker = class(TSynEditPlugin)
....
    protected
      procedure AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: integer); overload; override;
      procedure LinesInserted(AFirstRow, ACountRows: integer); overload; override; // обрабатываем вставки
      procedure LinesDeleted(AFirstRow, ACountRows: integer); overload; override;  // обрабатываем удаления
....
    public
//      procedure AfterConstruction(); override; // необязательно

    end;



2. Главная процедура (привожу рабочий вариант)

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
      procedure TSelectTextMarkupHighlighter.AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: Integer);
      var
        AStoreFont: TFont;
        AStoreBrush: TBrush;
        ASelectText: string;
        ACurrPt: TPoint;
        ARect: TRect;
        AIndexRow: Integer;
        ACurrCoord: TBufferCoord;
        ASelectCoord: TBufferCoord;
        ASelectEndCoord: TBufferCoord;
        ASearchPos: integer;
        AOffset: integer;
        ASelectSize: integer;
        ARow: string;
        AOrgRow: string;
        AOrgText: string;
      begin
        inherited AfterPaint(ACanvas, AClip, AFirstRow, ALastRow);
        if (not Enabled) then exit;
        if (not Editor.SelAvail) then exit;
        if (Editor.SelectionMode <> smNormal) then exit;
        ASelectText := Editor.SelText;
        ASelectSize := Editor.SelLength;
        ASelectCoord := Editor.CharIndexToRowCol(Editor.SelStart);
        ASelectEndCoord := Editor.CharIndexToRowCol(Editor.SelEnd);
        if (ASelectCoord.Line <> ASelectEndCoord.Line) then exit;
// Выделение располагается в одной строке!!!
        ARow := Editor.Lines[ASelectCoord.Line - 1];
        if (WholeWordOnly and (not ASelectText.WordInRow(ASelectCoord.Char, ARow))) then exit;
// Выделение есть слово!!!
        AStoreFont := TFont.Create();
        try
          AStoreFont.Assign(ACanvas.Font);
          AStoreBrush := TBrush.Create();
          try
            AStoreBrush.Assign(ACanvas.Brush);
            if (Attribute.Background <> clNone) then
              begin
                ACanvas.Brush.Color := Attribute.Background;
                ACanvas.Brush.Style := bsSolid
              end
            else
              begin
                ACanvas.Brush.Style := bsClear;
              end;
// Внимание, очень важно: свойства ACanvas.Pen нельзя менять - иначе будут проб-
// лемы с отрисовкой CodeFolding!
            AFirstRow := Editor.TopLine;
            ALastRow := Editor.TopLine + Editor.LinesInWindow - 1;
            if (not CaseSensitivity) then
              ASelectText := ASelectText.UpperCase();
            for AIndexRow := AFirstRow to ALastRow do
              begin
                AOffset := 1;
                ARow := Editor.Lines[AIndexRow - 1];
                AOrgRow := ARow;
                if (not CaseSensitivity) then
                  begin
                    ARow := Editor.Lines[AIndexRow - 1].UpperCase();
                  end;
                while (true) do
                  begin
                    ASearchPos := System.Pos(ASelectText, ARow, AOffset);
                    if (ASearchPos <= 0) then break;
                    if ((ASearchPos = ASelectCoord.Char) and (AIndexRow = ASelectCoord.Line)) then
                      begin
                        AOffset := ASearchPos + ASelectSize;
                        continue;
                      end;
                    if (WholeWordOnly and (not ASelectText.WordInRow(ASearchPos, ARow))) then
                      begin
                        AOffset := ASearchPos + ASelectSize;
                        continue;
                      end;
                    AOrgText := System.Copy(AOrgRow, ASearchPos, ASelectSize);
                    ACurrCoord := BufferCoord(ASearchPos, AIndexRow);
                    ACurrPt := Editor.RowColumnToPixels(Editor.BufferToDisplayPos(ACurrCoord));
                    ARect := Rect(ACurrPt.X, ACurrPt.Y, ACurrPt.X + Editor.CharWidth * ASelectSize, ACurrPt.Y + Editor.LineHeight);
                    ACanvas.FillRect(ARect);
                    ACanvas.TextRect(ARect, ACurrPt.X, ACurrPt.Y, AOrgText);
                    AOffset := ASearchPos + ASelectSize;
                  end
              end;
            ACanvas.Brush.Assign(AStoreBrush);
          finally
            System.SysUtils.FreeAndNil(AStoreBrush);
          end;
          ACanvas.Font.Assign(AStoreFont);
        finally
          System.SysUtils.FreeAndNil(AStoreFont);
        end;
        Editor.InvalidateGutterLines(AFirstRow, ALastRow);
        Editor.InvalidateLines(AFirstRow, ALastRow);
      end;



или (альтернативный, кода больше....)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
      procedure TBlockMarker.AfterPaint(ACanvas: TCanvas; const AClip: TRect; AFirstRow, ALastRow: integer);
      var
        ABlockMarkup: TBlockMarkup;
      begin
        if (not Enabled) then exit;
// Рисуем то что нужно...
//        for ABlockMarkup in FMarkups do
//          begin
//            if (not ABlockMarkup.Check(Editor)) then continue;
//            ABlockMarkup.Draw(Editor, ACanvas);
//          end;
      end;



3. Инициализация
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
      procedure TfmEditDocument.FormCreate(Sender: TObject);
      begin
.............................
        ASelectTextMarkup := TSelectTextMarkupHighlighter.Create(edTextEdit);
        with ASelectTextMarkup do
          begin
            Attribute.Background := $008FA0EF; // $008FA0EF; // $00CFAAE7; // clYellow; // clMoneyGreen; //$0078AAFF; //$0078AAFF;
            Enabled := false;
          end;
        AMarkupBlocks := TBlockMarker.Create(edTextEdit);
        with AMarkupBlocks do
          begin
            Enabled := false;
          end;
......................
 end;    
...
Рейтинг: 0 / 0
04.11.2021, 18:27
    #40109300
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
kapas,

благодарю за ответ! К сожалению как вижу существует несколько форков SynEdit. Мой переработанный вариант основан на официальном sourceforge.net/projects/synedit/ (который мультиплатформенный под Delphi/Kylix). Пытался по простому интегрировать Ваш код в него - море всего не находит и в типах и в интерфейсе. Взять другой форк проблематично - так как много интегрировано собственных наработок в этот. Если есть время и желание - просьба подсказать пошагово сие внедрение. Увы без документации на интерфейсы SynEdit - равносильно это написать самому с нуля, чем внедрять то, что не внедряется.
Заранее благодарю если возникнет желание помочь.
...
Рейтинг: 0 / 0
05.11.2021, 07:15
    #40109336
kapas
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
DelDelphi, могу только более подробно прокомментировать код. Не сегодня... :-(
1. Сам работаю с версией https://github.com/SynEdit/SynEdit
2. Этом коде в основном все стандартное из TSynEdit. Отдельные функции можно дописать самому

Успехов.
...
Рейтинг: 0 / 0
05.11.2021, 15:51
    #40109416
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
DelDelphi,

посмотрите примеры кода отсюда, это не оно? ( https://forum.lazarus.freepascal.org/index.php?topic=19424.0 )
в смысле, если по событию "выделение" определить, какая часть текста выделена и передать её в SynEdit.SetHighlightSearch(...)
...
Рейтинг: 0 / 0
06.11.2021, 03:06
    #40109590
ma1tus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
не обязательно через search, не обязательно в плагине... отрисовкой только в видимых строках в его же обработчике; топорно, нативно, "на официальном"
...
Рейтинг: 0 / 0
06.11.2021, 07:33
    #40109596
kapas
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
ma1tus,
Можно и так :-) Дело вкуса.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
..........................
 if DoTransient then
  begin
    // plugins
    if FPlugins <> nil then
      for i := 0 to FPlugins.Count - 1 do
        TSynEditPlugin(FPlugins[i]).PaintTransient(Canvas, TransientType);
    // event
    if Assigned(FOnPaintTransient) then
    begin
      Canvas.Font.Assign(Font);
      Canvas.Brush.Color := Color;
      HideCaret;
      try
        FOnPaintTransient(Self, Canvas, TransientType);
      finally
        ShowCaret;
      end;
    end;
...
Рейтинг: 0 / 0
06.11.2021, 14:08
    #40109639
ma1tus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
kapas, ну да ) Привёл упрощенный.
С т.з. декомпозиции плагин предпочтительней
...
Рейтинг: 0 / 0
06.11.2021, 19:32
    #40109699
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Кроик Семён,

Это форум лазарус. Да, в нем все это сделано и работает. У меня как раз вопрос как это сделать в Delphi, не портируя горы лазарусовского кода. Задача усложняется тем, что нужна динамическая подсветка огромного числа кейвордов что под курсором где щелкнул пользователь. При этом листинги порой на пару мегабайт. В Lazarus реализовано с учетом этих вещей насколько я понял. То есть адаптивная подсветка по мере скролла (и также отмена подсветки старого кейворда), а не скопом всех мегабайт. Если реализовывать по простому - будет все жутко тормозить при щелчках пользователя с кейворда на кейворд, когда каждый встречается в листинге несколько сотен или тысяч раз (операнды и регистры ассемблера). А если начать щелкать быстрее - или повесит приложение или приведет к тормозам. Это не вариант.

Пока к сожалению все что вижу из советов - либо не потянет эту задачу или требует несколько дней на на внедрение/адаптацию и тестирование, учитывая что мой форк основан на SynEdit 2016 года + был полностью адаптирован под юникод (для продукта критичен корректный показ строк из иероглифов, строк справа налево и так далее со всем функционалом SynEdit. К сожалению взять другой форк не получится - много своих продуктозависимых вещей добавлено и исправлено. Мерджить десятки файлов и переписывать сотню функций - тестирования и отладки на месяц.
...
Рейтинг: 0 / 0
06.11.2021, 19:42
    #40109702
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
ma1tus,
kapas,
Вот это уже гораздо ближе, благодарю парни! Надо проверить на своей задаче. Отпишу.
...
Рейтинг: 0 / 0
06.11.2021, 19:50
    #40109704
DelDelphi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
ma1tus,

Благодарю! Именно то что искал!
...
Рейтинг: 0 / 0
23.11.2021, 21:43
    #40114375
SergSni
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
SynEdit и подсветка текущего выделенного слова по документу
Я как-то имел опыт использования PaintTransient и ...
Есть там ряд нюансов при рисовании. Например, надо следить чтобы не нарисовать на Gutter-e
А при перемещении курсора по строкам это событие всегда вызывается и как следствие все эти выделенные куски мигают при перерисовке. Мелочь, но неприятно и это я так и не победил
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / SynEdit и подсветка текущего выделенного слова по документу / 22 сообщений из 22, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]