GTK3 Interface Workshop

Zur Vorstellung von Komponenten und Units für Lazarus
Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

GTK3 Interface Workshop

Beitrag von theo »

Dieser Thread ist für den Austausch zum Thema GTK3 Interface gedacht.
Bitte hier nur konkrete, Code-bezogene Themen besprechen.
Philosophisches, Organisatorisches und Blabla kann man weiterhin hier anbringen.



@af0815: Ich bin kein Fan von Start-Bürokratie und Stuhlkreisen, welche nur allzu oft in sofortigen Projektleichen enden.
Zuerst sollte man ein Gefühl dafür bekommen, was überhaupt los ist und ob man Bock hat.

Ich mache mal ein konkretes Beispiel wie so ein Ablauf aussehen könnte.

- Mach mal ein neues Projekt und lege ein Synedit drauf. Dann wähle als LCLWidgetType "gtk3" und starte.
- Sieht Kacke aus, oder? Wo ist das Caret? (Text Cursor).
- Öffne mal lazarus/lcl/interfaces/gtk3/gtk3defines.inc und schalte GTK3DEBUGNOTIMPLEMENTED ein.
- Dann kompiliere wieder und schau, was auf der Konsole oder im Output Fenster steht. Ich sehe da u.A.
WARNING: TGtk3WidgetSet.CreateCaret not implemented ...
WARNING: TGtk3WidgetSet.SetCaretRespondToFocus not implemented ...
WARNING: TGtk3WidgetSet.SetCaretPosEx not implemented ...
WARNING: TGtk3WidgetSet.ShowCaret not implemented ...
WARNING: TGtk3WidgetSet.ExcludeClipRect not implemented ...
WARNING: TGtk3WidgetSet.HideCaret not implemented ...
WARNING: TGtk3WidgetSet.DestroyCaret not implemented ...
WARNING: TGtk3WidgetSet.SetROP2 not implemented ...
Also auf Deutsch: Es gibt kein Caret!
Jetzt macht man sich bei GTK3 schlau und sucht und sucht.
Ich habe nichts gefunden wie ein Caret API.
Dann schaut man bei LCL-GTK2 nach. Da ist alles höchstlich verwinkelt und complicirt, aber am Ende - wenn ich das richtig gesehen habe - malt das den Strich einfach selber.
OK, muss man wohl selber malen.
Wie machen wir das? Das könnte man jetzt besprechen und dann umsetzen.

Wenn wir das schaffen, dann haben wir zwar noch kein durchorganisiertes Projekt, aber wenigstens einen Cursor für Synedit. :D
Wenn wir das nicht schaffen, nützt alle Vorfeld-Bürokratie nichts.

Sieht du das nicht auch so?

S.A.
https://docs.gtk.org/gtk3/migrating-2to3.html
https://docs.gtk.org/gtk4/migrating-3to4.html

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Gtk3 Infos

Beitrag von af0815 »

theo hat geschrieben:
Do 15. Dez 2022, 13:42
Sieht du das nicht auch so?
Das ist ein Beispiel mit dem ich was anfangen kann.

Muss mir mal auf meinem 'sauberen' Debian 11 den letzten "main" herunterladen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: Gtk3 Infos

Beitrag von theo »

af0815 hat geschrieben:
Do 15. Dez 2022, 14:28
Das ist ein Beispiel mit dem ich was anfangen kann.

Muss mir mal auf meinem 'sauberen' Debian 11 den letzten "main" herunterladen.
Sehr gut! :D

Und ich knüpfe gleich noch daran an:
theo hat geschrieben:
Do 15. Dez 2022, 13:42
OK, muss man wohl selber malen.
Wie machen wir das? Das könnte man jetzt besprechen und dann umsetzen.
Ein grundsätzliche Frage hier ist, ob man auf diesem Level überhaupt die abstrakten LCL Klassen schon verwenden darf/soll/kann?
Also könnten wir uns eine von z.B. TGraphicControl abgeleitete TCaret Klasse basteln und diese dort verwenden, oder müssen wir das im GKT API Stil machen?
Das Gefühl sagt eher nein, allerdings sind Controls, Forms und Graphics durchaus in der Uses von gtk3int.pas vorhanden.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Gtk3 Infos

Beitrag von af0815 »

theo hat geschrieben:
Do 15. Dez 2022, 14:50
Ein grundsätzliche Frage hier ist, ob man auf diesem Level überhaupt die abstrakten LCL Klassen schon verwenden darf/soll/kann?
Also könnten wir uns eine von z.B. TGraphicControl abgeleitete TCaret Klasse basteln und diese dort verwenden, oder müssen wir das im GKT API Stil machen?
Das Gefühl sagt eher nein, allerdings sind Controls, Forms und Graphics durchaus in der Uses von gtk3int.pas vorhanden.
Vom Gefühl her, sollte man auf der Ebene bleiben und nicht Rekusionen in höheren Objekten provozieren. Controls, Forms und Graphics setzen ja auf das Widgetset auf.

