Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_BasePaginationUIComponent.c
Go to the documentation of this file.
2{
3 [Attribute("1", desc: "Number of rows in content area.")]
4 protected int m_iRows;
5
6 [Attribute("1", desc: "Number of columns in content area.")]
7 protected int m_iColumns;
8
9 [Attribute("-1", desc: "Minimum mumber of rows in content area.\n When -1, value from 'Rows' will be used.")]
10 protected int m_iMinRows;
11
12 [Attribute("-1", desc: "Minimum number of rows in content area.\n When -1, value from 'Columns' will be used.")]
13 protected int m_iMinColumns;
14
15 [Attribute(desc: "Name of content area widget.")]
16 protected string m_sContentName;
17
18 [Attribute(desc: "Name of a widget which, when activated, will move to the previous page. This button is shown when cursor is focused on the area.")]
19 protected string m_sButtonPrevName;
20
21 [Attribute(desc: "Name of a widget which, when activated, will move to the next page. This button is shown when cursor is focused on the area.")]
22 protected string m_sButtonNextName;
23
24 [Attribute("PrevButton_NoScroll", desc: "Name of a widget which, when activated, will move to the previous page. This button is shown when cursor is not focused on the area.")]
26
27 [Attribute("NextButton_NoScroll", desc: "Name of a widget which, when activated, will move to the next page. This button is shown when cursor is not focused on the area.")]
29
30 [Attribute(desc: "Name of a widget which, when focused, will move to the previous page.\nused to auto-paging when focusing outside of content area in given direction.")]
31 protected string m_sFocusPrevName;
32
33 [Attribute(desc: "Name of a widget which, when focused, will move to the next page.\nused to auto-paging when focusing outside of content area in given direction.")]
34 protected string m_sFocusNextName;
35
36 [Attribute(desc: "Name of the widget which will show page numbers.")]
37 protected string m_sPageIndexVisualName;
38
39 [Attribute("#AR-Editor_ContentBrowser_PageIndex_Text", desc: "Format of page number text.")]
40 protected string m_sPageIndexVisualText;
41
42 [Attribute(desc: "When enabled, button shortcuts will be accepted only when cursor is over content widget.\nWhen disabled, cursor can be anywhere inside area of the widget this component is attached to.\nDoes not affect gamepad controls.")]
44
45 [Attribute(desc: "If content widget is UniformGridSlot, empty grid tiles will be filled with these layouts.\nIf there are more items than defined here, the last layout in the list will be used.\n\nWhen undefined, no filling will be performed.", uiwidget: UIWidgets.ResourceNamePicker, params: "layout")]
46 protected ref array<ResourceName> m_aEmptyItemLayouts;
47
48 [Attribute(desc: "When enabled, going next from the last page will cycle back to the first page, and vice versa.")]
49 protected bool m_bLoop;
50
51 [Attribute("1", desc: "When true it will hide the arrows instead of disabling them if the button is disabled.")]
53
54 [Attribute("0", desc: "When true always ignore gamepad input. Set this true if the widget is always on the screen and there is a seperate dialog version of it for the gamepad. Setting this true will make sure the next and prev focus buttons will have 'No Focus' enabled")]
55 protected bool m_bIgnoreGamePadInput;
56
57 [Attribute("1", desc: "If true it will play the next and prev page audio on page change")]
59
60 [Attribute("1", desc: "If true it will show empty entries")]
61 protected bool m_bShowEmptyEntries;
62
63 [Attribute(SCR_SoundEvent.TURN_PAGE, UIWidgets.EditBox)]
64 protected string m_sOnNextPageSfx;
65
66 [Attribute(SCR_SoundEvent.TURN_PAGE, UIWidgets.EditBox)]
67 protected string m_sOnPrevPageSfx;
68
69 [Attribute("", desc: "When true it will disable the arrows if number of pages is one.")]
71
72 protected int m_iCurrentPage;
73 protected bool m_bUnderCursor;
77 protected int m_FocusedIndex[2];
78
79 //------------------------------------------------------------------------------------------------
81 protected void DisableArrowsSinglePage()
82 {
84 return;
85
86 int countEntries = GetEntryCount();
87 int totalPages = Math.Ceil(countEntries / (m_iRows * m_iColumns));
88 if (totalPages > 1)
89 return;
90
91 m_ButtonPrevWidget.SetVisible(false);
92 m_ButtonNextWidget.SetVisible(false);
93 }
94
95 //--- To be overridden by inherited classes
103 protected void ShowEntries(Widget contentWidget, int indexStart, int indexEnd);
110
111 //--- Public functions
116 {
117 return m_iRows;
118 }
119
123 {
124 return m_iColumns;
125 }
126
130 {
131 return m_iCurrentPage;
132 }
133
138 {
139 int row = UniformGridSlot.GetRow(w);
140 int column = UniformGridSlot.GetColumn(w);
141 return (m_iCurrentPage * m_iRows * m_iColumns) + (row * m_iColumns + column);
142 }
143
150
156 sealed bool SetPage(int page, bool isRefresh = false)
157 {
158 if (!m_ContentWidget)
159 return false;
160
161 //--- Get currently focused widget
162 int focusedRow = m_FocusedIndex[0];
163 int focusedColumn = m_FocusedIndex[1];
164
165 //--- Set new page
166 int pageCapacity = m_iRows * m_iColumns;
167 int countEntries = GetEntryCount();
168 int totalPages = Math.Ceil(countEntries / (m_iRows * m_iColumns));
169 if (totalPages > 0 && m_bLoop)
170 page = Math.Repeat(page, totalPages);
171
172 int indexStart = page * pageCapacity;
173 int indexEnd = Math.Min(indexStart + pageCapacity, countEntries);
174 if (indexStart < 0 || (countEntries > 0 && indexStart >= countEntries))
175 return false;
176
177 if (m_bPlayAudioOnPageChange && !isRefresh && m_iCurrentPage != page)
178 {
179 if (page > m_iCurrentPage)
180 SCR_UISoundEntity.SoundEvent(m_sOnNextPageSfx, true);
181 else
182 SCR_UISoundEntity.SoundEvent(m_sOnPrevPageSfx, true);
183 }
184
185 m_iCurrentPage = page;
186
187 //--- Delete existing entries
188 while (m_ContentWidget.GetChildren())
189 {
190 m_ContentWidget.GetChildren().RemoveFromHierarchy();
191 }
192
193 //--- Add new entries
194 ShowEntries(m_ContentWidget, indexStart, indexEnd);
195 bool hasContent = m_ContentWidget.GetChildren() != null;
196
197 //--- Position entries in the grid
198 Widget focusedButton;
199 if (m_ContentWidget.GetTypeID() == WidgetType.UniformGridLayoutWidgetTypeID)
200 {
201 int row, column;
202 Widget child = m_ContentWidget.GetChildren();
203 while (child)
204 {
205 UniformGridSlot.SetRow(child, row);
206 UniformGridSlot.SetColumn(child, column);
207
208 //--- Set navigation
210 {
211 if (column == 0 && m_sFocusPrevName)
212 child.SetNavigation(WidgetNavigationDirection.LEFT, WidgetNavigationRuleType.EXPLICIT, m_sFocusPrevName);
213
214
215 if (column == m_iColumns - 1 && m_sFocusNextName)
216 child.SetNavigation(WidgetNavigationDirection.RIGHT, WidgetNavigationRuleType.EXPLICIT, m_sFocusNextName);
217 }
218
219 //--- Find focused widget
220 if (row == focusedRow && column == focusedColumn)
221 focusedButton = SCR_WidgetTools.FindWidgetInChildren(child, WidgetType.ButtonWidgetTypeID);
222
223 IterateIndex(row, column);
224 child = child.GetSibling();
225 }
226
228 {
229 //--- Fill the rest with empty layout
230 int minRows = m_iRows;
231 if (page == 0 && m_iMinRows >= 0)
232 minRows = Math.Max(m_iMinRows, row);
233
234 int minColumns = m_iColumns;
235 if (page == 0 && m_iMinColumns >= 0)
236 minColumns = Math.Max(m_iMinColumns, row);
237
238 Widget emptyWidget;
239 int emptyItemsCount = m_aEmptyItemLayouts.Count() - 1;
240 while (row < minRows && column < minColumns)
241 {
242 if (m_aEmptyItemLayouts.IsEmpty())
243 {
244 emptyWidget = GetGame().GetWorkspace().CreateWidget(WidgetType.ImageWidgetTypeID, WidgetFlags.VISIBLE | WidgetFlags.IGNORE_CURSOR | WidgetFlags.NOFOCUS, new Color(0, 0, 0, 0), 0, m_ContentWidget);
245 }
246 else
247 {
248 int index = Math.Min(row * m_iColumns + column, emptyItemsCount);
249 emptyWidget = GetGame().GetWorkspace().CreateWidgets(m_aEmptyItemLayouts[index], m_ContentWidget);
250 }
251
252 UniformGridSlot.SetRow(emptyWidget, row);
253 UniformGridSlot.SetColumn(emptyWidget, column);
254
255 IterateIndex(row, column);
256 }
257 }
258 }
259
260 //--- No focus preserved, choose the first item
261 if (!focusedButton)
262 focusedButton = m_ContentWidget.GetChildren();
263
264 //--- Set focus
265 if (focusedButton)
266 GetGame().GetCallqueue().Call(FocusWidget, focusedButton);
267
268 /*
269 //--- Create dummy widget in bottom right cell to stretch the grid
270 WorkspaceWidget workspace = GetGame().GetWorkspace();
271 if (workspace)
272 {
273 Widget dummy = workspace.CreateWidget(WidgetType.ImageWidgetTypeID, WidgetFlags.VISIBLE | WidgetFlags.DISABLED, new Color(0, 0, 0, 0), 0, m_ContentWidget);
274 UniformGridSlot.SetRow(dummy, m_iRows - 1);
275 UniformGridSlot.SetColumn(dummy, m_iColumns - 1);
276 }*/
277
278 //--- Update page number
280 {
281 if (countEntries == 0)
282 {
283 m_PageNumberWidget.SetVisible(false);
284 }
285 else
286 {
287 m_PageNumberWidget.SetTextFormat(m_sPageIndexVisualText, m_iCurrentPage + 1, totalPages);
288 m_PageNumberWidget.SetVisible(true);
289 }
290 }
291
292 //--- Set prev/next button visibility
293 bool canLoop = m_bLoop && totalPages > 1;
294
295 EnablePageButton(m_ButtonPrevWidget, canLoop || page > 0);
296 EnablePageButton(m_ButtonPrevNoScrollWidget, canLoop || page > 0);
297
298 EnablePageButton(m_ButtonNextWidget, canLoop || page < totalPages - 1);
299 EnablePageButton(m_ButtonNextNoScrollWidget, canLoop || page < totalPages - 1);
300
301 m_OnPageChanged.Invoke(page);
302
303 return hasContent;
304 }
305
306 //------------------------------------------------------------------------------------------------
308 protected void FocusWidget(Widget w)
309 {
310 GetGame().GetWorkspace().SetFocusedWidget(w);
311 }
312
317 sealed bool RefreshPage()
318 {
319 return SetPage(m_iCurrentPage, true);
320 }
321
322 protected void IterateIndex(out int row, out int column)
323 {
324 column++;
325 if (column >= m_iColumns)
326 {
327 column = 0;
328 row++;
329 }
330 }
331
332 protected void EnablePageButton(Widget w, bool enable)
333 {
334 if (!w)
335 return;
336
338 {
339 w.SetOpacity(enable);
340 return;
341 }
342
343 SCR_ButtonBaseComponent buttonComponent = SCR_ButtonBaseComponent.Cast(w.FindHandler(SCR_ButtonBaseComponent));
344
345 if (buttonComponent)
346 buttonComponent.SetEnabled(enable);
347 else
348 w.SetEnabled(enable);
349 }
350
351 protected void OnButtonPrev()
352 {
353 if (m_bIgnoreGamePadInput && !GetGame().GetInputManager().IsUsingMouseAndKeyboard())
354 return;
355
356 if (m_bUnderCursor && GetMenu().IsFocused())
358
359 }
360
361 protected void OnButtonNext()
362 {
363 if (m_bIgnoreGamePadInput && !GetGame().GetInputManager().IsUsingMouseAndKeyboard())
364 return;
365
368 }
369
370 protected void SetUnderCursor(bool newUnderCursor)
371 {
372 m_bUnderCursor = newUnderCursor;
373
375 {
378
381 }
382 }
383
384 protected void OnInputDeviceIsGamepad(bool isGamepad)
385 {
386 //--- Always considered "under cursor" with gamepad
387 SetUnderCursor(isGamepad);
388 }
389
390 override protected bool IsUnique()
391 {
392 return false;
393 }
394
395 override bool OnFocus(Widget w, int x, int y)
396 {
397 if (w == m_FocusPrevWidget)
398 {
399 m_FocusedIndex[1] = m_iColumns - 1; //--- Select rightmost item to preserve continuity
400 OnButtonPrev();
401 }
402 else if (w == m_FocusNextWidget)
403 {
404 m_FocusedIndex[1] = 0; //--- Select leftmost item to preserve continuity
405 OnButtonNext();
406 }
407 else
408 {
409 //--- Remember coordinates of selected item, so it can be restored when current page changes
410 while (w)
411 {
412 if (w.GetParent() == m_ContentWidget)
413 {
414 m_FocusedIndex[0] = UniformGridSlot.GetRow(w);
415 m_FocusedIndex[1] = UniformGridSlot.GetColumn(w);
416 break;
417 }
418 w = w.GetParent();
419 }
420 }
421
422 return false;
423 }
424
425 override bool OnMouseEnter(Widget w, int x, int y)
426 {
428 {
429 //--- Hovering over prev/next buttons always counts
430 if (w == m_ButtonPrevWidget || w == m_ButtonNextWidget)// || (w == m_ButtonPrevNoScrollWidget && w != null) || (w == m_ButtonNextNoScrollWidget && w != null))
431 {
432 SetUnderCursor(true);
433 return false;
434 }
435
436 //--- Considered under cursor only when hovering over content area
437 while (w)
438 {
439 if (w == m_ContentWidget)
440 {
441 SetUnderCursor(true);
442 break;
443 }
444 w = w.GetParent();
445 }
446 }
447 else
448 {
449 SetUnderCursor(true);
450 }
451 return false;
452 }
453
454 override bool OnMouseLeave(Widget w, Widget enterW, int x, int y)
455 {
456 SetUnderCursor(false);
457 return false;
458 }
459
460 override void HandlerAttached(Widget w)
461 {
462 super.HandlerAttached(w);
463
465 return;
466
467 m_ContentWidget = w.FindAnyWidget(m_sContentName);
468
470
471 m_ButtonPrevWidget = w.FindAnyWidget(m_sButtonPrevName);
472 m_ButtonNextWidget = w.FindAnyWidget(m_sButtonNextName);
473
476
477 m_FocusPrevWidget = w.FindAnyWidget(m_sFocusPrevName);
478 m_FocusNextWidget = w.FindAnyWidget(m_sFocusNextName);
479
481 {
483 m_FocusPrevWidget.SetFlags(WidgetFlags.NOFOCUS);
485 m_FocusNextWidget.SetFlags(WidgetFlags.NOFOCUS);
486
488 m_ButtonPrevWidget.SetFlags(WidgetFlags.NOFOCUS);
490 m_ButtonNextWidget.SetFlags(WidgetFlags.NOFOCUS);
491
493 m_ButtonPrevNoScrollWidget.SetFlags(WidgetFlags.NOFOCUS);
495 m_ButtonNextNoScrollWidget.SetFlags(WidgetFlags.NOFOCUS);
496 }
497
499 if (prevButtonComponent)
500 prevButtonComponent.m_OnActivated.Insert(OnButtonPrev);
501 else
502 ButtonActionComponent.GetOnAction(m_ButtonPrevWidget, true).Insert(OnButtonPrev);
503
505 if (nextButtonComponent)
506 nextButtonComponent.m_OnActivated.Insert(OnButtonNext);
507 else
508 ButtonActionComponent.GetOnAction(m_ButtonNextWidget, true).Insert(OnButtonNext);
509
511 {
513 if (prevButtonComponent)
514 prevButtonComponent.m_OnActivated.Insert(OnButtonPrev);
515 else
517 }
518
520 {
522 if (nextButtonComponent)
523 nextButtonComponent.m_OnActivated.Insert(OnButtonNext);
524 else
526 }
527
528 OnInputDeviceIsGamepad(!GetGame().GetInputManager().IsUsingMouseAndKeyboard());
529 GetGame().OnInputDeviceIsGamepadInvoker().Insert(OnInputDeviceIsGamepad);
530
531 SetPage(m_iCurrentPage, true);
532
533 DisableArrowsSinglePage(); // Only runs if the flag is set to true
534 }
535 override void HandlerDeattached(Widget w)
536 {
537 super.HandlerDeattached(w);
538
540 GetGame().OnInputDeviceIsGamepadInvoker().Remove(OnInputDeviceIsGamepad);
541 }
542};
ArmaReforgerScripted GetGame()
Definition game.c:1398
ScriptInvoker OnInputDeviceIsGamepadInvoker()
Definition game.c:238
InputManager GetInputManager()
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
bool IsFocused()
SCR_RadialMenu GetMenu()
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Component to execute action when the button or its shortcut is pressed.
Definition Color.c:13
Definition Math.c:13
sealed bool SetPage(int page, bool isRefresh=false)
void FocusWidget(Widget w)
Separated focus function for later call.
ref array< ResourceName > m_aEmptyItemLayouts
override bool OnMouseEnter(Widget w, int x, int y)
void DisableArrowsSinglePage()
Disable page change button if flag is true and number of pages is 1.
override bool OnFocus(Widget w, int x, int y)
void ShowEntries(Widget contentWidget, int indexStart, int indexEnd)
override bool OnMouseLeave(Widget w, Widget enterW, int x, int y)
void EnablePageButton(Widget w, bool enable)
void IterateIndex(out int row, out int column)
Base class for any button, regardless its own content.
static bool IsEditMode()
Definition Functions.c:1566
SCR_FieldOfViewSettings Attribute
WidgetFlags
Widget flags. See enf::Widget::SetFlags().
Definition WidgetFlags.c:14
ScriptInvokerBase< func > ScriptInvoker
Definition tools.c:134