13 [
Attribute(
"", UIWidgets.ResourceNamePicker,
desc:
"Entry widget that list is filled with.")]
14 protected ResourceName m_sEntry;
17 [
Attribute(
"1", UIWidgets.EditBox,
desc:
"Time for apearing animation")]
18 protected float m_fAnimationAppearTime;
20 [
Attribute(
"20", UIWidgets.EditBox,
desc:
"How many entries should be created for single page")]
21 protected int m_iPageEntriesCount;
23 [
Attribute(
"15", UIWidgets.EditBox,
desc:
"On which entry from border page should be changed")]
24 protected int m_iPageChangeOffset;
27 protected int m_iAllEntriesCount;
30 const float SIZE_UNMEASURED = -1;
31 const int CHECK_ENTRY_SIZE_DELAY = 100;
34 const float ENTRY_OFFSET_UP = 0.1;
37 const int ZORDER_OFFSET_TOP;
38 const int ZORDER_OFFSET_BOTTOM = 3;
41 const string WIDGET_PAGES =
"VPages";
42 const string WIDGET_PAGE0 =
"VPage0";
43 const string WIDGET_PAGE1 =
"VPage1";
45 const string WIDGET_SCROLL_LAYOUT =
"ScrollLayout";
46 const string WIDGET_SIZE_OFFSET_TOP =
"SizeOffsetTop";
47 const string WIDGET_SIZE_OFFSET_BOTTOM =
"SizeOffsetBottom";
49 const string WIDGET_FOCUS_REST =
"FocusRest";
52 protected float m_fListPxHeight = SIZE_UNMEASURED;
53 protected float m_fPagePxHeight = SIZE_UNMEASURED;
54 protected float m_fViewPxHeight = SIZE_UNMEASURED;
55 protected float m_fEntryPxHeight = SIZE_UNMEASURED;
58 protected ScrollLayoutWidget m_wScroll;
60 protected Widget m_wPagesWrap;
61 protected Widget m_wPage0;
62 protected Widget m_wPage1;
64 protected Widget m_wPage0FirstEntry;
65 protected Widget m_wPage0LastEntry;
66 protected Widget m_wPage1FirstEntry;
67 protected Widget m_wPage1LastEntry;
69 protected Widget m_wLastFocused;
71 protected ref array<Widget> m_aEntryWidgets = {};
73 protected SizeLayoutWidget m_wSizeOffsetTop;
74 protected SizeLayoutWidget m_wSizeOffsetBottom;
77 protected bool m_bPagesInverted;
78 protected int m_iCurrentPage;
81 protected float m_ScrollLastY;
84 bool m_bIsListFocused;
94 override void HandlerAttached(Widget w)
96 super.HandlerAttached(w);
101 CreateEntriesWidgets();
117 protected void OnActionUp()
119 if (!m_bIsListFocused)
122 WorkspaceWidget workspace =
GetGame().GetWorkspace();
125 workspace.SetFocusedWidget(m_wLastFocused);
127 if (m_fPagePxHeight == 0)
130 float invisibleEntries = EntriesOutOfView();
131 if (invisibleEntries == 0)
135 float scrollPageRatio = (m_iPageEntriesCount + ENTRY_OFFSET_UP) / invisibleEntries;
136 int currentPage = Math.Floor(m_ScrollLastY / scrollPageRatio);
142 Widget focus = workspace.GetFocusedWidget();
144 if (focus != m_wPage0FirstEntry && focus != m_wPage1FirstEntry)
150 if (focus == m_wPage0FirstEntry)
151 workspace.SetFocusedWidget(m_wPage1LastEntry);
152 else if (focus == m_wPage1FirstEntry)
153 workspace.SetFocusedWidget(m_wPage0LastEntry);
158 protected void OnActionDown()
160 if (!m_bIsListFocused)
163 WorkspaceWidget workspace =
GetGame().GetWorkspace();
166 workspace.SetFocusedWidget(m_wLastFocused);
171 protected void OnScroll(
float scrollY)
173 if (m_fPagePxHeight == 0)
177 int currentPage = CurrentPageFromScrollPos(scrollY);
180 SetCurrentPage(currentPage);
185 protected int CurrentPageFromScrollPos(
float scrollY)
188 if (m_iPageEntriesCount == 0)
191 int entriesOutOfView = EntriesOutOfView();
192 if (entriesOutOfView == 0)
196 float scrollPageRatio = m_iPageEntriesCount / entriesOutOfView;
199 float pos = scrollY / scrollPageRatio;
202 pos = pos - (m_iPageChangeOffset / m_iPageEntriesCount);
206 int currentPage = Math.Floor(pos);
215 protected float EntriesOutOfView()
217 if (m_fPagePxHeight == 0)
221 float pageViewRatio = m_fViewPxHeight / m_fPagePxHeight;
222 float outOfView = m_iAllEntriesCount - m_iPageEntriesCount * pageViewRatio;
236 void UpdateEntries(
bool animated =
false)
239 foreach (Widget w : m_aEntryWidgets)
252 WorkspaceWidget workspace =
GetGame().GetWorkspace();
254 float scrollX, scrollY = 0;
255 m_wScroll.GetSliderPos(scrollX, scrollY);
258 Widget focused = FocusedWidgetFromEntryList();
261 m_wLastFocused = focused;
264 Widget workspaceFocused = workspace.GetFocusedWidget();
265 m_bIsListFocused = (workspaceFocused == m_wLastFocused);
267 if (m_ScrollLastY == scrollY)
271 m_ScrollLastY = scrollY;
274 if (m_fEntryPxHeight == SIZE_UNMEASURED || m_fEntryPxHeight == 0 && m_iAllEntriesCount != 0)
283 protected void SetCurrentPage(
int page)
285 SetCurrentPageBase(page);
291 protected void SetCurrentPageBase(
int page)
299 int lastPage = Math.Floor(m_iAllEntriesCount / m_iPageEntriesCount);
302 pagesInverted =
false;
305 m_OnSetPage.Invoke(page);
310 protected void SwitchPages(
bool invert,
float size,
int page)
313 if (m_iAllEntriesCount == 0)
317 if (!m_wPage0 || !m_wPage1)
321 m_bPagesInverted = invert;
324 int maxPages = Math.Floor(m_iAllEntriesCount / m_iPageEntriesCount);
325 if (page > maxPages - 1)
331 m_wPage0.SetZOrder(invert);
332 m_wPage1.SetZOrder(!invert);
337 protected void SetupOffsets(
int page)
339 int overflowEntryCount = m_iAllEntriesCount - m_iPageEntriesCount*2;
340 float offset = m_fEntryPxHeight * overflowEntryCount - m_fPagePxHeight * page;
343 float pageSizeBaseOnEntry = m_fEntryPxHeight * m_iPageEntriesCount;
345 m_wSizeOffsetTop.SetHeightOverride(m_fPagePxHeight * page);
346 m_wSizeOffsetBottom.SetHeightOverride(offset);
348 m_wSizeOffsetTop.SetZOrder(ZORDER_OFFSET_TOP);
349 m_wSizeOffsetBottom.SetZOrder(ZORDER_OFFSET_BOTTOM);
354 void FocusFirstAvailableEntry()
357 Widget availableEntry = FirstAvailableEntry();
362 GetGame().GetWorkspace().SetFocusedWidget(
null);
363 GetGame().GetWorkspace().SetFocusedWidget(availableEntry);
373 m_bPagesInverted =
false;
374 SwitchPages(m_bPagesInverted, 0, 0);
377 m_wScroll.SetSliderPos(0, 0);
382 void ShowScrollbar(
bool show)
386 m_wRoot.ClearFlags(WidgetFlags.CLIPCHILDREN);
387 m_wRoot.SetFlags(WidgetFlags.INHERIT_CLIPPING);
391 m_wRoot.SetFlags(WidgetFlags.CLIPCHILDREN);
392 m_wRoot.ClearFlags(WidgetFlags.INHERIT_CLIPPING);
402 protected void AccessingHandlers()
405 m_wScroll = ScrollLayoutWidget.Cast(
m_wRoot.FindAnyWidget(WIDGET_SCROLL_LAYOUT));
408 m_wPagesWrap =
m_wRoot.FindAnyWidget(WIDGET_PAGES);
409 m_wPage0 =
m_wRoot.FindAnyWidget(WIDGET_PAGE0);
410 m_wPage1 =
m_wRoot.FindAnyWidget(WIDGET_PAGE1);
413 m_wSizeOffsetTop = SizeLayoutWidget.Cast(
m_wRoot.FindAnyWidget(WIDGET_SIZE_OFFSET_TOP));
414 m_wSizeOffsetBottom = SizeLayoutWidget.Cast(
m_wRoot.FindAnyWidget(WIDGET_SIZE_OFFSET_BOTTOM));
419 protected void CreateEntriesWidgets()
421 if(!
m_wRoot || m_sEntry.IsEmpty())
424 CreateEntriesWidgetsInPage(m_wPage0, m_iPageEntriesCount, m_wPage0FirstEntry, m_wPage0LastEntry);
425 CreateEntriesWidgetsInPage(m_wPage1, m_iPageEntriesCount, m_wPage1FirstEntry, m_wPage1LastEntry);
430 protected void CreateEntriesWidgetsInPage(Widget parent,
int count, out Widget firstEntry, out Widget lastEntry)
432 for (
int i = 0; i < count; i++)
434 Widget entry = CreateEntry(parent);
448 protected Widget CreateEntry(Widget parent)
450 WorkspaceWidget workspace =
GetGame().GetWorkspace();
452 if (!m_sEntry || !parent || !workspace)
455 Widget widget = workspace.CreateWidgets(m_sEntry, parent);
460 SetupEntryBehavior(widget);
463 m_aEntryWidgets.Insert(widget);
468 protected bool m_bIsMeasured =
false;
472 protected void CheckEntrySize()
474 if (m_aEntryWidgets.IsEmpty())
480 ShowScrollbar(
false);
484 m_aEntryWidgets[0].GetScreenSize(x, m_fEntryPxHeight);
487 m_wPage0.GetScreenSize(x, m_fPagePxHeight);
490 m_wRoot.GetScreenSize(x, m_fViewPxHeight);
493 if (m_fEntryPxHeight != 0)
495 m_bIsMeasured =
true;
503 m_fListPxHeight = m_fEntryPxHeight * m_iAllEntriesCount;
511 protected void SetupEntryBehavior(Widget entry) { }
518 protected void FillEntry(Widget w) {}
522 protected void AnimateEntryOpacity(Widget w,
int delay,
float animTime,
float opacityEnd,
float opacityStart = -1)
524 if (opacityStart != -1)
525 w.SetOpacity(opacityStart);
527 GetGame().GetCallqueue().CallLater(OpacityAnimation, delay,
false, w, animTime, opacityEnd);
531 protected void OpacityAnimation(Widget w,
int time,
float opacityEnd)
533 AnimateWidget.Opacity(w, opacityEnd, time);
538 protected void ShowEntries(
int dataCount)
541 for (
int i = 0; i < m_aEntryWidgets.Count(); i++)
543 bool show = i < dataCount;
544 m_aEntryWidgets[i].SetVisible(show);
548 int overflow = dataCount - m_iPageEntriesCount*2;
549 bool addOffsets = overflow > 0;
552 m_wSizeOffsetTop.SetVisible(addOffsets);
553 m_wSizeOffsetBottom.SetVisible(addOffsets);
561 protected Widget FocusedWidgetFromEntryList()
563 Widget focused =
GetGame().GetWorkspace().GetFocusedWidget();
565 int focusedEntryId = m_aEntryWidgets.Find(focused);
567 if (focusedEntryId == -1)
577 int GetPageEntriesCount()
579 return m_iPageEntriesCount;
583 array<Widget> GetEntryWidgets()
585 return m_aEntryWidgets;
590 void SetDataEntries(
int entriesCount)
593 m_iAllEntriesCount = entriesCount;
596 ShowEntries(entriesCount);
599 GetGame().GetCallqueue().CallLater(CheckEntrySize, CHECK_ENTRY_SIZE_DELAY);
604 Widget FirstAvailableEntry()
606 foreach (Widget entry : m_aEntryWidgets)
608 if (entry.IsVisible() && entry.IsEnabled())
616 void SetIsListFocused(
bool focused)
618 m_bIsListFocused = focused;
624 return m_bIsListFocused;
628 Widget GetScrollWidget()