418 lines
14 KiB
C#
418 lines
14 KiB
C#
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using RecrownedAthenaeum.Input;
|
|
using RecrownedAthenaeum.Render;
|
|
using RecrownedAthenaeum.SpecialTypes;
|
|
using RecrownedAthenaeum.UI.SkinSystem;
|
|
using RecrownedAthenaeum.UI.SkinSystem.Definitions;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace RecrownedAthenaeum.UI.Modular.Modules
|
|
{
|
|
public class UIScrollable : UIModule
|
|
{
|
|
UIModuleGroup group;
|
|
|
|
Color scrollBarColor;
|
|
float opacityOfBar = 1;
|
|
bool showingBars;
|
|
private bool mouseWasPressed;
|
|
private bool horizontalSelected;
|
|
private Vector2 mouseRelativePosition;
|
|
float shiftX, shiftY;
|
|
int furthestX;
|
|
int furthestY;
|
|
UIModule furthestXModule, furthestYMod;
|
|
|
|
bool horScrollAvailable, vertScrollAvailable;
|
|
|
|
Rectangle horizontalScrollBarBounds, verticalScrollBarBounds;
|
|
/// <summary>
|
|
/// How fast the bars fade away in opacity (0 to 254) per second.
|
|
/// </summary>
|
|
public float barFadeSpeed = 250;
|
|
|
|
ISpecialDrawable horizontalScrollBar, verticalScrollBar;
|
|
ISpecialDrawable background, horizontalBarTrack, verticalBarTrack;
|
|
|
|
private int topPadding, bottomPadding, leftPadding, rightPadding;
|
|
public int PadTop { get { return topPadding; } set { topPadding = value; HeightOrYChange(); } }
|
|
public int PadBottom { get { return bottomPadding; } set { bottomPadding = value; HeightOrYChange(); } }
|
|
public int PadLeft { get { return leftPadding; } set { leftPadding = value; WidthOrXChange(); } }
|
|
public int PadRight { get { return rightPadding; } set { rightPadding = value; WidthOrXChange(); } }
|
|
|
|
/// <summary>
|
|
/// The minimum bar length for the scroll bar.
|
|
/// </summary>
|
|
public int minimumBarLength = 16;
|
|
|
|
public int HorizontalBarThickness { get { return horizontalScrollBarBounds.Height; } set { horizontalScrollBarBounds.Height = value; HeightOrYChange(); } }
|
|
public int VerticalBarThickness { get { return verticalScrollBarBounds.Width; } set { verticalScrollBarBounds.Width = value; WidthOrXChange(); } }
|
|
|
|
/// <summary>
|
|
/// Whether or not to hide scroll bars.
|
|
/// </summary>
|
|
public bool HideScrollBars
|
|
{
|
|
get { return hideScrollBars; }
|
|
set
|
|
{
|
|
hideScrollBars = value;
|
|
WidthOrXChange(true);
|
|
HeightOrYChange(true);
|
|
if (!value)
|
|
{
|
|
opacityOfBar = 1f;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool hideScrollBars = true;
|
|
|
|
/// <summary>
|
|
/// Set to true to change from the normal position to the new position.
|
|
/// </summary>
|
|
public bool verticalBarLeftPosition, horizontalBarTopPosition;
|
|
|
|
|
|
public override int Width
|
|
{
|
|
get
|
|
{
|
|
return base.Width;
|
|
}
|
|
set
|
|
{
|
|
base.Width = value;
|
|
WidthOrXChange();
|
|
}
|
|
}
|
|
|
|
public override int Height
|
|
{
|
|
get
|
|
{
|
|
return base.Height;
|
|
}
|
|
set
|
|
{
|
|
base.Height = value;
|
|
HeightOrYChange();
|
|
}
|
|
}
|
|
|
|
public override int X
|
|
{
|
|
get
|
|
{
|
|
return base.X;
|
|
}
|
|
set
|
|
{
|
|
WidthOrXChange(true);
|
|
base.X = value;
|
|
}
|
|
}
|
|
|
|
public override int Y
|
|
{
|
|
get
|
|
{
|
|
return base.Y;
|
|
}
|
|
set
|
|
{
|
|
HeightOrYChange(true);
|
|
base.Y = value;
|
|
}
|
|
}
|
|
|
|
public UIScrollable(ISpecialDrawable horizontalScrollBar, ISpecialDrawable verticalScrollBar, ISpecialDrawable horizontalBarTrack = null, ISpecialDrawable verticalBarTrack = null, ISpecialDrawable background = null)
|
|
{
|
|
this.horizontalScrollBar = horizontalScrollBar;
|
|
this.verticalScrollBar = verticalScrollBar;
|
|
this.horizontalBarTrack = horizontalBarTrack;
|
|
this.verticalBarTrack = verticalBarTrack;
|
|
this.background = background;
|
|
|
|
group = new UIModuleGroup(new BasicScissor());
|
|
HorizontalBarThickness = 12;
|
|
VerticalBarThickness = 12;
|
|
}
|
|
|
|
public UIScrollable(ISkin skin, string definition = null) :
|
|
this(skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().horizontalBar, true),
|
|
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().verticalBar, true),
|
|
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().horizontalBarTrack),
|
|
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().verticalBarTrack),
|
|
skin.GetTextureAtlasRegion(skin.ObtainDefinition<UIScrollableSkinDefinition>().background))
|
|
{
|
|
}
|
|
|
|
public override void Update(GameTime gameTime)
|
|
{
|
|
if (hideScrollBars)
|
|
{
|
|
if (!showingBars && !mouseWasPressed)
|
|
{
|
|
if (opacityOfBar > 0f)
|
|
{
|
|
opacityOfBar -= (barFadeSpeed / 255f) * (float)gameTime.ElapsedGameTime.TotalSeconds;
|
|
scrollBarColor = color * opacityOfBar;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
opacityOfBar = 1f;
|
|
scrollBarColor = color * opacityOfBar;
|
|
}
|
|
}
|
|
|
|
if (horScrollAvailable)
|
|
{
|
|
horizontalScrollBarBounds.X = (int)(((float)-shiftX / furthestX) * (group.Width - horizontalScrollBarBounds.Width));
|
|
}
|
|
|
|
if (vertScrollAvailable)
|
|
{
|
|
verticalScrollBarBounds.Y = (int)(((float)-shiftY / furthestY) * (group.Height - verticalScrollBarBounds.Height));
|
|
}
|
|
|
|
base.Update(gameTime);
|
|
}
|
|
|
|
public override void Draw(ConsistentSpriteBatch spriteBatch)
|
|
{
|
|
background?.Draw(spriteBatch, Boundaries, color, origin: origin);
|
|
|
|
group.Draw(spriteBatch);
|
|
|
|
if (horScrollAvailable)
|
|
{
|
|
horizontalScrollBar.Draw(spriteBatch, horizontalScrollBarBounds, scrollBarColor);
|
|
}
|
|
if (vertScrollAvailable)
|
|
{
|
|
horizontalScrollBar.Draw(spriteBatch, verticalScrollBarBounds, scrollBarColor);
|
|
}
|
|
base.Draw(spriteBatch);
|
|
}
|
|
|
|
public void AddModules(params UIModule[] addModules)
|
|
{
|
|
group.AddModules(addModules);
|
|
|
|
for (int i = 0; i < addModules.Length; i++)
|
|
{
|
|
UIModule m = addModules[i];
|
|
int mFurthestX = m.Boundaries.X + m.Boundaries.Width;
|
|
int mFurthestY = m.Boundaries.Y + m.Boundaries.Height;
|
|
if (mFurthestX > furthestX)
|
|
{
|
|
furthestXModule = m;
|
|
furthestX = mFurthestX;
|
|
}
|
|
if (mFurthestY > furthestY)
|
|
{
|
|
furthestYMod = m;
|
|
furthestY = mFurthestY;
|
|
}
|
|
}
|
|
|
|
WidthOrXChange();
|
|
HeightOrYChange();
|
|
}
|
|
|
|
public void RemoveModule(UIModule module)
|
|
{
|
|
group.RemoveModule(module);
|
|
|
|
if (module == furthestXModule)
|
|
{
|
|
furthestX = 0;
|
|
UIModule[] modules = group.GetCopyOfModules();
|
|
for (int i = 0; i < modules.Length; i++)
|
|
{
|
|
UIModule m = modules[i];
|
|
int mFurthestX = m.Boundaries.X + m.Boundaries.Width;
|
|
if (mFurthestX > furthestX)
|
|
{
|
|
furthestXModule = m;
|
|
furthestX = mFurthestX;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (module == furthestYMod)
|
|
{
|
|
furthestY = 0;
|
|
UIModule[] modules = group.GetCopyOfModules();
|
|
|
|
for (int i = 0; i < modules.Length; i++)
|
|
{
|
|
UIModule m = modules[i];
|
|
int mFurthestY = m.Boundaries.Y + m.Boundaries.Height;
|
|
if (mFurthestY > furthestY)
|
|
{
|
|
furthestYMod = m;
|
|
furthestY = mFurthestY;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void WidthOrXChange(bool onlyXChange = false)
|
|
{
|
|
group.X = X + leftPadding;
|
|
if (!onlyXChange)
|
|
{
|
|
group.Width = Width - rightPadding - leftPadding;
|
|
if (Width < furthestX)
|
|
{
|
|
horScrollAvailable = true;
|
|
horizontalScrollBarBounds.Width = (int)(Width * ((float)Width / furthestX));
|
|
horizontalScrollBarBounds.Width = Math.Max(horizontalScrollBarBounds.Width, minimumBarLength);
|
|
}
|
|
else { horScrollAvailable = false; }
|
|
|
|
verticalScrollBarBounds.X = X;
|
|
if (!hideScrollBars)
|
|
{
|
|
group.Width -= VerticalBarThickness;
|
|
if (!verticalBarLeftPosition)
|
|
{
|
|
verticalScrollBarBounds.X += group.Width;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!verticalBarLeftPosition)
|
|
{
|
|
verticalScrollBarBounds.X += group.Width - verticalScrollBarBounds.Width;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void HeightOrYChange(bool onlyYChange = false)
|
|
{
|
|
group.Y = Y + bottomPadding;
|
|
if (!onlyYChange)
|
|
{
|
|
group.Height = Height - bottomPadding - topPadding;
|
|
if (Height < furthestY)
|
|
{
|
|
vertScrollAvailable = true;
|
|
verticalScrollBarBounds.Height = (int)(Height * ((float)Height / furthestY));
|
|
verticalScrollBarBounds.Height = Math.Max(verticalScrollBarBounds.Height, minimumBarLength);
|
|
}
|
|
else { vertScrollAvailable = false; }
|
|
|
|
horizontalScrollBarBounds.Y = Y;
|
|
if (!hideScrollBars)
|
|
{
|
|
group.Height -= HorizontalBarThickness;
|
|
if (!horizontalBarTopPosition)
|
|
{
|
|
horizontalScrollBarBounds.Y += group.Height;
|
|
}
|
|
else
|
|
{
|
|
group.Y += horizontalScrollBarBounds.Height;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!horizontalBarTopPosition)
|
|
{
|
|
horizontalScrollBarBounds.Y += group.Height - horizontalScrollBarBounds.Height;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public override bool KeyboardStateChanged(KeyboardState state)
|
|
{
|
|
if (state.IsKeyDown(Keys.Right))
|
|
{
|
|
shiftX -= 20;
|
|
}
|
|
|
|
return base.KeyboardStateChanged(state);
|
|
}
|
|
|
|
public override bool MouseStateChanged(MouseState state)
|
|
{
|
|
if (InputUtilities.MouseWithinBoundries(Boundaries))
|
|
{
|
|
showingBars = true;
|
|
}
|
|
else
|
|
{
|
|
showingBars = false;
|
|
}
|
|
|
|
if (InputUtilities.MouseWithinBoundries(horizontalScrollBarBounds))
|
|
{
|
|
if (state.LeftButton == ButtonState.Pressed)
|
|
{
|
|
mouseWasPressed = true;
|
|
horizontalSelected = true;
|
|
}
|
|
if (!mouseWasPressed)
|
|
{
|
|
mouseRelativePosition.X = state.X - horizontalScrollBarBounds.X;
|
|
}
|
|
}
|
|
|
|
if (InputUtilities.MouseWithinBoundries(verticalScrollBarBounds))
|
|
{
|
|
if (state.LeftButton == ButtonState.Pressed)
|
|
{
|
|
mouseWasPressed = true;
|
|
horizontalSelected = false;
|
|
}
|
|
if (!mouseWasPressed)
|
|
{
|
|
mouseRelativePosition.Y = state.Y - verticalScrollBarBounds.Y;
|
|
}
|
|
}
|
|
|
|
if (mouseWasPressed)
|
|
{
|
|
if (horizontalSelected)
|
|
{
|
|
float latestPosition = state.X - mouseRelativePosition.X;
|
|
shiftX = -(latestPosition / (Width - horizontalScrollBarBounds.Width)) * furthestX;
|
|
}
|
|
else
|
|
{
|
|
float latestPosition = state.Y - mouseRelativePosition.Y;
|
|
shiftY = -(latestPosition / (Height - verticalScrollBarBounds.Height)) * furthestY;
|
|
}
|
|
|
|
if (state.LeftButton == ButtonState.Released)
|
|
{
|
|
mouseWasPressed = false;
|
|
}
|
|
}
|
|
return base.MouseStateChanged(state);
|
|
}
|
|
|
|
private void MoveHorizontalScrollBar(int position)
|
|
{
|
|
shiftX = -(int)(furthestX * ((float)position / Width));
|
|
}
|
|
|
|
private void MoveVerticalScrollBar(int position)
|
|
{
|
|
shiftY = (int)(furthestY * ((float)position / Height));
|
|
}
|
|
}
|
|
}
|