UWindow
Class UWindowDynamicTextArea

source: e:\games\UnrealTournament\UWindow\Classes\UWindowDynamicTextArea.uc
Core.Object
   |
   +--UWindow.UWindowBase
      |
      +--UWindow.UWindowWindow
         |
         +--UWindow.UWindowDialogControl
            |
            +--UWindow.UWindowDynamicTextArea
Direct Known Subclasses:UWindowConsoleTextAreaControl, UWindowHTMLTextArea, UWindowURLTextArea

class UWindowDynamicTextArea
extends UWindow.UWindowDialogControl


Variables
 Font AbsoluteFont
           Assumes !bTopCentric, !bScrollOnResize
 int Count
           Assumes !bTopCentric, !bScrollOnResize
 float DefaultTextHeight
 int Font
           Assumes !bTopCentric, !bScrollOnResize
 UWindowDynamicTextRow List
           Assumes !bTopCentric, !bScrollOnResize
 int MaxLines
 OldW, OldH
           Assumes !bTopCentric, !bScrollOnResize
 class RowClass
           Assumes !bTopCentric, !bScrollOnResize
 color TextColor
           Assumes !bTopCentric, !bScrollOnResize
 UWindowVScrollBar VertSB
           Assumes !bTopCentric, !bScrollOnResize
 int VisibleRows
           Assumes !bTopCentric, !bScrollOnResize
 float WrapWidth
           Assumes !bTopCentric, !bScrollOnResize
 bool bAutoScrollbar
 bool bDirty
           Assumes !bTopCentric, !bScrollOnResize
 bool bHCenter
 bool bScrollOnResize
 bool bTopCentric
 bool bVCenter
 bool bVariableRowHeight
           Assumes !bTopCentric, !bScrollOnResize


Function Summary
 UWindowDynamicTextRow AddText(string NewLine)
 void BeforePaint(Canvas C, float X, float Y)
 UWindowDynamicTextRow CheckMaxRows()
 void Clear()
 void Created()
 float DrawTextLine(Canvas C, UWindowDynamicTextRow L, float Y)
     
///////////////////////////////////////////////////////
// Functions to override to change format/layout
///////////////////////////////////////////////////////
 int GetWrapPos(Canvas C, UWindowDynamicTextRow L, float MaxWidth)
     
// find where to break the line
 void Paint(Canvas C, float MouseX, float MouseY)
 void RemoveNextWord(out string, out string)
 void RemoveWrap(UWindowDynamicTextRow L)
 void SetAbsoluteFont(Font F)
 void SetFont(int F)
 void SetTextColor(Color C)
 UWindowDynamicTextRow SplitRowAt(UWindowDynamicTextRow L, int SplitPos)
 void TextAreaClipText(Canvas C, float DrawX, float DrawY, string S, optional bool)
 void TextAreaTextSize(Canvas C, string Text, out float, out float)
 void WordWrap(Canvas C, bool bForce)
 void WrapRow(Canvas C, UWindowDynamicTextRow L)



Source Code


