WOPR Talk

Rund um die LCL und andere Komponenten
pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Toll. Dann wird es vermutlich in einiger Zeit mehrer Lösungen geben, die man nutzen kann.

Darauf habe ich gewartet.... Aber trotzdem werde ich an meiner eigenen "Version" weiter machen(zwischendurch) allerdings wird die dann wohl kein RTF unterstützen.

Was heißt eigentlich "siehe Revision 11268" wo steht sowas ?
MFG
Michael Springwald

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

Beitrag von theo »

pluto hat geschrieben:Toll. Dann wird es vermutlich in einiger Zeit mehrer Lösungen geben, die man nutzen kann.
Wie kommst du drauf?

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

Re: WOPR Talk

Beitrag von theo »

Habe heute nach langer Pause wieder mal an WOPR weitergebastelt.

Es gibt jetzt ein vernünftig funktionierendes Undo-Redo System.
Während das jetzige Undo sehr Speicher-ökonomisch arbeitet ist Redo ein bisschen ein Speicherfresser.
Redo speichert Momentan der Einfachheit halber das ganze Dokument.
Das ist aber nicht so schlimm wie es klingt, denn Redo hat eine kurze Lebenszeit.
Während auf den Undo Stack bei jeder Operation geschrieben wird, auch beim Buchstaben eintippen, kommt Redo nur ins Spiel, wenn ein Undo (CTRL-Z) ausgelöst wird. Wird wieder eine andere Operation als Undo-Redo ausgeführt wird der Redo-Stack gelöscht.
Ich glaube, das ist im Moment vertretbar, denn es gibt noch viel anderes zu Tun.
Ein Undo (mit Speichern des Redo) dauert bei meinem grossen Test-Dokument von 240 A4-Seiten (also schon ein rechtes Buch, alles in Memory und inklusive Rendering des ganzen Dokuments und Zeichnen) bei mir 700 ms. Bei kleineren Texten < 50 A4 Seiten, was etwa die Absicht ist, flutscht's nur so.

Das ganze ist nicht soo einfach wie es scheinen Mag, denn WOPR arbeitet auf einem Baum von Elementen, also nat. nicht nur Strings.
Probleme bei Undo/Redo sind:
Wenn ich z.B. etwas markiertes aus dem Text lösche (das kann ein Buchstabe, das ganze Dokument, oder mehrere Absätze mit Bildern und Tabellen sein) so muss eine Kopie dieses Teilbaumes auf den Undo-Stack.
Damit das überhaupt noch beherrschbar ist, muss ich immer mindestens ein Document-RootChild, also ein Absatz oder eine Tabelle in den Stack kopieren. Da die zu löschende Selektion aber auch nur einen Teil der Absätze ausmachen kann, müssen beim Undo diese ganzen Absätze erst gelöscht und mit dem Teilbaum des Undo Elements ersezt werden.
Über mehrere Operationen hinweg, kann man deshalb nicht mehr die Pointer speichern, wo eingefügt werden muss (da diese Flöten sind) sondern muss mit Dokumenten-Indizes Arbeiten, um die Position wiederzufinden.
Zusätzlich muss noch die Cursor und die Markierungs-Start- und End Position wiederhergestellt werden.

Wenn nun tatsächlich eine Undo Operation (CTRL-Z) ausgelöst wird, so muss ein neues Redo Item auf den Stack, welches den vorherigen Zustand speichert, und zusätzlich muss das Undo Item in diesem Redo gespeichert werden, damit nach dem Redo wieder ein Undo gemacht werden kann. Das Undo-Item wird dann ge-popt und Umgekert das Redo-Item.

Also eine Arbeit, die viel Bier erfordert. ;-)

Zu meinem eigenen Erstaunen funktioniert WOPR scheint's immer noch ohne Speicherlecks:

Heap dump by heaptrc unit
1157341 memory blocks allocated : 44083484/48296664
1157341 memory blocks freed : 44083484/48296664
0 unfreed memory blocks : 0

Wollte nur mal wieder berichten.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: WOPR Talk