Ich habe noch zuwenig dort hineingeschaut, muss mich erst etwas einlesen. Du hast da einen Vorsprung.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: Gtk3 Infos

Beitrag von theo »

af0815 hat geschrieben:
Do 15. Dez 2022, 14:57
Vom Gefühl her, sollte man auf der Ebene bleiben und nicht Rekusionen in höheren Objekten provozieren. Controls, Forms und Graphics setzen ja auf das Widgetset auf.
Ja, sehe ich (leider) auch so.
af0815 hat geschrieben:
Do 15. Dez 2022, 14:57
Ich habe noch zuwenig dort hineingeschaut, muss mich erst etwas einlesen. Du hast da einen Vorsprung.
Um meinen "Vorsprung" aufzuholen, brauchst du aber nicht lange lesen... :lol:

Aber ja, es schon so, dass man nicht nur die Lazarus-Interface-Seite verstehen muss sondern sich auch ein Stück weit in die GTK Welt einlesen muss.
Schliesslich wollen wir die zwei ja zusammenbringen.
Das ist schon anspruchsvoll.

Du meldest dich dann, wenn du dich "gewappnet" fühlst?

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: GTK3 Interface Workshop

Beitrag von af0815 »

wo finde ich die gdk-3 ? Die mekert er mir aktuell beim Linken an. Er findet -lgdk-3 nicht. Ich bin jetzt auf der suche nach libgdk-3 aber da findet er nichts, auch keine -dev. Nur ein Paket libgdk3.0-cil das gehört aber eher zum Mono Projekt (und dort ist es auch nicht drinnen).

Ach ja, mein System ist Debian BullsEye mit LXDE Desktop und sehr schlank aufgesetzt.
Hint: (11030) Start of reading config file /home/andi/data/lazdev/trunk_gtk/fpc/bin/x86_64-linux/fpc.cfg
Hint: (11031) End of reading config file /home/andi/data/lazdev/trunk_gtk/fpc/bin/x86_64-linux/fpc.cfg
Free Pascal Compiler version 3.3.1-12185-g725da25477 [2022/12/13] for x86_64
Copyright (c) 1993-2022 by Florian Klaempfl and others
(1002) Target OS: Linux for x86-64
(3104) Compiling testsynedit.lpr
(9022) Compiling resource /home/andi/data/testprojects/synedit/lib/x86_64-linux/testsynedit.or
(9015) Linking /home/andi/data/testprojects/synedit/testsynedit
/usr/bin/ld: cannot find -lgtk-3
/usr/bin/ld: cannot find -lgdk-3
/home/andi/data/testprojects/synedit/testsynedit.lpr(24,1) Error: (9013) Error while linking
/home/andi/data/testprojects/synedit/testsynedit.lpr(24,1) Fatal: (10026) There were 1 errors compiling module, stopping
Fatal: (1018) Compilation aborted
Error: /home/andi/data/lazdev/trunk_gtk/fpc/bin/x86_64-linux/ppcx64 returned an error exitcode
Edit:
sudo apt install libgtk-3-dev

machts wieder gut.

