Files
OpenRA/OpenRA.Game/Widgets/SliderWidget.cs
2011-06-29 09:15:39 +12:00

204 lines
5.0 KiB
C#
Executable File

#region Copyright & License Information
/*
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Drawing;
using OpenRA.Graphics;
namespace OpenRA.Widgets
{
public class SliderWidget : Widget
{
public Func<bool> IsDisabled = () => false;
public event Action<float> OnChange;
public Func<float> GetOffset;
public int Ticks = 0;
public int TrackHeight = 5;
// TODO: Changing this breaks the semantics of Get/SetOffset
// This is bogus
public float2 Range = new float2(0f, 1f);
float Offset = 0;
int2 lastMouseLocation;
protected bool isMoving = false;
public SliderWidget()
: base()
{
GetOffset = () =>
{
var Big = Math.Max(Range.X, Range.Y);
var Little = Math.Min(Range.X, Range.Y);
var Spread = Big - Little;
return Spread * Offset + Little;
};
OnChange = x => Offset = x.Clamp(0f, 1f);
}
public SliderWidget(SliderWidget other)
: base(other)
{
OnChange = other.OnChange;
GetOffset = other.GetOffset;
Ticks = other.Ticks;
Range = other.Range;
Offset = GetOffset();
TrackHeight = other.TrackHeight;
lastMouseLocation = other.lastMouseLocation;
isMoving = other.isMoving;
}
public void SetOffset(float newOffset)
{
var Big = Math.Max(Range.X, Range.Y);
var Little = Math.Min(Range.X, Range.Y);
var Spread = Big - Little;
Offset = ((newOffset - Little) / Spread).Clamp(0f, 1f);
}
public override bool HandleMouseInput(MouseInput mi)
{
if (mi.Button != MouseButton.Left)
return false;
if (mi.Event == MouseInputEvent.Down && !TakeFocus(mi))
return false;
if (!Focused)
return false;
switch (mi.Event)
{
case MouseInputEvent.Up:
{
if (Focused)
{
isMoving = false;
base.LoseFocus(mi);
}
}
break;
case MouseInputEvent.Down:
{
if (thumbRect.Contains(mi.Location))
{
isMoving = true;
lastMouseLocation = mi.Location;
}
else if (Ticks != 0)
{
var pos = Offset;
// Offset slightly the direction we want to move so we don't get stuck on a tick
var delta = 0.001;
var targetTick = (float)((mi.Location.X > thumbRect.Right) ? Math.Ceiling((pos + delta) * (Ticks - 1))
: Math.Floor((pos - delta) * (Ticks - 1)));
OnChange(targetTick / (Ticks - 1));
if (thumbRect.Contains(mi.Location))
{
isMoving = true;
lastMouseLocation = mi.Location;
}
return true;
}
else // No ticks; move to the mouse position
{
var thumb = thumbRect;
var center = thumb.X + thumb.Width / 2;
var newOffset = OffsetBy((mi.Location.X - center) * 1f / (RenderBounds.Width - thumb.Width));
if (newOffset != Offset)
{
OnChange(newOffset);
if (thumbRect.Contains(mi.Location))
{
isMoving = true;
lastMouseLocation = mi.Location;
}
return true;
}
}
}
break;
case MouseInputEvent.Move:
{
if ((mi.Location.X != lastMouseLocation.X) && isMoving)
{
var newOffset = OffsetBy((mi.Location.X - lastMouseLocation.X) * 1f / (RenderBounds.Width - thumbRect.Width));
if (newOffset != Offset)
{
lastMouseLocation = mi.Location;
OnChange(newOffset);
}
}
}
break;
}
return thumbRect.Contains(mi.Location.X, mi.Location.Y);
}
float OffsetBy(float amount)
{
var centerPos = Offset + amount;
if (centerPos < 0) centerPos = 0;
if (centerPos > 1) centerPos = 1;
return centerPos;
}
public override Widget Clone() { return new SliderWidget(this); }
protected Rectangle thumbRect
{
get
{
var width = RenderBounds.Height;
var height = RenderBounds.Height;
var origin = (int)((RenderBounds.X + width / 2) + Offset * (RenderBounds.Width - width) - width / 2f);
return new Rectangle(origin, RenderBounds.Y, width, height);
}
}
public override void DrawInner()
{
if (!IsVisible())
return;
var tr = thumbRect;
var trackWidth = RenderBounds.Width - tr.Width;
var trackOrigin = RenderBounds.X + tr.Width / 2;
var trackRect = new Rectangle(trackOrigin - 1, RenderBounds.Y + (RenderBounds.Height - TrackHeight) / 2, trackWidth + 2, TrackHeight);
// Tickmarks (hacked until we have real art)
for (int i = 0; i < Ticks; i++)
{
var tickRect = new Rectangle(trackOrigin - 1 + (int)(i * trackWidth * 1f / (Ticks - 1)),
RenderBounds.Y + RenderBounds.Height / 2, 2, RenderBounds.Height / 2);
WidgetUtils.DrawPanel("slider-tick", tickRect);
}
// Track
WidgetUtils.DrawPanel("slider-track", trackRect);
// Thumb
ButtonWidget.DrawBackground("scrollthumb", tr, IsDisabled(), isMoving, tr.Contains(Viewport.LastMousePos));
}
}
}