Beitrag von Christian »

Schön das man mal wieder was davon hört, hattes schon fast abgeschrieben.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: WOPR Talk

Beitrag von pluto »

Redo speichert Momentan der Einfachheit halber das ganze Dokument.
Warum das ganze Dokument ? das Redo kannst du doch genauso machen wie das Undo... nur halt anders herum.
Das ganze ist nicht soo einfach wie es scheinen Mag
Jetzt verstehe ich wo das Problem liegt. Warum hast du das denn "so" Kompliziert gemacht ?
Test-Dokument von 240 A4
Deine Test Ergebnisse sind doch Vielversprechend.
Wie kommst du drauf?
Diese Antwort von dir habe ich wohl übersehen.... Ganz einfach: Weil dieses Thema "gerade" in ist. Im DelphiGl reden wir über so ein Thema.
Ich versuche selbst mit meinem PLEditor sowas in "klein" fertig zu bekommen. Das ist für mein "ersteunen" auch schon recht gut gelungen. Es gibt zwar noch einige kleinere Fehler aber nicht der Rede wert. Für den Nachfolge mache ich auch schon einige kleinere Test und Experimente.

Wobei unsere Ziele natürlich weit auseinander gehen. Naja, im Moment aufjedenfall. Wenn bei mein Nachfolger Projekt alles gut geht werde ich mal schauen ob ich mir zu erst ein eigenes Format erstelle, oder auf ein vorhandenes aufbaue.
Aber mal sehen.

Aufjedenfall finde ich das Thema recht Interessant und auch Spanend. Gerade im DelphiGL Forum, diskutieren wir sehr ausgiebig über genau dieses Thema: http://www.delphigl.com/forum/viewtopic ... 02&start=0" onclick="window.open(this.href);return false;
Darum. glaube ich das es "bald", wobei bald einige Jahre dauern könnte, bedeutet, es verschiedene ansetzte in dieser Richtung geben könnte.
MFG
Michael Springwald

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

Re: WOPR Talk

Beitrag von theo »

pluto hat geschrieben: Warum hast du das denn "so" Kompliziert gemacht ?
Meinst du mit dem Baum?
Weil es einfach auf der Hand liegt. Wie soll's denn sonst gehen?
Wenn man das objektmässig und hierarchisch ablegen will, sehe ich keinen besseren Weg.
Ausserdem sind ja viele modernere Strukturen so. z.B. HTML-, XML- DOM, OpenOffice ...
s.A. http://de.wikipedia.org/wiki/Document_Object_Model" onclick="window.open(this.href);return false;

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: WOPR Talk

Beitrag von Christian »

frag doch lieber nicht.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

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

Re: WOPR Talk

Beitrag von theo »

Hirnprobleme

Hat jemand Lust zu denken? Nein? War mir schon klar. ;-)
Vielleicht schreibe ich folgendes nur, um mir selber darüber klar zu werden.

Ich stosse gerade an die Grenzen meines Abstraktionsvermögens.

Es geht um Tabellen, namentlich Rowspan.
Vielleicht ist die HTML Darstellung am klarsten zum zeigen worum's geht:

Sowas:

Code: Alles auswählen

<table>
   <tr>
      <td rowspan="2">c1</td>
      <td>c2</td>
      <td>c3</td>
      <td>c4</td>
    </tr>
    <tr>
      <!--<td>d1</td>-->
      <td>d2</td>
      <td>d3</td>
      <td>d4</td>
    </tr>
</table>
...veranlasst die Tabelle in HTML Beschreibung, die erste Zelle über zwei Reihen zu spannen.

also etwa (kann man hier nicht richtig darstellen):

Code: Alles auswählen

c2 c3 c4
c1
     d2 d3 d4