00001	class UWindowDynamicTextArea expands UWindowDialogControl;
00002	
00003	var config int MaxLines;
00004	
00005	var bool bTopCentric;
00006	var float DefaultTextHeight;
00007	var bool bScrollOnResize;
00008	var bool bVCenter;
00009	var bool bHCenter;
00010	var bool bAutoScrollbar;
00011	var bool bVariableRowHeight;	// Assumes !bTopCentric, !bScrollOnResize
00012	var float WrapWidth;
00013	
00014	// private
00015	var UWindowDynamicTextRow List;
00016	var UWindowVScrollBar VertSB;
00017	var float OldW, OldH;
00018	var bool bDirty;
00019	var int Count;
00020	var int VisibleRows;
00021	var int Font;
00022	var Font AbsoluteFont;
00023	var color TextColor;
00024	var class<UWindowDynamicTextRow> RowClass;
00025	
00026	function Created()
00027	{
00028		Super.Created();
00029	
00030		VertSB = UWindowVScrollbar(CreateWindow(class'UWindowVScrollbar', WinWidth-12, 0, 12, WinHeight));
00031		VertSB.bAlwaysOnTop = True;
00032	
00033		Clear();
00034	}
00035	
00036	function Clear()
00037	{
00038		bDirty = True;
00039	
00040		if(List != None)
00041		{
00042			if(List.Next == None)
00043				return;
00044			List.DestroyList();
00045		}
00046	
00047		List = new RowClass;
00048		List.SetupSentinel();
00049	}
00050	
00051	function SetAbsoluteFont(Font F)
00052	{
00053		AbsoluteFont = F;
00054	}
00055	
00056	function SetFont(int F)
00057	{
00058		Font = F;
00059	}
00060	
00061	function SetTextColor(Color C)
00062	{
00063		TextColor = C;
00064	}
00065	
00066	function TextAreaClipText(Canvas C, float DrawX, float DrawY, coerce string S, optional bool bCheckHotkey)
00067	{
00068		ClipText(C, DrawX, DrawY, S, bCheckHotkey);	
00069	}
00070	
00071	function TextAreaTextSize(Canvas C, string Text, out float W, out float H)
00072	{
00073		TextSize(C, Text, W, H);
00074	}
00075	
00076	function BeforePaint( Canvas C, float X, float Y )
00077	{
00078		Super.BeforePaint(C, X, Y);
00079	
00080		VertSB.WinTop = 0;
00081		VertSB.WinHeight = WinHeight;
00082		VertSB.WinWidth = LookAndFeel.Size_ScrollbarWidth;
00083		VertSB.WinLeft = WinWidth - LookAndFeel.Size_ScrollbarWidth;
00084	}
00085	
00086	function Paint( Canvas C, float MouseX, float MouseY )
00087	{
00088		local UWindowDynamicTextRow L;
00089		local int SkipCount, DrawCount;
00090		local int i;
00091		local float Y, Junk;
00092		local bool bWrapped;
00093	
00094		C.DrawColor = TextColor;
00095	
00096		if(AbsoluteFont != None)
00097			C.Font = AbsoluteFont;
00098		else
00099			C.Font = Root.Fonts[Font];
00100	
00101		if(OldW != WinWidth || OldH != WinHeight)
00102		{
00103			WordWrap(C, True);
00104			OldW = WinWidth;
00105			OldH = WinHeight;
00106			bWrapped = True;
00107		}
00108		else
00109		if(bDirty)
00110		{
00111			WordWrap(C, False);
00112			bWrapped = True;
00113		}
00114	
00115		if(bWrapped)
00116		{
00117			TextAreaTextSize(C, "A", Junk, DefaultTextHeight);
00118			VisibleRows = WinHeight / DefaultTextHeight;
00119			Count = List.Count();
00120			VertSB.SetRange(0, Count, VisibleRows);
00121	
00122			if(bScrollOnResize)
00123			{
00124				if(bTopCentric)
00125					VertSB.Pos = 0;
00126				else
00127					VertSB.Pos = VertSB.MaxPos;
00128			}
00129	
00130			if(bAutoScrollbar && !bVariableRowHeight)
00131			{
00132				if(Count <= VisibleRows)
00133					VertSB.HideWindow();
00134				else
00135					VertSB.ShowWindow();
00136			}
00137		}
00138	
00139		if(bTopCentric)
00140		{
00141			SkipCount = VertSB.Pos;
00142			L = UWindowDynamicTextRow(List.Next);
00143			for(i=0; i < SkipCount && (L != None) ; i++)
00144				L = UWindowDynamicTextRow(L.Next);
00145	
00146			if(bVCenter && Count <= VisibleRows)
00147				Y = int((WinHeight - (Count * DefaultTextHeight)) / 2);
00148			else
00149				Y = 1;
00150	
00151			DrawCount = 0;
00152			while(Y < WinHeight)
00153			{
00154				DrawCount++;
00155				if(L != None)
00156				{
00157					Y += DrawTextLine(C, L, Y);
00158					L = UWindowDynamicTextRow(L.Next);
00159				}
00160				else
00161					Y += DefaultTextHeight;
00162			}
00163	
00164			if(bVariableRowHeight)
00165			{
00166				VisibleRows = DrawCount - 1;
00167	
00168				while(VertSB.Pos + VisibleRows > Count)
00169					VisibleRows--;
00170	
00171				VertSB.SetRange(0, Count, VisibleRows);
00172	
00173				if(bAutoScrollbar)
00174				{
00175					if(Count <= VisibleRows)
00176						VertSB.HideWindow();
00177					else
00178						VertSB.ShowWindow();
00179				}
00180			}
00181		}
00182		else
00183		{
00184			SkipCount = Max(0, Count - (VisibleRows + VertSB.Pos));
00185			L = UWindowDynamicTextRow(List.Last);
00186			for(i=0; i < SkipCount && (L != List) ; i++)
00187				L = UWindowDynamicTextRow(L.Prev);
00188	
00189			Y = WinHeight - DefaultTextHeight;
00190			while(L != List && L != None && Y > -DefaultTextHeight)
00191			{
00192				DrawTextLine(C, L, Y);
00193				Y = Y - DefaultTextHeight;
00194				L = UWindowDynamicTextRow(L.Prev);
00195			}
00196		}
00197	}
00198	
00199	function UWindowDynamicTextRow AddText(string NewLine)
00200	{
00201		local UWindowDynamicTextRow L;
00202		local string Temp;
00203		local int i;
00204	
00205		bDirty = True;
00206		
00207		i = InStr(NewLine, "\\n");
00208		if(i != -1)
00209		{
00210			Temp = Mid(NewLine, i+2);
00211			NewLine = Left(NewLine, i);		
00212		}
00213		else
00214			Temp = "";
00215		
00216	
00217		// reuse a row if possible
00218		L = CheckMaxRows();
00219	
00220		if(L != None)
00221			List.AppendItem(L);
00222		else
00223			L = UWindowDynamicTextRow(List.Append(RowClass));
00224	
00225		L.Text = NewLine;
00226		L.WrapParent = None;
00227		L.bRowDirty = True;
00228	
00229		if(Temp != "")
00230			AddText(Temp);
00231	
00232		return L;
00233	}
00234	
00235	function UWindowDynamicTextRow CheckMaxRows()
00236	{
00237		local UWindowDynamicTextRow L;
00238		L = None;
00239		while(MaxLines > 0 && List.Count() > MaxLines - 1 && List.Next != None)
00240		{
00241			L = UWindowDynamicTextRow(List.Next);
00242			RemoveWrap(L);
00243			L.Remove();
00244		}
00245		return L;
00246	}
00247	
00248	function WordWrap(Canvas C, bool bForce)
00249	{
00250		local UWindowDynamicTextRow L;
00251	
00252		for(L = UWindowDynamicTextRow(List.Next); L != None; L = UWindowDynamicTextRow(L.Next))
00253			if(L.WrapParent == None && (L.bRowDirty || bForce))
00254				WrapRow(C, L);
00255	
00256		bDirty = False;
00257	}
00258	
00259	function WrapRow(Canvas C, UWindowDynamicTextRow L)
00260	{
00261		local UWindowDynamicTextRow CurrentRow, N;
00262		local float MaxWidth;
00263		local int WrapPos;
00264	
00265		if(WrapWidth == 0)
00266		{
00267			if(VertSB.bWindowVisible || bAutoScrollbar)
00268				MaxWidth = WinWidth - VertSB.WinWidth;
00269			else
00270				MaxWidth = WinWidth;
00271		}
00272		else
00273			MaxWidth = WrapWidth;
00274	
00275		L.bRowDirty = False;
00276	
00277		// fast check - single line?
00278		N = UWindowDynamicTextRow(L.Next);
00279		if(N == None || N.WrapParent != L)
00280		{
00281			if(GetWrapPos(C, L, MaxWidth) == -1)
00282				return;
00283		}
00284	
00285		RemoveWrap(L);
00286		CurrentRow = L;
00287	
00288		while(True)
00289		{
00290			WrapPos = GetWrapPos(C, CurrentRow, MaxWidth);
00291			if(WrapPos == -1)
00292				break;
00293	
00294			CurrentRow = SplitRowAt(CurrentRow, WrapPos);
00295		}
00296	}
00297	
00298	///////////////////////////////////////////////////////
00299	// Functions to override to change format/layout
00300	///////////////////////////////////////////////////////
00301	
00302	function float DrawTextLine(Canvas C, UWindowDynamicTextRow L, float Y)
00303	{
00304		local float X, W, H;
00305	
00306		if(bHCenter)
00307		{
00308			TextAreaTextSize(C, L.Text, W, H);
00309			if(VertSB.bWindowVisible)
00310				X = int(((WinWidth - VertSB.WinWidth) - W) / 2);
00311			else
00312				X = int((WinWidth - W) / 2);
00313		}
00314		else
00315			X = 2;
00316		TextAreaClipText(C, X, Y, L.Text);
00317	
00318		return DefaultTextHeight;
00319	}
00320	
00321	
00322	// find where to break the line
00323	function int GetWrapPos(Canvas C, UWindowDynamicTextRow L, float MaxWidth)
00324	{
00325		local float W, H, LineWidth, NextWordWidth;
00326		local string Input, NextWord;
00327		local int WordsThisRow, WrapPos;
00328	
00329		// quick check
00330		TextAreaTextSize(C, L.Text, W, H);
00331		if(W <= MaxWidth)
00332			return -1;
00333	
00334		Input = L.Text;
00335		WordsThisRow = 0;
00336		LineWidth = 0;
00337		WrapPos = 0;
00338		NextWord = "";
00339	
00340		while(Input != "" || NextWord != "")
00341		{
00342			if(NextWord == "")
00343			{
00344				RemoveNextWord(Input, NextWord);
00345				TextAreaTextSize(C, NextWord, NextWordWidth, H);
00346			}
00347			if(WordsThisRow > 0 && LineWidth + NextWordWidth > MaxWidth)
00348			{
00349				return WrapPos;
00350			}
00351			else
00352			{
00353				WrapPos += Len(NextWord);
00354				LineWidth += NextWordWidth;
00355				NextWord = "";
00356				WordsThisRow++;
00357			}
00358		}
00359		return -1;
00360	}
00361	
00362	function UWindowDynamicTextRow SplitRowAt(UWindowDynamicTextRow L, int SplitPos)
00363	{
00364		local UWindowDynamicTextRow N;
00365	
00366		N = UWindowDynamicTextRow(L.InsertAfter(RowClass));
00367	
00368		if(L.WrapParent == None)
00369			N.WrapParent = L;
00370		else
00371			N.WrapParent = L.WrapParent;
00372	
00373		N.Text = Mid(L.Text, SplitPos);
00374		L.Text = Left(L.Text, SplitPos);
00375	
00376		return N;
00377	}
00378	
00379	function RemoveNextWord(out string Text, out string NextWord)
00380	{
00381		local int i;
00382	
00383		i = InStr(Text, " ");
00384		if(i == -1)
00385		{
00386			NextWord = Text;
00387			Text = "";
00388		}
00389		else
00390		{
00391			while(Mid(Text, i, 1) == " ")
00392				i++;
00393	
00394			NextWord = Left(Text, i);
00395			Text = Mid(Text, i);
00396		}
00397	}
00398	
00399	function RemoveWrap(UWindowDynamicTextRow L)
00400	{
00401		local UWindowDynamicTextRow N;
00402	
00403		// Remove previous word-wrapping
00404		N = UWindowDynamicTextRow(L.Next);
00405		while(N != None && N.WrapParent == L)
00406		{
00407			L.Text = L.Text $ N.Text;
00408			N.Remove();
00409			N = UWindowDynamicTextRow(L.Next);
00410		}
00411	}
00412	
00413	defaultproperties
00414	{
00415	     bScrollOnResize=True
00416	     TextColor=(R=255,G=255,B=255)
00417	     RowClass=Class'UWindow.UWindowDynamicTextRow'
00418	     bNoKeyboard=True
00419	}

End Source Code