Client LuaCsForBarotrauma
GUIListBox.cs
1 using EventInput;
2 using Microsoft.Xna.Framework;
3 using Microsoft.Xna.Framework.Graphics;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
8 using Microsoft.Xna.Framework.Input;
9 
10 namespace Barotrauma
11 {
13  {
14  protected List<GUIComponent> selected;
15 
16  public delegate bool OnSelectedHandler(GUIComponent component, object obj);
18 
19  public delegate object CheckSelectedHandler();
21 
22  public delegate void OnRearrangedHandler(GUIListBox listBox, object obj);
24 
28  public GUIFrame ContentBackground { get; private set; }
29 
33  public GUIFrame Content { get; private set; }
34  public GUIScrollBar ScrollBar { get; private set; }
35 
36  private readonly Dictionary<GUIComponent, bool> childVisible = new Dictionary<GUIComponent, bool>();
37 
38  private int totalSize;
39  private bool childrenNeedsRecalculation;
40  private bool scrollBarNeedsRecalculation;
41  private bool dimensionsNeedsRecalculation;
42 
43  // TODO: Define in styles?
44  private int ScrollBarSize
45  {
46  get
47  {
48  //use the average of the "desired" size and the scaled size
49  //scaling the bar linearly with the resolution tends to make them too large on large resolutions
50  float desiredSize = 25.0f;
51  float scaledSize = desiredSize * GUI.Scale;
52  return (int)Math.Min((desiredSize + scaledSize) / 2.0f, Rect.Height / 3);
53  }
54  }
55 
56  public enum SelectMode
57  {
58  SelectSingle,
60  RequireShiftToSelectMultiple,
61  None
62  }
63 
64  public SelectMode CurrentSelectMode = SelectMode.SelectSingle;
65 
66  public bool SelectMultiple
67  {
68  get { return CurrentSelectMode != SelectMode.SelectSingle; }
69  set
70  {
71  CurrentSelectMode = value ? SelectMode.SelectMultiple : SelectMode.SelectSingle;
72  }
73  }
74 
75  public bool HideChildrenOutsideFrame = true;
76 
78 
79  private bool useGridLayout;
80 
81  private GUIComponent scrollToElement;
82 
83  public bool AllowMouseWheelScroll { get; set; } = true;
84 
85  public bool AllowArrowKeyScroll { get; set; } = true;
86 
90  public bool SmoothScroll { get; set; }
91 
95  public bool ClampScrollToElements { get; set; }
96 
100  public bool FadeElements { get; set; }
101 
105  public bool PadBottom { get; set; }
106 
110  public bool SelectTop { get; set; }
111 
112  public bool UseGridLayout
113  {
114  get { return useGridLayout; }
115  set
116  {
117  if (useGridLayout == value) return;
118  useGridLayout = value;
119  childrenNeedsRecalculation = true;
120  scrollBarNeedsRecalculation = true;
121  }
122  }
123 
127  private readonly bool useMouseDownToSelect = false;
128 
129  private Vector4? overridePadding;
130  public Vector4 Padding
131  {
132  get
133  {
134  if (overridePadding.HasValue) { return overridePadding.Value; }
135  if (Style == null) { return Vector4.Zero; }
136  return Style.Padding;
137  }
138  set
139  {
140  dimensionsNeedsRecalculation = true;
141  overridePadding = value;
142  }
143  }
144 
146  {
147  get
148  {
149  return selected.FirstOrDefault();
150  }
151  }
152 
153  public override bool Selected
154  {
155  get { return isSelected; }
156  set { isSelected = value; }
157  }
158 
159  public IReadOnlyList<GUIComponent> AllSelected => selected;
160 
161  public object SelectedData
162  {
163  get
164  {
165  return SelectedComponent?.UserData;
166  }
167  }
168 
169  public int SelectedIndex
170  {
171  get
172  {
173  if (SelectedComponent == null) return -1;
175  }
176  }
177 
178  public float BarScroll
179  {
180  get { return ScrollBar.BarScroll; }
181  set { ScrollBar.BarScroll = value; }
182  }
183 
184  public float BarSize
185  {
186  get { return ScrollBar.BarSize; }
187  }
188 
189  public float TotalSize
190  {
191  get { return totalSize; }
192  }
193 
194  public int Spacing { get; set; }
195 
196  public override Color Color
197  {
198  get
199  {
200  return base.Color;
201  }
202  set
203  {
204  base.Color = value;
205 
206  Content.Color = value;
207  }
208  }
209 
213  public bool ScrollBarEnabled { get; set; } = true;
214  public bool KeepSpaceForScrollBar { get; set; }
215 
216  public bool CanTakeKeyBoardFocus { get; set; } = true;
217 
218  public bool ScrollBarVisible
219  {
220  get
221  {
222  return ScrollBar.Visible;
223  }
224  set
225  {
226  if (ScrollBar.Visible == value) { return; }
227  ScrollBar.Visible = value;
228  dimensionsNeedsRecalculation = true;
229  }
230  }
231 
235  public bool AutoHideScrollBar { get; set; } = true;
236  private bool IsScrollBarOnDefaultSide { get; set; }
237 
238  public enum DragMode
239  {
240  NoDragging,
241  DragWithinBox,
242  DragOutsideBox
243  }
244 
245  private DragMode currentDragMode = DragMode.NoDragging;
247  {
248  get
249  {
250  return currentDragMode;
251  }
252  set
253  {
254  if (value == DragMode.NoDragging && currentDragMode != DragMode.NoDragging && isDraggingElement)
255  {
256  DraggedElement = null;
257  }
258  currentDragMode = value;
259  }
260  }
261 
262  private GUIComponent draggedElement;
263  private Point dragMousePosRelativeToTopLeftCorner;
264  private bool isDraggingElement => draggedElement != null;
265 
266  public bool HasDraggedElementIndexChanged { get; private set; }
267 
269  {
270  get
271  {
272  return draggedElement;
273  }
274  set
275  {
276  if (value == draggedElement) { return; }
277  draggedElement = value;
279 
280  if (value == null) { return; }
281 
282  dragMousePosRelativeToTopLeftCorner = PlayerInput.MousePosition.ToPoint() - value.Rect.Location;
283 
284  if (SelectMultiple)
285  {
286  if (!AllSelected.Contains(DraggedElement))
287  {
288  Select(DraggedElement.ToEnumerable());
289  }
290  }
291  }
292  }
293 
294  //This exists to work around the fact that rendering child
295  //elements on top of the listbox's siblings is a clusterfuck.
296  public bool HideDraggedElement = false;
297 
298  private readonly bool isHorizontal;
299 
303  public bool CanInteractWhenUnfocusable { get; set; } = false;
304 
305  public override Rectangle MouseRect
306  {
307  get
308  {
309  if (!CanBeFocused && !CanInteractWhenUnfocusable) { return Rectangle.Empty; }
311  }
312  }
313 
314  public override bool PlaySoundOnSelect { get; set; } = false;
315 
316  public bool PlaySoundOnDragStop { get; set; } = false;
317 
318  public GUISoundType? SoundOnDragStart { get; set; } = null;
319 
320  public GUISoundType? SoundOnDragStop { get; set; } = null;
321 
322  #region enums
323  public enum Force
324  {
325  Yes,
326  No
327  }
328 
329  public enum AutoScroll
330  {
331  Enabled,
332  Disabled
333  }
334 
335  public enum TakeKeyBoardFocus
336  {
337  Yes,
338  No
339  }
340 
341  public enum PlaySelectSound
342  {
343  Yes,
344  No
345  }
346 
347  private AutoScroll GetAutoScroll(bool b)
348  {
349  return b ? AutoScroll.Enabled : AutoScroll.Disabled;
350  }
351  #endregion
352 
354  public GUIListBox(RectTransform rectT, bool isHorizontal = false, Color? color = null, string style = "", bool isScrollBarOnDefaultSide = true, bool useMouseDownToSelect = false) : base(style, rectT)
355  {
356  this.isHorizontal = isHorizontal;
357  HoverCursor = CursorState.Hand;
358  CanBeFocused = true;
359  selected = new List<GUIComponent>();
360  this.useMouseDownToSelect = useMouseDownToSelect;
361  ContentBackground = new GUIFrame(new RectTransform(Vector2.One, rectT), style)
362  {
363  CanBeFocused = false
364  };
365  Content = new GUIFrame(new RectTransform(Vector2.One, ContentBackground.RectTransform), style: null)
366  {
367  CanBeFocused = false
368  };
370  {
371  scrollBarNeedsRecalculation = true;
372  childrenNeedsRecalculation = true;
373  };
374  if (style != null)
375  {
376  GUIStyle.Apply(ContentBackground, "", this);
377  }
378  if (color.HasValue)
379  {
380  this.color = color.Value;
381  }
382  IsScrollBarOnDefaultSide = isScrollBarOnDefaultSide;
383  Point size;
384  Anchor anchor;
385  if (isHorizontal)
386  {
387  size = new Point((int)(Rect.Width - Padding.X - Padding.Z), (int)(ScrollBarSize * GUI.Scale));
388  anchor = isScrollBarOnDefaultSide ? Anchor.BottomCenter : Anchor.TopCenter;
389  }
390  else
391  {
392  // TODO: Should this be multiplied by the GUI.Scale as well?
393  size = new Point(ScrollBarSize, (int)(Rect.Height - Padding.Y - Padding.W));
394  anchor = isScrollBarOnDefaultSide ? Anchor.CenterRight : Anchor.CenterLeft;
395  }
396  ScrollBar = new GUIScrollBar(
397  new RectTransform(size, rectT, anchor)
398  {
399  AbsoluteOffset = isHorizontal ?
400  new Point(0, IsScrollBarOnDefaultSide ? (int)Padding.W : (int)Padding.Y) :
401  new Point(IsScrollBarOnDefaultSide ? (int)Padding.Z : (int)Padding.X, 0)
402  },
403  isHorizontal: isHorizontal);
405  Enabled = true;
406  ScrollBar.BarScroll = 0.0f;
407  RectTransform.ScaleChanged += () => dimensionsNeedsRecalculation = true;
408  RectTransform.SizeChanged += () => dimensionsNeedsRecalculation = true;
410 
411  rectT.ChildrenChanged += CheckForChildren;
412  }
413 
414  private void CheckForChildren(RectTransform rectT)
415  {
416  if (rectT == ScrollBar.RectTransform || rectT == Content.RectTransform || rectT == ContentBackground.RectTransform) { return; }
417  throw new InvalidOperationException($"Children were added to {nameof(GUIListBox)}, Add them to {nameof(GUIListBox)}.{nameof(Content)} instead.");
418  }
419 
420  public void UpdateDimensions()
421  {
422  dimensionsNeedsRecalculation = false;
425  Point contentSize = reduceScrollbarSize ? CalculateFrameSize(ScrollBar.IsHorizontal, ScrollBarSize) : Rect.Size;
426  Content.RectTransform.Resize(new Point((int)(contentSize.X - Padding.X - Padding.Z), (int)(contentSize.Y - Padding.Y - Padding.W)));
427  if (!IsScrollBarOnDefaultSide) { Content.RectTransform.SetPosition(Anchor.BottomRight); }
429  IsScrollBarOnDefaultSide ? (int)Padding.X : (int)Padding.Z,
430  IsScrollBarOnDefaultSide ? (int)Padding.Y : (int)Padding.W);
432  new Point((int)(Rect.Width - Padding.X - Padding.Z), ScrollBarSize) :
433  new Point(ScrollBarSize, (int)(Rect.Height - Padding.Y - Padding.W)));
435  new Point(0, (int)Padding.W) :
436  new Point((int)Padding.Z, 0);
438  }
439 
440  public void Select(object userData, Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled)
441  {
442  var children = Content.Children;
443  int i = 0;
444  foreach (GUIComponent child in children)
445  {
446  if (Equals(child.UserData, userData))
447  {
448  Select(i, force, autoScroll);
449  if (!SelectMultiple) { return; }
450  }
451  i++;
452  }
453  }
454 
455  private Point CalculateFrameSize(bool isHorizontal, int scrollBarSize)
456  => isHorizontal ? new Point(Rect.Width, Rect.Height - scrollBarSize) : new Point(Rect.Width - scrollBarSize, Rect.Height);
457 
458  public Vector2 CalculateTopOffset()
459  {
460  int x = 0;
461  int y = 0;
462  if (ScrollBar.BarSize < 1.0f)
463  {
465  {
466  x -= (int)((totalSize - Content.Rect.Width) * ScrollBar.BarScroll);
467  }
468  else
469  {
470  y -= (int)((totalSize - Content.Rect.Height) * ScrollBar.BarScroll);
471  }
472  }
473 
474  return new Vector2(x, y);
475  }
476 
477  private void CalculateChildrenOffsets(Action<int, Point> callback)
478  {
479  Vector2 topOffset = CalculateTopOffset();
480  int x = (int)topOffset.X;
481  int y = (int)topOffset.Y;
482 
483  for (int i = 0; i < Content.CountChildren; i++)
484  {
485  GUIComponent child = Content.GetChild(i);
486  if (child == null || !child.Visible) { continue; }
487  if (RectTransform != null)
488  {
489  callback(i, new Point(x, y));
490  }
491 
492  if (useGridLayout)
493  {
494  void advanceGridLayout(
495  ref int primaryCoord,
496  ref int secondaryCoord,
497  int primaryChildDimension,
498  int secondaryChildDimension,
499  int primaryParentDimension)
500  {
501  if (primaryCoord + primaryChildDimension + Spacing > primaryParentDimension)
502  {
503  primaryCoord = 0;
504  secondaryCoord += secondaryChildDimension + Spacing;
505  callback(i, new Point(x, y));
506  }
507  primaryCoord += primaryChildDimension + Spacing;
508  }
509 
511  {
512  advanceGridLayout(
513  primaryCoord: ref y,
514  secondaryCoord: ref x,
515  primaryChildDimension: child.Rect.Height,
516  secondaryChildDimension: child.Rect.Width,
517  primaryParentDimension: Content.Rect.Height);
518  }
519  else
520  {
521  advanceGridLayout(
522  primaryCoord: ref x,
523  secondaryCoord: ref y,
524  primaryChildDimension: child.Rect.Width,
525  secondaryChildDimension: child.Rect.Height,
526  primaryParentDimension: Content.Rect.Width);
527  }
528  }
529  else
530  {
532  {
533  x += child.Rect.Width + Spacing;
534  }
535  else
536  {
537  y += child.Rect.Height + Spacing;
538  }
539  }
540  }
541  }
542 
543  private void RepositionChildren()
544  {
545  CalculateChildrenOffsets((index, offset) =>
546  {
547  var child = Content.GetChild(index);
548  if (child != draggedElement && child.RectTransform.AbsoluteOffset != offset)
549  {
550  child.RectTransform.AbsoluteOffset = offset;
551  }
552  });
553  }
554 
559  public void ScrollToElement(GUIComponent component, PlaySelectSound playSelectSound = PlaySelectSound.No)
560  {
561  if (playSelectSound == PlaySelectSound.Yes)
562  {
563  SoundPlayer.PlayUISound(GUISoundType.Select);
564  }
565  List<GUIComponent> children = Content.Children.ToList();
566  int index = children.IndexOf(component);
567  if (index < 0) { return; }
568 
569  void performScroll(GUIComponent c)
570  {
571  if (SmoothScroll && PadBottom)
572  {
573  scrollToElement = c;
574  }
575  else
576  {
577  float diff = isHorizontal ? c.Rect.X - Content.Rect.X : c.Rect.Y - Content.Rect.Y;
578  ScrollBar.BarScroll += diff / TotalSize;
579  }
580  }
581 
582  if (!Content.Children.Contains(component) || !component.Visible)
583  {
584  performScroll(null);
585  }
586  else
587  {
588  performScroll(component);
589  }
590  }
591 
592  public void ScrollToEnd(float duration)
593  {
594  CoroutineManager.StartCoroutine(ScrollCoroutine());
595 
596  IEnumerable<CoroutineStatus> ScrollCoroutine()
597  {
598  if (BarSize >= 1.0f)
599  {
600  yield return CoroutineStatus.Success;
601  }
602  float t = 0.0f;
603  float startScroll = BarScroll;
604  float distanceToTravel = ScrollBar.MaxValue - startScroll;
605  float speed = distanceToTravel / duration;
606  while (t < duration && !MathUtils.NearlyEqual(ScrollBar.MaxValue, BarScroll))
607  {
608  t += CoroutineManager.DeltaTime;
609  BarScroll += speed * CoroutineManager.DeltaTime;
610  yield return CoroutineStatus.Running;
611  }
612 
613  yield return CoroutineStatus.Success;
614  }
615  }
616 
617  private double lastDragStartTime;
618 
619  private void StartDraggingElement(GUIComponent child)
620  {
621  DraggedElement = child;
622  if (Timing.TotalTime > lastDragStartTime + 0.2f)
623  {
624  lastDragStartTime = Timing.TotalTime;
625  SoundPlayer.PlayUISound(SoundOnDragStart);
626  }
627  }
628 
629  private bool UpdateDragging()
630  {
631  if (CurrentDragMode == DragMode.NoDragging || !isDraggingElement) { return false; }
632  if (!PlayerInput.PrimaryMouseButtonHeld())
633  {
634  var draggedElem = draggedElement;
635  OnRearranged?.Invoke(this, draggedElem.UserData);
636  DraggedElement = null;
638  {
639  SoundPlayer.PlayUISound(SoundOnDragStop);
640  }
641  RepositionChildren();
642  if (AllSelected.Contains(draggedElem)) { return true; }
643  }
644  else
645  {
646  Vector2 topOffset = CalculateTopOffset();
647  var mousePos = PlayerInput.MousePosition.ToPoint();
648  draggedElement.RectTransform.AbsoluteOffset = mousePos - Content.Rect.Location - dragMousePosRelativeToTopLeftCorner;
649  if (CurrentDragMode != DragMode.DragOutsideBox)
650  {
651  var offset = draggedElement.RectTransform.AbsoluteOffset;
652  draggedElement.RectTransform.AbsoluteOffset =
653  isHorizontal ? new Point(offset.X, 0) : new Point(0, offset.Y);
654  }
655 
656  int index = Content.RectTransform.GetChildIndex(draggedElement.RectTransform);
657  int newIndex = index;
658 
659  Point draggedOffsetWhenReleased = Point.Zero;
660  CalculateChildrenOffsets((i, offset) =>
661  {
662  if (index != i) { return; }
663  draggedOffsetWhenReleased = offset;
664  });
665  Rectangle draggedRectWhenReleased = new Rectangle(Content.Rect.Location + draggedOffsetWhenReleased, draggedElement.Rect.Size);
666 
667  void shiftIndices(
668  float mousePos,
669  ref int draggedRectWhenReleasedLocation,
670  int draggedRectWhenReleasedSize)
671  {
672  while (mousePos > (draggedRectWhenReleasedLocation + draggedRectWhenReleasedSize) && newIndex < Content.CountChildren-1)
673  {
674  newIndex++;
675  draggedRectWhenReleasedLocation += draggedRectWhenReleasedSize;
676  }
677  while (mousePos < draggedRectWhenReleasedLocation && newIndex > 0)
678  {
679  newIndex--;
680  draggedRectWhenReleasedLocation -= draggedRectWhenReleasedSize;
681  }
682 
683  if (newIndex != index && AllSelected.Count > 1)
684  {
685  this.selected.Sort((a, b) => Content.GetChildIndex(a) - Content.GetChildIndex(b));
686  int draggedPos = AllSelected.IndexOf(draggedElement);
687  if (newIndex < draggedPos)
688  {
689  newIndex = draggedPos;
690  }
691  if (newIndex >= Content.CountChildren - (AllSelected.Count - draggedPos))
692  {
693  int max = Content.CountChildren - (AllSelected.Count - draggedPos);
694  newIndex = max;
695  }
696  }
697  }
698 
699  if (isHorizontal)
700  {
701  shiftIndices(
702  mousePos.X,
703  ref draggedRectWhenReleased.X,
704  draggedRectWhenReleased.Width);
705  }
706  else
707  {
708  shiftIndices(
709  mousePos.Y,
710  ref draggedRectWhenReleased.Y,
711  draggedRectWhenReleased.Height);
712  }
713 
714  if (newIndex != index)
715  {
716  if (AllSelected.Count > 1)
717  {
718  this.selected.Sort((a, b) => Content.GetChildIndex(a) - Content.GetChildIndex(b));
719  int indexOfDraggedElem = AllSelected.IndexOf(draggedElement);
720  IEnumerable<GUIComponent> allSelected = AllSelected;
721  if (newIndex > index) { allSelected = allSelected.Reverse(); }
722  foreach (var elem in allSelected)
723  {
724  elem.RectTransform.RepositionChildInHierarchy(newIndex + AllSelected.IndexOf(elem) - indexOfDraggedElem);
725  }
726  }
727  else
728  {
729  draggedElement.RectTransform.RepositionChildInHierarchy(newIndex);
730  }
732  }
733 
734  return true;
735  }
736 
737  return false;
738  }
739 
740  private void UpdateChildrenRect()
741  {
742  if (UpdateDragging()) { return; }
743 
744  if (SelectTop)
745  {
746  foreach (GUIComponent child in Content.Children)
747  {
748  child.CanBeFocused = !selected.Contains(child);
749  if (!child.CanBeFocused)
750  {
751  child.State = ComponentState.None;
752  }
753  }
754  }
755 
756  if (SelectTop && Content.Children.Any() && scrollToElement == null)
757  {
758  GUIComponent component = Content.Children.FirstOrDefault(c => (c.Rect.Y - Content.Rect.Y) / (float)c.Rect.Height > -0.1f);
759 
760  if (component != null && !selected.Contains(component))
761  {
762  int index = Content.Children.ToList().IndexOf(component);
763  if (index >= 0)
764  {
765  Select(index, autoScroll: AutoScroll.Disabled, takeKeyBoardFocus: TakeKeyBoardFocus.Yes);
766  }
767  }
768  }
769 
770  for (int i = 0; i < Content.CountChildren; i++)
771  {
772  var child = Content.RectTransform.GetChild(i)?.GUIComponent;
773  if (!(child is { Visible: true })) { continue; }
774 
775  // selecting
776  if (Enabled && (CanBeFocused || CanInteractWhenUnfocusable) && child.CanBeFocused && child.Rect.Contains(PlayerInput.MousePosition) && GUI.IsMouseOn(child))
777  {
778  child.State = ComponentState.Hover;
779 
780  var mouseDown = useMouseDownToSelect ? PlayerInput.PrimaryMouseButtonDown() : PlayerInput.PrimaryMouseButtonClicked();
781 
782  if (mouseDown)
783  {
784  if (SelectTop)
785  {
786  ScrollToElement(child);
787  }
788  Select(i, autoScroll: AutoScroll.Disabled, takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
789  }
790 
791  if (CurrentDragMode != DragMode.NoDragging
792  && (CurrentSelectMode != SelectMode.RequireShiftToSelectMultiple || (!PlayerInput.IsShiftDown() && !PlayerInput.IsCtrlDown()))
793  && PlayerInput.PrimaryMouseButtonDown() && GUI.MouseOn == child)
794  {
795  StartDraggingElement(child);
796  }
797  }
798  else if (selected.Contains(child))
799  {
800  child.State = ComponentState.Selected;
801 
802  if (CheckSelected != null)
803  {
804  if (CheckSelected() != child.UserData) selected.Remove(child);
805  }
806  }
807  else
808  {
809  child.State = !child.ExternalHighlight ? ComponentState.None : ComponentState.Hover;
810  }
811  }
812  }
813 
814  public override void AddToGUIUpdateList(bool ignoreChildren = false, int order = 0)
815  {
816  if (!Visible) { return; }
817 
818  if (!ignoreChildren)
819  {
820  foreach (GUIComponent child in Children)
821  {
822  if (child == Content || child == ScrollBar || child == ContentBackground) { continue; }
823  child.AddToGUIUpdateList(ignoreChildren, order);
824  }
825  }
826 
827  foreach (GUIComponent child in Content.Children)
828  {
829  if (!childVisible.ContainsKey(child)) { childVisible[child] = child.Visible; }
830  if (childVisible[child] != child.Visible)
831  {
832  childVisible[child] = child.Visible;
833  childrenNeedsRecalculation = true;
834  scrollBarNeedsRecalculation = true;
835  break;
836  }
837  }
838 
839  if (childrenNeedsRecalculation)
840  {
842  childVisible.Clear();
843  }
844 
845  UpdateOrder = order;
846  GUI.AddToUpdateList(this);
847 
848  if (ignoreChildren)
849  {
850  OnAddedToGUIUpdateList?.Invoke(this);
851  return;
852  }
853 
854  int lastVisible = 0;
855  for (int i = 0; i < Content.CountChildren; i++)
856  {
857  var child = Content.GetChild(i);
858  if (!child.Visible) continue;
859  if (!IsChildInsideFrame(child))
860  {
861  if (lastVisible > 0) break;
862  continue;
863  }
864  lastVisible = i;
865  child.AddToGUIUpdateList(false, order);
866  }
867  if (ScrollBar.Enabled)
868  {
869  ScrollBar.AddToGUIUpdateList(false, order);
870  }
871  OnAddedToGUIUpdateList?.Invoke(this);
872  }
873 
874  public override void ForceLayoutRecalculation()
875  {
876  base.ForceLayoutRecalculation();
879  }
880 
881  public void RecalculateChildren()
882  {
883  foreach (GUIComponent child in Content.Children)
884  {
885  ClampChildMouseRects(child);
886  }
887  RepositionChildren();
888  childrenNeedsRecalculation = false;
889  }
890 
891  private void ClampChildMouseRects(GUIComponent child)
892  {
893  child.ClampMouseRectToParent = true;
894 
895  //no need to go through grandchildren if the child is a GUIListBox, it handles this by itself
896  if (child is GUIListBox) { return; }
897 
898  foreach (GUIComponent grandChild in child.Children)
899  {
900  ClampChildMouseRects(grandChild);
901  }
902  }
903 
904  protected override void Update(float deltaTime)
905  {
906  if (!Visible) { return; }
907 
908  UpdateChildrenRect();
909  RepositionChildren();
910 
911  if (scrollBarNeedsRecalculation)
912  {
914  }
915 
916  if (FadeElements)
917  {
918  foreach (var (component, _) in childVisible)
919  {
920  float lerp = 0;
921  float y = component.Rect.Y;
922  float contentY = Content.Rect.Y;
923  float height = component.Rect.Height;
924  if (y < Content.Rect.Y)
925  {
926  float distance = (contentY - y) / height;
927  lerp = distance;
928  }
929 
930  float centerY = Content.Rect.Y + Content.Rect.Height / 2.0f;
931  if (y > centerY)
932  {
933  float distance = (y - centerY) / (centerY - height);
934  lerp = distance;
935  }
936 
937  component.Color = component.HoverColor = ToolBox.GradientLerp(lerp, component.DefaultColor, Color.Transparent);
938  component.DisabledColor = ToolBox.GradientLerp(lerp, component.Style.DisabledColor, Color.Transparent);
939  component.HoverColor = ToolBox.GradientLerp(lerp, component.Style.HoverColor, Color.Transparent);
940 
941  foreach (var child in component.GetAllChildren())
942  {
943  Color gradient = ToolBox.GradientLerp(lerp, child.DefaultColor, Color.Transparent);
944  child.Color = child.HoverColor = gradient;
945  if (child is GUITextBlock block)
946  {
947  block.TextColor = block.HoverTextColor = gradient;
948  }
949  }
950  }
951  }
952 
953  if (scrollToElement != null)
954  {
955  if (!scrollToElement.Visible || !Content.Children.Contains(scrollToElement))
956  {
957  scrollToElement = null;
958  }
959  else
960  {
961  float diff = isHorizontal ? scrollToElement.Rect.X - Content.Rect.X : scrollToElement.Rect.Y - Content.Rect.Y;
962  float speed = MathHelper.Clamp(Math.Abs(diff) * 0.1f, 5.0f, 100.0f);
963  if (Math.Abs(diff) < speed || GUIScrollBar.DraggingBar != null)
964  {
965  speed = Math.Abs(diff);
966  scrollToElement = null;
967  }
968  BarScroll += speed * Math.Sign(diff) / TotalSize;
969  }
970  }
971 
972  bool IsMouseOn() =>
973  FindScrollableParentListBox(GUI.MouseOn) == this ||
974  GUI.IsMouseOn(ScrollBar) ||
976 
977  if (PlayerInput.ScrollWheelSpeed != 0 && AllowMouseWheelScroll && IsMouseOn())
978  {
979  if (SmoothScroll)
980  {
982  {
983  bool scrollDown = Math.Clamp(PlayerInput.ScrollWheelSpeed, 0, 1) > 0;
984  if (scrollDown)
985  {
986  SelectPrevious(takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
987  }
988  else
989  {
990  SelectNext(takeKeyBoardFocus: TakeKeyBoardFocus.Yes, playSelectSound: PlaySelectSound.Yes);
991  }
992  }
993  }
994  else
995  {
997  }
998  }
999 
1001  if (AutoHideScrollBar)
1002  {
1004  }
1005  if (dimensionsNeedsRecalculation)
1006  {
1007  UpdateDimensions();
1008  }
1009  }
1010 
1011  private static GUIListBox FindScrollableParentListBox(GUIComponent target)
1012  {
1013  if (target is GUIListBox listBox && listBox.ScrollBarEnabled && listBox.BarSize < 1.0f) { return listBox; }
1014  if (target?.Parent == null) { return null; }
1015  return FindScrollableParentListBox(target.Parent);
1016  }
1017 
1018  public void SelectNext(Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus = TakeKeyBoardFocus.No, PlaySelectSound playSelectSound = PlaySelectSound.No)
1019  {
1020  int index = SelectedIndex + 1;
1021  while (index < Content.CountChildren)
1022  {
1023  GUIComponent child = Content.GetChild(index);
1024  if (child.Visible)
1025  {
1026  Select(index, force, GetAutoScroll(!SmoothScroll && autoScroll == AutoScroll.Enabled), takeKeyBoardFocus, playSelectSound);
1027  if (SmoothScroll)
1028  {
1029  ScrollToElement(child, playSelectSound);
1030  }
1031  break;
1032  }
1033  index++;
1034  }
1035  }
1036 
1037  public void SelectPrevious(Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus = TakeKeyBoardFocus.No, PlaySelectSound playSelectSound = PlaySelectSound.No)
1038  {
1039  int index = SelectedIndex - 1;
1040  while (index >= 0)
1041  {
1042  GUIComponent child = Content.GetChild(index);
1043  if (child.Visible)
1044  {
1045  Select(index, force, GetAutoScroll(!SmoothScroll && autoScroll == AutoScroll.Enabled), takeKeyBoardFocus, playSelectSound);
1046  if (SmoothScroll)
1047  {
1048  ScrollToElement(child, playSelectSound);
1049  }
1050  break;
1051  }
1052  index--;
1053  }
1054  }
1055 
1056  public void Select(int childIndex, Force force = Force.No, AutoScroll autoScroll = AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus = TakeKeyBoardFocus.No, PlaySelectSound playSelectSound = PlaySelectSound.No)
1057  {
1058  if (childIndex >= Content.CountChildren || childIndex < 0 || CurrentSelectMode == SelectMode.None) { return; }
1059 
1060  GUIComponent child = Content.GetChild(childIndex);
1061  if (child is null) { return; }
1062  if (!child.Enabled) { return; }
1063 
1064  bool wasSelected = true;
1065  if (OnSelected != null)
1066  {
1067  // TODO: The callback is called twice, fix this!
1068  wasSelected = force == Force.Yes || OnSelected(child, child.UserData);
1069  }
1070 
1071  if (!wasSelected) { return; }
1072 
1073  if (CurrentSelectMode == SelectMode.SelectMultiple ||
1074  (CurrentSelectMode == SelectMode.RequireShiftToSelectMultiple && PlayerInput.IsCtrlDown()))
1075  {
1076  if (selected.Contains(child))
1077  {
1078  selected.Remove(child);
1079  }
1080  else
1081  {
1082  selected.Add(child);
1083  }
1084  }
1085  else if (CurrentSelectMode == SelectMode.RequireShiftToSelectMultiple && PlayerInput.IsShiftDown())
1086  {
1087  var first = SelectedComponent ?? child;
1088  var last = child;
1089  int firstIndex = Content.GetChildIndex(first);
1090  int lastIndex = Content.GetChildIndex(last);
1091  int sgn = Math.Sign(lastIndex - firstIndex);
1092  selected.Clear(); selected.Add(first);
1093  for (int i = firstIndex + sgn; i != lastIndex; i += sgn)
1094  {
1095  if (Content.GetChild(i) is { Visible: true } interChild)
1096  {
1097  selected.Add(interChild);
1098  }
1099  }
1100  if (first != last) { selected.Add(last); }
1101  }
1102  else
1103  {
1104  selected.Clear();
1105  selected.Add(child);
1106  }
1107 
1108  // Ensure that the selected element is visible. This may not be the case, if the selection is run from code. (e.g. if we have two list boxes that are synced)
1109  // TODO: This method only works when moving one item up/down (e.g. when using the up and down arrows)
1110  if (autoScroll == AutoScroll.Enabled)
1111  {
1112  if (ScrollBar.IsHorizontal)
1113  {
1114  if (child.Rect.X < MouseRect.X)
1115  {
1116  //child outside the left edge of the frame -> move left
1117  ScrollBar.BarScroll -= (float)(MouseRect.X - child.Rect.X) / (totalSize - Content.Rect.Width);
1118  }
1119  else if (child.Rect.Right > MouseRect.Right)
1120  {
1121  //child outside the right edge of the frame -> move right
1122  ScrollBar.BarScroll += (float)(child.Rect.Right - MouseRect.Right) / (totalSize - Content.Rect.Width);
1123  }
1124  }
1125  else
1126  {
1127  if (child.Rect.Y < MouseRect.Y)
1128  {
1129  //child above the top of the frame -> move up
1130  ScrollBar.BarScroll -= (float)(MouseRect.Y - child.Rect.Y) / (totalSize - Content.Rect.Height);
1131  }
1132  else if (child.Rect.Bottom > MouseRect.Bottom)
1133  {
1134  //child below the bottom of the frame -> move down
1135  ScrollBar.BarScroll += (float)(child.Rect.Bottom - MouseRect.Bottom) / (totalSize - Content.Rect.Height);
1136  }
1137  }
1138  }
1139 
1140  // If one of the children is the subscriber, we don't want to register, because it will unregister the child.
1141  if (takeKeyBoardFocus == TakeKeyBoardFocus.Yes && CanTakeKeyBoardFocus && RectTransform.GetAllChildren().None(rt => rt.GUIComponent == GUI.KeyboardDispatcher.Subscriber))
1142  {
1143  Selected = true;
1144  GUI.KeyboardDispatcher.Subscriber = this;
1145  }
1146 
1147  // List box child components can be parents to other components that can play sounds when selected (e.g. store elements)
1148  // so the list box shouldn't play the Select sound if the GUI.MouseOn component has a sound to play
1149  if (playSelectSound == PlaySelectSound.Yes && PlaySoundOnSelect && !child.PlaySoundOnSelect &&
1150  (GUI.MouseOn == null || GUI.MouseOn.Parent == Content || !GUI.MouseOn.PlaySoundOnSelect))
1151  {
1152  SoundPlayer.PlayUISound(GUISoundType.Select);
1153  }
1154  }
1155 
1156  public void Select(IEnumerable<GUIComponent> children)
1157  {
1158  if (CurrentSelectMode == SelectMode.None) { return; }
1159  Selected = true;
1160  selected.Clear();
1161  selected.AddRange(children.Where(c => Content.Children.Contains(c)));
1162  foreach (var child in selected) { OnSelected?.Invoke(child, child.UserData); }
1163  }
1164 
1165  public void Deselect()
1166  {
1167  Selected = false;
1168  if (GUI.KeyboardDispatcher.Subscriber == this)
1169  {
1170  GUI.KeyboardDispatcher.Subscriber = null;
1171  }
1172  selected.Clear();
1173  }
1174 
1175  public void UpdateScrollBarSize()
1176  {
1177  scrollBarNeedsRecalculation = false;
1178  if (Content == null) { return; }
1179 
1180  totalSize = 0;
1181  var children = Content.Children.Where(c => c.Visible);
1182  if (useGridLayout)
1183  {
1184  int pos = 0;
1185  foreach (GUIComponent child in children)
1186  {
1187  if (ScrollBar.IsHorizontal)
1188  {
1189  if (pos + child.Rect.Height + Spacing > Content.Rect.Height)
1190  {
1191  pos = 0;
1192  totalSize += child.Rect.Width + Spacing;
1193  }
1194  pos += child.Rect.Height + Spacing;
1195 
1196  if (child == children.Last())
1197  {
1198  totalSize += child.Rect.Width + Spacing;
1199  }
1200  }
1201  else
1202  {
1203  if (pos + child.Rect.Width + Spacing > Content.Rect.Width)
1204  {
1205  pos = 0;
1206  totalSize += child.Rect.Height + Spacing;
1207  }
1208  pos += child.Rect.Width + Spacing;
1209 
1210  if (child == children.Last())
1211  {
1212  totalSize += child.Rect.Height + Spacing;
1213  }
1214  }
1215  }
1216  }
1217  else
1218  {
1219  foreach (GUIComponent child in children)
1220  {
1221  totalSize += (ScrollBar.IsHorizontal) ? child.Rect.Width : child.Rect.Height;
1222  }
1223  totalSize += Content.CountChildren * Spacing;
1224  if (PadBottom)
1225  {
1226  GUIComponent last = Content.Children.LastOrDefault();
1227  if (last != null)
1228  {
1229  totalSize += Rect.Height - last.Rect.Height;
1230  }
1231  }
1232  }
1233 
1234  float minScrollBarSize = 20.0f;
1236  Math.Min(Content.Rect.Width / (float)totalSize, 1.0f) :
1237  Math.Min(Content.Rect.Height / (float)totalSize, 1.0f);
1239  Math.Max(ScrollBar.UnclampedBarSize, minScrollBarSize / Content.Rect.Width) :
1240  Math.Max(ScrollBar.UnclampedBarSize, minScrollBarSize / Content.Rect.Height);
1241  }
1242 
1243  public override void ClearChildren()
1244  {
1246  selected.Clear();
1247  }
1248 
1249  public override void RemoveChild(GUIComponent child)
1250  {
1251  if (child == null) { return; }
1252  child.RectTransform.Parent = null;
1253  if (selected.Contains(child)) { selected.Remove(child); }
1254  if (draggedElement == child) { DraggedElement = null; }
1256  }
1257 
1258  public override void DrawChildren(SpriteBatch spriteBatch, bool recursive)
1259  {
1260  //do nothing (the children have to be drawn in the Draw method after the ScissorRectangle has been set)
1261  return;
1262  }
1263 
1264  protected override void Draw(SpriteBatch spriteBatch)
1265  {
1266  if (!Visible) { return; }
1267 
1268  ContentBackground.DrawManually(spriteBatch, alsoChildren: false);
1269 
1270  Rectangle prevScissorRect = spriteBatch.GraphicsDevice.ScissorRectangle;
1272  {
1273  spriteBatch.End();
1274  spriteBatch.GraphicsDevice.ScissorRectangle = Rectangle.Intersect(prevScissorRect, Content.Rect);
1275  spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
1276  }
1277 
1278  int lastVisible = 0;
1279 
1280  int i = 0;
1281  foreach (GUIComponent child in Content.Children)
1282  {
1283  if (!child.Visible) { continue; }
1284  if (child == draggedElement && CurrentDragMode == DragMode.DragOutsideBox) { continue; }
1285  if (!IsChildInsideFrame(child))
1286  {
1287  if (lastVisible > 0) { break; }
1288  continue;
1289  }
1290  lastVisible = i;
1291  child.DrawManually(spriteBatch, alsoChildren: true, recursive: true);
1292  i++;
1293  }
1294 
1295  if (isDraggingElement && CurrentDragMode == DragMode.DragOutsideBox && HideDraggedElement)
1296  {
1297  Rectangle drawRect = DraggedElement.Rect;
1298  int draggedElementIndex = Content.GetChildIndex(DraggedElement);
1299  CalculateChildrenOffsets((index, point) =>
1300  {
1301  if (draggedElementIndex == index)
1302  {
1303  drawRect.Location = Content.Rect.Location + point;
1304  }
1305  });
1306  GUI.DrawRectangle(spriteBatch, drawRect, Color.White * 0.5f, thickness: 2f);
1307  }
1308 
1310  {
1311  spriteBatch.End();
1312  spriteBatch.GraphicsDevice.ScissorRectangle = prevScissorRect;
1313  spriteBatch.Begin(SpriteSortMode.Deferred, samplerState: GUI.SamplerState, rasterizerState: GameMain.ScissorTestEnable);
1314  }
1315 
1316  if (isDraggingElement && CurrentDragMode == DragMode.DragOutsideBox && !HideDraggedElement)
1317  {
1318  draggedElement.DrawManually(spriteBatch, alsoChildren: true, recursive: true);
1319  }
1320 
1321  if (ScrollBarVisible)
1322  {
1323  ScrollBar.DrawManually(spriteBatch, alsoChildren: true, recursive: true);
1324  }
1325  }
1326 
1327  private bool IsChildInsideFrame(GUIComponent child)
1328  {
1329  if (child == null) { return false; }
1330 
1331  if (ScrollBar.IsHorizontal)
1332  {
1333  if (child.Rect.Right < Content.Rect.X) { return false; }
1334  if (child.Rect.X > Content.Rect.Right) { return false; }
1335  }
1336  else
1337  {
1338  if (child.Rect.Bottom < Content.Rect.Y) { return false; }
1339  if (child.Rect.Y > Content.Rect.Bottom) { return false; }
1340  }
1341 
1342  return true;
1343  }
1344 
1345  public void ReceiveTextInput(char inputChar)
1346  {
1347  GUI.KeyboardDispatcher.Subscriber = null;
1348  }
1349  public void ReceiveTextInput(string text) { }
1350  public void ReceiveCommandInput(char command) { }
1351  public void ReceiveEditingInput(string text, int start, int length) { }
1352 
1353  public void ReceiveSpecialInput(Keys key)
1354  {
1355  switch (key)
1356  {
1357  case Keys.Down:
1358  if (!isHorizontal && AllowArrowKeyScroll) { SelectNext(playSelectSound: PlaySelectSound.Yes); }
1359  break;
1360  case Keys.Up:
1361  if (!isHorizontal && AllowArrowKeyScroll) { SelectPrevious(playSelectSound: PlaySelectSound.Yes); }
1362  break;
1363  case Keys.Left:
1364  if (isHorizontal && AllowArrowKeyScroll) { SelectPrevious(playSelectSound: PlaySelectSound.Yes); }
1365  break;
1366  case Keys.Right:
1367  if (isHorizontal && AllowArrowKeyScroll) { SelectNext(playSelectSound: PlaySelectSound.Yes); }
1368  break;
1369  default:
1370  GUI.KeyboardDispatcher.Subscriber = null;
1371  break;
1372  }
1373  }
1374  }
1375 }
static CoroutineStatus Running
static CoroutineStatus Success
virtual void ForceLayoutRecalculation()
GUIComponent(string style, RectTransform rectT)
This is the new constructor.
GUIComponent GetChild(int index)
Definition: GUIComponent.cs:54
virtual ComponentState State
virtual void AddToGUIUpdateList(bool ignoreChildren=false, int order=0)
Rectangle ClampRect(Rectangle r)
virtual bool PlaySoundOnSelect
Action< GUIComponent > OnAddedToGUIUpdateList
virtual void ClearChildren()
int GetChildIndex(GUIComponent child)
Definition: GUIComponent.cs:60
virtual void DrawManually(SpriteBatch spriteBatch, bool alsoChildren=false, bool recursive=true)
By default, all the gui elements are drawn automatically in the same order they appear on the update ...
virtual Rectangle Rect
IEnumerable< GUIComponent > GetAllChildren()
Returns all child elements in the hierarchy.
Definition: GUIComponent.cs:49
GUIComponentStyle Style
RectTransform RectTransform
IEnumerable< GUIComponent > Children
Definition: GUIComponent.cs:29
override void RemoveChild(GUIComponent child)
Definition: GUIListBox.cs:1249
void Select(IEnumerable< GUIComponent > children)
Definition: GUIListBox.cs:1156
OnRearrangedHandler OnRearranged
Definition: GUIListBox.cs:23
List< GUIComponent > selected
Definition: GUIListBox.cs:14
override void AddToGUIUpdateList(bool ignoreChildren=false, int order=0)
Definition: GUIListBox.cs:814
GUIComponent DraggedElement
Definition: GUIListBox.cs:269
bool ClampScrollToElements
Whether to only allow scrolling from one element to the next when smooth scrolling is enabled
Definition: GUIListBox.cs:95
void SelectNext(Force force=Force.No, AutoScroll autoScroll=AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus=TakeKeyBoardFocus.No, PlaySelectSound playSelectSound=PlaySelectSound.No)
Definition: GUIListBox.cs:1018
void ReceiveTextInput(string text)
Definition: GUIListBox.cs:1349
override bool PlaySoundOnSelect
Definition: GUIListBox.cs:314
Vector2 CalculateTopOffset()
Definition: GUIListBox.cs:458
bool ResizeContentToMakeSpaceForScrollBar
Definition: GUIListBox.cs:77
DragMode CurrentDragMode
Definition: GUIListBox.cs:247
void ScrollToEnd(float duration)
Definition: GUIListBox.cs:592
void ReceiveTextInput(char inputChar)
Definition: GUIListBox.cs:1345
bool ScrollBarEnabled
Disables the scroll bar without hiding it.
Definition: GUIListBox.cs:213
bool SmoothScroll
Scrolls the list smoothly
Definition: GUIListBox.cs:90
GUIScrollBar ScrollBar
Definition: GUIListBox.cs:34
override void DrawChildren(SpriteBatch spriteBatch, bool recursive)
Draws all the children manually.
Definition: GUIListBox.cs:1258
CheckSelectedHandler CheckSelected
Definition: GUIListBox.cs:20
GUIFrame ContentBackground
A frame drawn behind the content of the listbox
Definition: GUIListBox.cs:28
override void Draw(SpriteBatch spriteBatch)
Definition: GUIListBox.cs:1264
GUIComponent SelectedComponent
Definition: GUIListBox.cs:146
void ReceiveCommandInput(char command)
Definition: GUIListBox.cs:1350
override void Update(float deltaTime)
Definition: GUIListBox.cs:904
bool HasDraggedElementIndexChanged
Definition: GUIListBox.cs:266
OnSelectedHandler OnSelected
Definition: GUIListBox.cs:17
delegate bool OnSelectedHandler(GUIComponent component, object obj)
bool CanInteractWhenUnfocusable
Setting this to true and CanBeFocused to false allows the list background to be unfocusable while the...
Definition: GUIListBox.cs:303
bool PadBottom
Adds enough extra padding to the bottom so the end of the scroll will only contain the last element
Definition: GUIListBox.cs:105
GUIFrame Content
A frame that contains the contents of the listbox. The frame itself is not rendered.
Definition: GUIListBox.cs:33
GUISoundType? SoundOnDragStop
Definition: GUIListBox.cs:320
override bool Selected
Definition: GUIListBox.cs:154
IReadOnlyList< GUIComponent > AllSelected
Definition: GUIListBox.cs:159
void ScrollToElement(GUIComponent component, PlaySelectSound playSelectSound=PlaySelectSound.No)
Scrolls the list to the specific element.
Definition: GUIListBox.cs:559
void Select(object userData, Force force=Force.No, AutoScroll autoScroll=AutoScroll.Enabled)
Definition: GUIListBox.cs:440
void SelectPrevious(Force force=Force.No, AutoScroll autoScroll=AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus=TakeKeyBoardFocus.No, PlaySelectSound playSelectSound=PlaySelectSound.No)
Definition: GUIListBox.cs:1037
void ReceiveEditingInput(string text, int start, int length)
Definition: GUIListBox.cs:1351
SelectMode CurrentSelectMode
Definition: GUIListBox.cs:64
void Select(int childIndex, Force force=Force.No, AutoScroll autoScroll=AutoScroll.Enabled, TakeKeyBoardFocus takeKeyBoardFocus=TakeKeyBoardFocus.No, PlaySelectSound playSelectSound=PlaySelectSound.No)
Definition: GUIListBox.cs:1056
GUISoundType? SoundOnDragStart
Definition: GUIListBox.cs:318
bool AutoHideScrollBar
Automatically hides the scroll bar when the content fits in.
Definition: GUIListBox.cs:235
bool FadeElements
When set to true elements at the bottom of the list are gradually faded
Definition: GUIListBox.cs:100
bool SelectTop
When set to true always selects the topmost item on the list
Definition: GUIListBox.cs:110
override void ForceLayoutRecalculation()
Definition: GUIListBox.cs:874
GUIListBox(RectTransform rectT, bool isHorizontal=false, Color? color=null, string style="", bool isScrollBarOnDefaultSide=true, bool useMouseDownToSelect=false)
For horizontal listbox, default side is on the bottom. For vertical, it's on the right.
Definition: GUIListBox.cs:354
delegate object CheckSelectedHandler()
override Rectangle? MouseRect
Definition: GUIListBox.cs:306
delegate void OnRearrangedHandler(GUIListBox listBox, object obj)
override void ClearChildren()
Definition: GUIListBox.cs:1243
void ReceiveSpecialInput(Keys key)
Definition: GUIListBox.cs:1353
override bool Enabled
Definition: GUIScrollBar.cs:76
static GUIScrollBar DraggingBar
Definition: GUIScrollBar.cs:10
float UnclampedBarSize
ListBoxes with lots of content in them clamp the size of the scrollbar above a certain minimum size; ...
static RasterizerState ScissorTestEnable
Definition: GameMain.cs:195
void SetPosition(Anchor anchor, Pivot? pivot=null)
GUIComponent GUIComponent
Should be assigned only by GUIComponent. Note that RectTransform is created first and the GUIComponen...
IEnumerable< RectTransform > GetAllChildren()
Returns all child elements in the hierarchy.
Point AbsoluteOffset
Absolute in pixels but relative to the anchor point. Calculated away from the anchor point,...
void Resize(Point absoluteSize, bool resizeChildren=true)
RectTransform GetChild(int index)
RectTransform?? Parent
bool RepositionChildInHierarchy(int index)
Action< RectTransform > ChildrenChanged
The element provided as the argument is the changed child. It may be new in the hierarchy or just rep...
int GetChildIndex(RectTransform rectT)
GUISoundType
Definition: GUI.cs:21
CursorState
Definition: GUI.cs:40