In meiner Lösung, hält die Tabelle eine "WidthsList". Diese wird vorgängig korrekt erstellt, aus den z.B. HTML Daten. Dabei werden auch Colspan und Rowspan berücksichtigt. Im ersten Schritt handelt es sich um eine Normalisierung der HTML Daten (dort kann ja jede Zelle ein Width Attribut haben, aber der Sinn der Tabelle ist ja, dass alle Spalten gleich breit sind: Der letzte gewinnt.).
Danach werden die konkreten Breiten verteilt. Je nachdem ob diese Prozentual zur verfügbaren Breite, in Pixel oder gar nicht definiert sind.
Im letzteren Falle werden die berechnneten Inhaltsbreiten auf den verfügbaren Platz verteilt (MinMax).

Nun weiss ich also die Pixelbreiten der Spalten.

Jetzt muss ich diese auf die Elemente anwenden, etwa so:

Im Kontext TTable:

Code: Alles auswählen

for i:=0 to childNodes.length-1 do
begin
 if childNodes.item(i) is TTableRow then
   begin
     ARow:=TTableRow(childNodes.item(i));
     for j:=0 to ARow.childNodes.length-1 do
       begin
         if ARow.childNodes.item(j) is TTableCell then
          begin
           TTableCell(ARow.childNodes.item(j)).ItemRect:=.......
          end;
       end;
   end;
end;
Nun besteht die WidthsList aus Records die neben dem Wert und dem Typ (90%, 200px, -1undefiniert) auch eine (Lauf-)Variable RowspanRun hält.
Wenn nun eine Zelle der jew. aktuellen Reihe einen Rowspan1 enthält, wird der RowspanRun der entsprechenden Spalte in der WidthsList gesetzt.
Dann weiss man bei der nächsten Reihe grundsätzlich, welche Spaltenzelle als Objekt NICHT VORHANDEN!! ist.
Mein Haken ist nun ein ziemlich doofer: Ich weiss nicht, ob ich über die WidthsList oder über die RowChilds loopen soll.
Beides ist irgendwie falsch. Ich kann kein Child abholen, welches nicht da ist, oder das jew. Child muss nicht dem zugehörigen WidhtsList Eintrag entsprechen.

Die Lösung ist wahrscheinlich eine Count Variable, die von RowspanRun gesetzt wird.

Nixfürungut. Wenn jemand DIE Idee hat: immer her damit.

Wie auch immer: HTML-Tabellen sind schwierig zu rendern und daher auch etwas langsam. Von den Zellenhöhen haben wir jetzt noch nicht gesprochen.... ;-)

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Re: WOPR Talk

Beitrag von Christian »

Ist doch eigentlich egal, markiere die Zellen die nicht gerendert werden sollen einfach mit einem Boolean. Über was du dann loopst ist egal. Wobei ich die RowChilds als sauberere Lösung ansehen würde.
Zum Thema langsam, das kannst du Teilweise vermeiden indem du bei fester Dokumentgrösse der tabelle eine fixe grösse verpasst. Bei dynamischer Dokumentgrösse so wie in HTML musst dus natürlich so lassen.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

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

Re: WOPR Talk

Beitrag von theo »

Christian hat geschrieben:Ist doch eigentlich egal, markiere die Zellen die nicht gerendert werden sollen einfach mit einem Boolean. Über was du dann loopst ist egal. Wobei ich die RowChilds als sauberere Lösung ansehen würde.
Naja, ganz so einfach ist es nicht. Es gibt diese Zellen(-Objekte) ja gar nicht und sie hätten auch keinen Inhalt.
Man könnte dort "künstlich" Zellen einfügen, aber das löst das Problem nicht.
Ich bin aber an einer Lösung dran.... ;-)
Christian hat geschrieben: Zum Thema langsam, das kannst du Teilweise vermeiden indem du bei fester Dokumentgrösse der tabelle eine fixe grösse verpasst. Bei dynamischer Dokumentgrösse so wie in HTML musst dus natürlich so lassen.
Stimmt teilweise. Wenn man aber das HTML-Modell verfolgt, gibt immer noch die Tatsache, dass eine Spalte mindestens so breit ist, wie das längste nicht-trennbare Wort oder ein Bild in einer Zelle. Deshalb muss man hier trotzdem den Inhalt "ausmessen".

Antworten