Release 8.0.0.15408
[platform/core/csapi/tizenfx.git] / test / Tizen.NUI.Samples / Tizen.NUI.Samples / Samples / TextPageUtil.cs
1 using System.Collections.Generic;
2 using System;
3 using System.IO;
4
5
6 using Tizen.NUI;
7 using Tizen.NUI.BaseComponents;
8 using Tizen.NUI.Components;
9 using Tizen.NUI.Wearable;
10
11 namespace Tizen.NUI.Samples
12 {
13   class PageData
14   {
15     public string previousTag  {get; set;}
16     public string endTag {get; set;}
17     public int startOffset {get; set;}
18     public int endOffset {get; set;}
19   }
20
21   class TagData
22   {
23     public string tagName {get; set;}
24     public string attributeName {get; set;}
25     public bool isEndTag {get; set;}
26   }
27
28   public class TextPageUtil
29   {
30     private static char LESS_THAN      = '<';
31     private static char GREATER_THAN   = '>';
32     private static char EQUAL          = '=';
33     private static char QUOTATION_MARK = '\'';
34     private static char SLASH          = '/';
35     private static char BACK_SLASH     = '\\';
36     private static char AMPERSAND      = '&';
37     private static char HASH           = '#';
38     private static char SEMI_COLON     = ';';
39     private static char CHAR_ARRAY_END = '\0';
40     private static char HEX_CODE       = 'x';
41     private static byte WHITE_SPACE    = 0x20;
42
43     private static int TEXTPAGE_TEXT_CHUNK = 20000;
44
45     private int totalPageCnt;
46
47     private List<PageData> pageList;
48     private List<TagData> tagList;
49     private StringReader stream;
50     private List<char> characterList;
51     private string pageString;
52
53
54     public int SetText(TextLabel label, string str)
55     {
56       if(str == null) return 0;
57
58       // perform this operation to match the utf32 character used in native Dali.
59       bool previousMarkup = label.EnableMarkup;
60       label.EnableMarkup = false;
61       label.Text = str;
62       pageString = label.Text;
63       label.EnableMarkup = previousMarkup;
64       label.MultiLine = true;
65       label.Ellipsis = false;
66
67       int length = pageString.Length;
68       int remainLength = length;
69       int offset = 0;
70       int cutOffIndex = 0;
71
72       // init
73       pageList = new List<PageData>();
74       tagList = new List<TagData>();
75       characterList = new List<char>();
76
77       stream = new StringReader(pageString);
78
79       RendererParameters textParameters = new RendererParameters();
80       textParameters.Text = pageString;
81       textParameters.HorizontalAlignment = label.HorizontalAlignment;
82       textParameters.VerticalAlignment = label.VerticalAlignment;
83       textParameters.FontFamily = label.FontFamily;
84       textParameters.FontWeight = "";
85       textParameters.FontWidth = "";
86       textParameters.FontSlant = "";
87       textParameters.Layout = TextLayout.MultiLine;
88       textParameters.TextColor = Color.Black;
89       textParameters.FontSize = label.PointSize;
90       textParameters.TextWidth = (uint)label.Size.Width;
91       textParameters.TextHeight = (uint)label.Size.Height;
92       textParameters.EllipsisEnabled = true;
93       textParameters.MarkupEnabled = previousMarkup;
94
95
96       Tizen.NUI.PropertyArray cutOffIndexArray = TextUtils.GetLastCharacterIndex( textParameters );
97       uint count = cutOffIndexArray.Count();
98       for(uint i=0; i < count; i++)
99       {
100           cutOffIndexArray.GetElementAt(i).Get(out cutOffIndex); // Gets the last index of text shown on the actual screen.
101
102           // If markup is enabled, It should parse markup
103           if(label.EnableMarkup)
104           {
105             int preOffset = offset;
106             offset = MarkupProcess( offset, cutOffIndex - preOffset );
107             remainLength -= (offset - preOffset);
108           }
109           //If markup is not enabled, parsing is not required.
110           else
111           {
112             PageData pageData = new PageData();
113             pageData.startOffset = offset;
114             int cnt = (cutOffIndex - offset ) < remainLength ? (cutOffIndex - offset ) : remainLength;
115             remainLength -= cnt;
116             offset += cnt;
117             pageData.endOffset = offset;
118             pageList.Add(pageData);
119           }
120           totalPageCnt++;
121           if(offset <= 0 ) break;
122       }
123
124       stream = null;
125       return totalPageCnt;
126     }
127
128     public string GetText(int pageNum)
129     {
130       if( pageNum > totalPageCnt || pageNum < 1 ) {
131           Tizen.Log.Error("NUI", $"Out of Range total page count : {totalPageCnt}, input page number : {pageNum}\n");
132           return "";
133       }
134
135       List<PageData> dataList = pageList.GetRange(pageNum-1, 1);
136       foreach(PageData data in dataList)
137       {
138         int cnt = data.endOffset - data.startOffset;
139         char[] charArray = new char[cnt];
140         pageString.CopyTo(data.startOffset, charArray, 0, cnt);
141         string pageText = data.previousTag+new String(charArray)+data.endTag;
142         return pageText;
143       }
144       return "";
145     }
146
147     private void SkipWhiteSpace(ref int offset)
148     {
149       int character;
150       while( ( character = stream.Read()) != -1)
151       {
152         offset++;
153         if( character == WHITE_SPACE) continue;
154         else break;
155       }
156     }
157
158     private bool IsTag(TagData tag, ref int offset)
159     {
160       List<char> tagChaList = new List<char>();
161
162       bool isTag = false;
163       bool isQuotationOpen = false;
164       bool attributesFound = false;
165       tag.isEndTag = false;
166       bool isPreviousLessThan = true;
167       bool isPreviousSlash = false;
168
169       int character;
170
171       tag.tagName = "";
172       tag.attributeName = "";
173       // SkipWhiteSpace(ref offset);
174       while((!isTag) && ((character = stream.Read()) != -1)) {
175         offset++;
176         characterList.Add((char)character);
177         if( !isQuotationOpen && ( SLASH == character ) ) // '/'
178         {
179           if (isPreviousLessThan)
180           {
181             tag.isEndTag = true;
182           }
183           else
184           {
185             // if the tag has a '/' it may be an end tag.
186             isPreviousSlash = true;
187           }
188           isPreviousLessThan = false;
189           // SkipWhiteSpace(ref offset);
190         }
191         else if( GREATER_THAN == character ) // '>'
192         {
193           isTag = true;
194           if (isPreviousSlash)
195           {
196             tag.isEndTag = true;
197           }
198
199           if(!attributesFound) {
200             tag.tagName = new String(tagChaList.ToArray());
201           } else {
202             tag.attributeName = new String(tagChaList.ToArray());
203           }
204
205           isPreviousSlash = false;
206           isPreviousLessThan = false;
207         }
208         else if( QUOTATION_MARK == character )
209         {
210           tagChaList.Add((char)character);
211           isQuotationOpen = !isQuotationOpen;
212
213           isPreviousSlash = false;
214           isPreviousLessThan = false;
215         }
216         else if( WHITE_SPACE >= character || EQUAL == character ) // ' ', '='
217         {
218           // Let's save tag name.
219           if(!attributesFound) {
220             tag.tagName = new String(tagChaList.ToArray());
221             tagChaList.Clear();
222           }
223           tagChaList.Add((char)character);
224           // If the tag contains white spaces then it may have attributes.
225           if( !isQuotationOpen )
226           {
227             attributesFound = true;
228           }
229         }
230         else
231         {
232           tagChaList.Add((char)character);
233           isPreviousSlash = false;
234           isPreviousLessThan = false;
235         }
236       }
237       return isTag;
238     }
239
240
241     private int MarkupProcess(int startOffset, int cutOffIndex)
242     {
243
244       int count = 0;
245       int offset = startOffset;
246       int character = 0;
247       characterList.Clear();
248       PageData pageData = new PageData();
249
250       pageData.startOffset = offset;
251
252       bool isPreviousLessThan = false;
253       bool isPreviousSlash = false;
254
255       // If the markup was previously open, the markup tag should be attached to the front.
256       string tag ="";
257       foreach (TagData data in tagList)
258       {
259         tag += "<"+data.tagName+data.attributeName+">";
260       }
261       pageData.previousTag = tag;
262
263
264       bool isTag = false;
265       while( (character = stream.Read()) != -1 )
266       {
267         offset++;
268         characterList.Add((char)character);
269
270         TagData tagData = new TagData();
271         isTag = false;
272         if( LESS_THAN == character ) // '<'
273         {
274           isTag = IsTag(tagData, ref offset);
275         }
276
277         if(isTag) {
278           if(tagData.isEndTag) {
279             int lastIndex = tagList.Count;
280             tagList.RemoveAt(lastIndex-1);
281           } else {
282             tagList.Add(tagData);
283           }
284         } else {
285           count++;
286         }
287         if(count >= cutOffIndex) break;
288
289       }
290
291       // If the markup was previously open, you should attach the label tag.
292       tag ="";
293       foreach (TagData data in tagList)
294       {
295         tag = "</"+data.tagName+">" + tag;
296       }
297       pageData.endTag = tag;
298
299       pageData.endOffset = offset;
300       pageList.Add(pageData);
301
302       if(character == -1) offset = -1;
303       return offset;
304     }
305
306   }
307 }