schon seit Tagen versuche ich einen "Automatischen Zeilenumbruch Funktion" in meine "Text Engine" einzubauen. Aber alle meine versuche bisher waren nicht erfolgreich. Das Konzept habe ich mir grob gesehen so vorgestellt:
01) Ich erzeuge im Moment per Default einen Extra "Default Container" in jeder Zeile, später kann das noch optimiert werden.
02) Wenn es schon ein "Default Container" gibt, und dort Einträge vorhanden sind, werden sie gelöscht
03) Jetzt wird geschaut, ob das Objekt in die Zeile passt oder nicht. Wenn ja, wird es in die Zeile hinzugefügt, wenn nein wird es umgebrochen, dabei
04) wird geschaut, wie viel vom Objekt noch in die Aktuelle Zeile passt.
05) Später: Soll hier noch geschaut werden, wenn das Word nicht mehr rein passt in die Zeile, wie viel Buchstaben vom Aktuellen Word noch rein gehen.
Im Moment erkenne ich ein Word nur daran, das es mit einem "Leerzeichen" endet, später kann das noch verbessert werden.
Das Problem ist jetzt folgendes: Ob einer gewissen Größe, wird Falsch Umgebrochen, gerade bei mehren Objekten in der Zeile.
Es sind im Prinzip nur zwei arten von Objekten betroffen: Das "Text Objekt" und später das "Link Objekt".
Sollte jemand Probleme haben, das zu verstehen, was ich hier geschrieben habe einfach nach Fragen. Das Konzept ist etwas Kompliziert, aber bietet Praktische Vorteile.
Eventuell hilft auch dieses Bild weiter: http://forge.lazarusforum.de/wiki/textengine/imagelist3" onclick="window.open(this.href);return false;
Dort versuche ich den Groben Aufbau eines Dokumentes, in meiner "Text Engine" zu erklären.
Bevor ich es Vergesse hier ein noch der Komplette Soruce-Code der Funktion:
Code: Alles auswählen
procedure TPLTE_Container_Line.InitPosSizeItems(const NewSize:Boolean = True);
var
i, x,x1,x2, px, py,px2,m,pw,pw2,pw3,pw4,c:Integer;
str,LineText,LineText1,LineText2:String;
df2:TPLTE_Container_Default;
Line:TPLTE_Container_Line;
Obj:TPLTE_ObjectSTD_Text;
AutoBreakLine:Boolean;
procedure iAddContainer;
begin
if (not Assigned(df)) and (Visible) then begin
Name:='Line0';
df:=df2.AddNewDefaultContainer;
df.Style.Assign(df2.Style);
df.Style.Border.B.Color:=pl_red1;
df.Align:=CA_None;
df.VS.Visible:=False; df.HS.Visible:=False;
df.Visible:=False;
df.Left:=Left;
df.Top:=py;
df.Name:='DF';
df.Width:=Width;
df.Visible:=False;
Visible:=False;
end
else
df.Visible:=False;
end; // iAddContainer
begin
df2:=TPLTE_Container_Default(Parent);
pw:=0; LineText:='';
px:=Left+2; py:=Top+3; Height:=GetLineHeight+5; x:=0; x2:=1; m:=0; px2:=0;
// Vorhandene Objekte im Temp. Continaer Löschen, aber nur
// wenn sich die Anwendung nicht im Lade zustand befindet oder
// der Temp Container(df) nicht installisiert ist.
if (not df2.NoLoad) and (Assigned(df)) then begin
df.Visible:=False;
df.fContainerList.OwnsObjects:=False;
for i:=df.Count-1 downto 0 do begin
if TObject(df.fContainerList[i]) is TPLTE_Container_Line then begin
df.fContainerList.Remove(df.Items_Line[i]);
// df.Items_Line[i].Destroy;
end;
// df.fContainerList.Delete(i);
end;
df.fContainerList.Clear;
end;
// Zunächst wird alles in eine Zeile gepackt bis sie "voll" ist
// dann wird sie zum Temp. Conatiner(DF) hinzugefügt und eine neue
// wird erzeugt
if Name <> 'Test' then begin
iAddContainer;
Line:=df.AddNewLine;
Line.df:=df;
Line.Name:='Test';
// Line.Visible:=True;
end;
if df2.ClientWidth > 0 then begin
LineText2:='';
for i:=0 to Count-1 do begin
if items[i] is TPLTE_ObjectSTD_Text then begin
LineText:=''; str:=''; LineText1:=''; x1:=0; str:=''; LineText2:='';
items[i].Left:=px; items[i].Top:=py;
Items_Text[i].Style.ToCanvas(Canvas); x:=0;
pw:=Canvas.TextWidth(Items_Text[i].Text);
if Name <> 'Test' then begin
if (px+pw+10 >=df2.ClientWidth) then begin
pw2:=0; x:=0; px2:=px; pw:=0; x2:=0; LineText:='';
LineText1:=Items_Text[i].Text; pw4:=0;
repeat
x1:=PosEx(' ',LineText1,x+1);
str:=Copy(LineText1,x+1,(x1-(x)));
pw2:=Canvas.TextWidth(str);
// Der Rest, wird in eine Extra Variable kopiert. Damit das in eine Schleife wider holt werden kann.
LineText2:=Copy(LineText1,x,Length(LineText1)-x);
pw3:=Canvas.TextWidth(LineText2);
// writeln(str,'|',px2+pw2,'|',Width,'|',LineText2,'|',x,'|',x1,'|',LineText1);
if x1 = 0 then writeln(LineText);
if ((px2+pw2 >= Width) and (LineText <> '')) or (x1 = 0) then begin
pw4:=Canvas.TextWidth(LineText);
if (px2 >=Width) or (x1=0) then begin
Line:=df.AddNewLine;
Line.Name:='Test';
Line.df:=df;
pw4:=-2;
end;
Line.AddText(LineText).Style.Assign(Items_Text[i].Style);
if (pw4 <> -2) and (x1 > 0) then begin
Line:=df.AddNewLine;
Line.Name:='Test';
Line.df:=df;
end;
// GANZ wichtig: Damit der Rest ebenso behandelt werden kann, wird er mit Line Text gleich gesetzt.
LineText1:=LineText2;
LineText:='';
x:=0;
// if x1 > 0 then
px2:=left;
// if x1 > 0 then begin
Continue;
// end
end;
LineText:=LineText+str;
px2:=px2+pw2;
x:=x1;
until x1 = 0;
end
else
Line.fItems.Add(Items_Text[i]);
end;
px:=px+pw-10;
end;
end; // for i
end;
if (Assigned(df)) and (NewSize) then begin
df.Visible:=True;
df.InitPosSizeItems(False);
end;
NoInit:=False;
end; // TPLTE_Container_Line.InitPosSizeItems
die Mehtode "df.InitPosSizeItems" unterscheidet sich von der "TPLTE_Container_Line.InitPosSizeItems" in sehr vielen Punkten.
Zum Schluss noch ein "Screenshot". Die Scrolleisten, haben im Moment noch keine Funktion. Sie sind einfach nur "da".
Ich hoffe ihr könnt mir weiter helfen. Ich sehe einfach den Fehler nicht den ich mache. Ich hoffe der Soruce-Code ist euch klar, wie er Funktioniert.
Wenn jemand Lust hat: Ich könnte auch den Kompletten Soruce-Code der Engine hoch laden so könnte ihr "eure" Ideen gleich ausprobieren. Ich komme an diese Stelle einfach nicht mehr weiter.
PS: Habe den Titel geändert, weil sonst das (gelöst) nicht mehr rein passte. Schön währe eine "CheckBox" dafür.