Edit2:
testsynedit:4259): Gtk-[1;33mWARNING[0m **: [34m16:58:22.677[0m: Theme parsing error: <broken file>:1:0: Failed to import: Fehler beim Öffnen der Datei »/home/andi/data/testprojects/synedit/theme.css«: Datei oder Verzeichnis nicht gefunden
WARNING: TGtk3WidgetSet.ShowWindow not implemented ...
Focused
GtkEventResize: Form1:TForm1 Send=0 x=193 y=273 w=200 h=200
GtkEventResize: Form1:TForm1 Send=1 x=47 y=128 w=200 h=200
GtkEventResize: Form1:TForm1 Send=1 x=193 y=273 w=200 h=200
WARNING: TGtk3WidgetSet.CreateCaret not implemented ...
WARNING: TGtk3WidgetSet.SetCaretRespondToFocus not implemented ...
WARNING: TGtk3WidgetSet.SetCaretPosEx not implemented ...
WARNING: TGtk3WidgetSet.ShowCaret not implemented ...
GtkEventResize: Form1:TForm1 Send=1 x=193 y=273 w=200 h=200
GtkEventResize: Form1:TForm1 Send=1 x=193 y=273 w=200 h=200
ok, ich kann es mal laufen lassen.

Edit3:
Schau mal in QT5 rein, da wird das Caret scheinbar auch in QtCaret.pas behandelt.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: GTK3 Interface Workshop

Beitrag von theo »

af0815 hat geschrieben:
Do 15. Dez 2022, 16:42
Edit3:
Schau mal in QT5 rein, da wird das Caret scheinbar auch in QtCaret.pas behandelt.
Ja, das ist interessant. Nimmt ganz schön viel "Platz" ein im Code, dieses Caret.

Es gibt bei GTK2 etwas, was für uns vielleicht noch näher ist:
gtk2winapiwindow.pp "A GTK widget to support controls derived from a wincontrol".
Dort wird das Caret für GTK2 letztlich behandelt.
So ganz verstehe ich aber die Motivation für "GTKAPIWidget" noch nicht.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: GTK3 Interface Workshop

Beitrag von Warf »

Ein bisschen ist natürlich die Frage was schon da ist und was Fehlt. Z.B. was den Caret angeht, wenn man den Selbst Zeichnen muss, kann man sich ja mal anschauen was für Zeichenroutinen schon vorhanden sind.

Alle Controls sind TGTK3Widgets, die haben die Funktion DoBeforeLCLPaint, genau dort kann man eigene Zeichenroutinen einbauen. Zum zeichnen kann man den TGTK3DeviceContext benutzen, welcher die Grundlegenden Zeichenprimitiven bereitstellt. Ein beispiel hierfür ist die bereits bestehende Panel Implementation:

Code: Alles auswählen

procedure TGtk3Panel.DoBeforeLCLPaint;
var
  DC: TGtk3DeviceContext;
  NColor: TColor;
begin
  inherited DoBeforeLCLPaint;
  if not Visible then
    exit;

  DC := TGtk3DeviceContext(FContext);

  NColor := LCLObject.Color;
  if (NColor <> clNone) and (NColor <> clDefault) then
  begin
    DC.CurrentBrush.Color := ColorToRGB(NColor);
    DC.fillRect(0, 0, LCLObject.Width, LCLObject.Height);
  end;

  if BorderStyle <> bsNone then
  begin
    DC.CurrentPen.Color := ColorToRGB(clBtnShadow); // not sure what color to use here?
    DC.drawRect(0, 0, LCLObject.Width, LCLObject.Height, False, True);
  end;
end;   
Eine entsprechende Implementation für den Caret würde dann vermutlich so aussehen:

Code: Alles auswählen

procedure TGtk3Editable.DoBeforeLCLPaint; // Klasse von der alle edit artigen widgets abstammen
var
  DC: TGtk3DeviceContext;
  CaretPosition: Integer;
  CaretHeight: Integer;
begin
  inherited DoBeforeLCLPaint;
  if not Visible then
    exit;

  DC := TGtk3DeviceContext(FContext);
  CaretPosition := TextWidth(DC.CurrentFont, Self.Text.Substring(0, CaretPos));
  CaretHeight := GetFontSize(DC.CurrentFont);
  DC.MoveTo(CaretPosition.X, CaretPosition.Y, nil);
  DC.LineTo(CaretPosition.X, CaretPostion.Y + CaretHeight);
end;
Das meiste ist schon da, allerdings fehlt aber noch an ein paar Stellen. Um genau zu sein das Ausrechnen der Textwidth und der Height. Beides müsste über das Pango Layout von TGTK3Font eigentlich recht einfach sein, ist aber (soweit ich jetzt in den 20 minuten die ich das angeschaut habe), noch nicht implementiert.

Wenn man das wirklich kollaborativ machen möchte, denke ich sollte man das strukturiert aufziehen, indem man erst mal eine sehr high level liste macht was alles fehlt, und dann unter die haube schaut was fehlt um das zu verwirklichen.
Das könnte man z.B. mit einem Git Repository auf Gitlab oder Github machen, indem man Issues für alles was Fehlt eröffnet, sodass man da direkt sehen kann was wurde bereits identifiziert, und evtl auch wer woran arbeitet.

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: GTK3 Interface Workshop

Beitrag von theo »

@Warf: Danke für den Tipp, das schaue ich mir an. Mir ist nur etwas dazwischen gekommen.
https://docs.gtk.org/gtk3/iface.Editable.html
Es gibt viel zu entdecken... :wink:

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: GTK3 Interface Workshop

Beitrag von Warf »

Was mich nur ein wenig wundert, entry in GTK haben ja schon einen cursor, also ist die Frage warum es die bei Lazarus nicht gibt.

Wenn ich ein gtk_entry_new erzeuge funktioniert das ja out of the box, letztenendes macht das TGTK3Entry widget im gtk3 widgetset ja nix anderes. Es hat vermutlich einen guten grund, nur muss man den erst einmal rausfinden.

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: GTK3 Interface Workshop

Beitrag von theo »

@Warf: Der Haken ist wohl, dass Synedit nicht von einem TGtk3Editable abstammt. Es ist ein komplettes CustomControl.
Man bräuchte ein "losgelöstes" Caret, welches man unabhängig von der Klassenstruktur benutzen kann, wie es offenbar bei Windows ist:
https://learn.microsoft.com/en-us/windo ... reatecaret
Ansonsten ist wohl selber zeichnen angesagt.
Am Ende soll ja TGtk3WidgetSet.CreateCaret etc. implementiert werden.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: GTK3 Interface Workshop

Beitrag von af0815 »

Soweit ich das bisher sehe (mal in gtk2/Qt5 hineingeschaut) so ist der Cursor nichts anderes wie eine Bitmap, die als Sprite funktioniert. Das macht auch Sinn, weil der Cursor = Caret, ja je nachdem seine Gestalt ändern können sollte. So wie es ausieht wird in QT5 sich an die Entsprechung von WIndows angelehnt. Weil in QT5 wird da auf ein EmulatedCaret in QTCaret zurückgegeriffen.

Die Frage ist, gibt es in gtk3 eine Entsprechung für das Caret oder nicht. Wenn nicht, so wird man auf eine Emulation wie bei QT zurückgreifen müssen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: GTK3 Interface Workshop

Beitrag von Warf »

Ach das ist kein GTK editable, dann ist das klar das man es dann selbst zeichnen muss.

Wundert mich aber dann, da das anscheinend auch bei gtk2 und qt der Fall ist, das man das dann nicht als option im TSynEdit package einbaut statt immer die selbe lösung pro widgetset zu bauen
Aber grundsätzlich sollte das dann recht einfach sein da es die ganzen zeichenprimitiven schon gibt

Benutzeravatar
theo
Beiträge: 10468
Registriert: Mo 11. Sep 2006, 19:01

Re: GTK3 Interface Workshop

Beitrag von theo »

Warf hat geschrieben:
Sa 17. Dez 2022, 21:50
Wundert mich aber dann, da das anscheinend auch bei gtk2 und qt der Fall ist, das man das dann nicht als option im TSynEdit package einbaut statt immer die selbe lösung pro widgetset zu bauen
Es mag andere Komponenten geben, die auch CreateCaret etc. benutzen.
Dann kann man die Frage umdrehen. Wieso soll jede Komponente ein eigenes Caret basteln? :wink:

Man muss das ja historisch betrachten.
Damit möglichst viel Delphi-Zeug ohne weiteres läuft, hat man Winapi-Kompatibilitäts Code für andere Systeme hinzugefügt (qtwinapi.inc, gtk2winapi.inc ...).
Zu diesen APis gehört auch CreateCaret, GetCaretPos etc.

Synedit war ja auch zuerst eine Delphi Komponente. Ursprünglich war es mwEdit von Martin Waldenburg.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6200
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: GTK3 Interface Workshop

Beitrag von af0815 »

theo hat geschrieben:
So 18. Dez 2022, 00:06
Es mag andere Komponenten geben, die auch CreateCaret etc. benutzen.
Dann kann man die Frage umdrehen. Wieso soll jede Komponente ein eigenes Caret basteln? :wink:
Man bastelt wie bei QT5 ein allgemeine Version davon, nichts was speziell für Synedit ist und verwendet die Klasse wo man sie braucht. Ich bin gerade dabei mir die Sache mit vergleichender Verhaltensforschung tiefer anzusehen.
Das heisst ischaue mir gerade mal folgendes an
WARNING: TGtk3WidgetSet.CreateCaret not implemented ...
WARNING: TGtk3WidgetSet.SetCaretRespondToFocus not implemented ...
WARNING: TGtk3WidgetSet.SetCaretPosEx not implemented ...
WARNING: TGtk3WidgetSet.ShowCaret not implemented ...
WARNING: TGtk3WidgetSet.ExcludeClipRect not implemented ...
WARNING: TGtk3WidgetSet.HideCaret not implemented ...
WARNING: TGtk3WidgetSet.DestroyCaret not implemented ...
Wobei einmal der Focus auf CreateCaret und DestroyCaret liegt. Weil für den Rest muss ich begreifen wie ich da auf die Verwaltungsstrukturen zugreife. Besonders die Zurordnung HWND zu Gtk3Widget.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Antworten