Dropdown listboxes
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OpenRA.Widgets
|
namespace OpenRA.Widgets
|
||||||
{
|
{
|
||||||
@@ -70,13 +71,108 @@ namespace OpenRA.Widgets
|
|||||||
WidgetUtils.DrawPanel(Depressed ? "dialog3" : "dialog2", RenderBounds);
|
WidgetUtils.DrawPanel(Depressed ? "dialog3" : "dialog2", RenderBounds);
|
||||||
|
|
||||||
var text = GetText();
|
var text = GetText();
|
||||||
|
|
||||||
font.DrawText(text,
|
font.DrawText(text,
|
||||||
new int2(RenderOrigin.X + Bounds.Width / 2, RenderOrigin.Y + Bounds.Height / 2)
|
new int2(RenderOrigin.X + UsableWidth / 2, RenderOrigin.Y + Bounds.Height / 2)
|
||||||
- new int2(font.Measure(text).X / 2,
|
- new int2(font.Measure(text).X / 2,
|
||||||
font.Measure(text).Y / 2) + stateOffset, Color.White);
|
font.Measure(text).Y / 2) + stateOffset, Color.White);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Widget Clone() { return new ButtonWidget(this); }
|
public override Widget Clone() { return new ButtonWidget(this); }
|
||||||
|
public virtual int UsableWidth { get { return Bounds.Width; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DropDownButtonWidget : ButtonWidget
|
||||||
|
{
|
||||||
|
public DropDownButtonWidget()
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DropDownButtonWidget(DropDownButtonWidget widget)
|
||||||
|
: base(widget)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawInner(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
base.DrawInner(wr);
|
||||||
|
var image = ChromeProvider.GetImage("scrollbar", "down_arrow");
|
||||||
|
WidgetUtils.DrawRGBA( image,
|
||||||
|
new float2( RenderBounds.Right - RenderBounds.Height + 4,
|
||||||
|
RenderBounds.Top + (RenderBounds.Height - image.bounds.Height) / 2 ));
|
||||||
|
|
||||||
|
WidgetUtils.FillRectWithColor(new Rectangle(RenderBounds.Right - RenderBounds.Height,
|
||||||
|
RenderBounds.Top + 3, 1, RenderBounds.Height - 6),
|
||||||
|
Color.White);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Widget Clone() { return new DropDownButtonWidget(this); }
|
||||||
|
public override int UsableWidth { get { return Bounds.Width - Bounds.Height; } } /* space for button */
|
||||||
|
|
||||||
|
public static void ShowDropDown<T>(Widget w, IEnumerable<T> ts, Func<T, int, LabelWidget> ft)
|
||||||
|
{
|
||||||
|
var fullscreenMask = new ContainerWidget
|
||||||
|
{
|
||||||
|
Bounds = new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height),
|
||||||
|
ClickThrough = false,
|
||||||
|
Visible = true
|
||||||
|
};
|
||||||
|
|
||||||
|
Widget.RootWidget.AddChild(fullscreenMask);
|
||||||
|
|
||||||
|
var origin = w.RenderOrigin;
|
||||||
|
var dropDown = new ListBoxWidget
|
||||||
|
{
|
||||||
|
Bounds = new Rectangle(w.RenderOrigin.X, w.RenderOrigin.Y + w.Bounds.Height, w.Bounds.Width, 100),
|
||||||
|
Visible = true,
|
||||||
|
ClickThrough = false,
|
||||||
|
OnMouseUp = mi => true,
|
||||||
|
};
|
||||||
|
|
||||||
|
Widget.RootWidget.AddChild(dropDown);
|
||||||
|
|
||||||
|
Action HideDropDown = () =>
|
||||||
|
{
|
||||||
|
Widget.RootWidget.Children.Remove(fullscreenMask);
|
||||||
|
Widget.RootWidget.Children.Remove(dropDown);
|
||||||
|
};
|
||||||
|
|
||||||
|
fullscreenMask.OnMouseUp = mi =>
|
||||||
|
{
|
||||||
|
HideDropDown();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var y = 0;
|
||||||
|
List<LabelWidget> items = new List<LabelWidget>();
|
||||||
|
|
||||||
|
foreach (var t in ts)
|
||||||
|
{
|
||||||
|
var tt = t;
|
||||||
|
var ww = ft(t, dropDown.Bounds.Width);
|
||||||
|
var origMouseUp = ww.OnMouseUp;
|
||||||
|
ww.OnMouseUp = mi => { var result = origMouseUp(mi); HideDropDown(); return result; };
|
||||||
|
ww.ClickThrough = false;
|
||||||
|
ww.IsVisible = () => true;
|
||||||
|
ww.Bounds = new Rectangle(0, y, ww.Bounds.Width, ww.Bounds.Height);
|
||||||
|
|
||||||
|
ww.OnMouseMove = mi =>
|
||||||
|
{
|
||||||
|
items.Do(lw =>
|
||||||
|
{
|
||||||
|
lw.Background = null; ww.Background = "dialog2";
|
||||||
|
}); return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
dropDown.AddChild(ww);
|
||||||
|
items.Add(ww);
|
||||||
|
|
||||||
|
y += ww.Bounds.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
dropDown.ContentHeight = y;
|
||||||
|
dropDown.Bounds.Height = y + 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,14 +103,14 @@ namespace OpenRA.Widgets.Delegates
|
|||||||
bg.AddChild(theirStance);
|
bg.AddChild(theirStance);
|
||||||
controls.Add(theirStance);
|
controls.Add(theirStance);
|
||||||
|
|
||||||
var myStance = new ButtonWidget
|
var myStance = new DropDownButtonWidget
|
||||||
{
|
{
|
||||||
Bounds = new Rectangle( margin + 2 * labelWidth + 20, y, labelWidth, 25),
|
Bounds = new Rectangle( margin + 2 * labelWidth + 20, y, labelWidth, 25),
|
||||||
Id = "DIPLOMACY_PLAYER_LABEL_MY_{0}".F(p.Index),
|
Id = "DIPLOMACY_PLAYER_LABEL_MY_{0}".F(p.Index),
|
||||||
Text = world.LocalPlayer.Stances[ pp ].ToString(),
|
Text = world.LocalPlayer.Stances[ pp ].ToString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
myStance.OnMouseUp = mi => { CycleStance(pp, myStance); return true; };
|
myStance.OnMouseDown = mi => { ShowDropDown(pp, myStance); return true; };
|
||||||
|
|
||||||
bg.AddChild(myStance);
|
bg.AddChild(myStance);
|
||||||
controls.Add(myStance);
|
controls.Add(myStance);
|
||||||
@@ -119,29 +119,26 @@ namespace OpenRA.Widgets.Delegates
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stance GetNextStance(Stance s)
|
void ShowDropDown(Player p, Widget w)
|
||||||
{
|
{
|
||||||
switch (s)
|
DropDownButtonWidget.ShowDropDown(w, Enum.GetValues(typeof(Stance)).OfType<Stance>(),
|
||||||
{
|
(s, width) => new LabelWidget
|
||||||
case Stance.Ally: return Stance.Enemy;
|
{
|
||||||
case Stance.Enemy: return Stance.Neutral;
|
Bounds = new Rectangle(0, 0, width, 24),
|
||||||
case Stance.Neutral: return Stance.Ally;
|
Text = " {0}".F(s),
|
||||||
default:
|
OnMouseUp = mi => { SetStance((ButtonWidget)w, p, s); return true; },
|
||||||
throw new ArgumentException();
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CycleStance(Player p, ButtonWidget bw)
|
void SetStance(ButtonWidget bw, Player p, Stance ss)
|
||||||
{
|
{
|
||||||
if (p.World.LobbyInfo.GlobalSettings.LockTeams)
|
if (p.World.LobbyInfo.GlobalSettings.LockTeams)
|
||||||
return; // team changes are banned
|
return; // team changes are banned
|
||||||
|
|
||||||
var nextStance = GetNextStance((Stance)Enum.Parse(typeof(Stance), bw.Text));
|
|
||||||
|
|
||||||
world.IssueOrder(new Order("SetStance", world.LocalPlayer.PlayerActor,
|
world.IssueOrder(new Order("SetStance", world.LocalPlayer.PlayerActor,
|
||||||
false) { TargetLocation = new int2(p.Index, (int)nextStance) });
|
false) { TargetLocation = new int2(p.Index, (int)ss) });
|
||||||
|
|
||||||
bw.Text = nextStance.ToString();
|
bw.Text = ss.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using System.Linq;
|
|||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
using OpenRA.Network;
|
using OpenRA.Network;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace OpenRA.Widgets.Delegates
|
namespace OpenRA.Widgets.Delegates
|
||||||
{
|
{
|
||||||
@@ -215,6 +216,34 @@ namespace OpenRA.Widgets.Delegates
|
|||||||
{
|
{
|
||||||
return orderManager.LobbyInfo.ClientInSlot( slot );
|
return orderManager.LobbyInfo.ClientInSlot( slot );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowDropDown(Session.Slot slot, ButtonWidget name, bool showBotOptions)
|
||||||
|
{
|
||||||
|
var dropDownOptions = new List<Pair<string, Action>>
|
||||||
|
{
|
||||||
|
new Pair<string, Action>( "Open",
|
||||||
|
() => orderManager.IssueOrder( Order.Command( "slot_open " + slot.Index ) )),
|
||||||
|
new Pair<string, Action>( "Closed",
|
||||||
|
() => orderManager.IssueOrder( Order.Command( "slot_close " + slot.Index ) )),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (showBotOptions)
|
||||||
|
{
|
||||||
|
var bots = new string[] { "HackyAI" };
|
||||||
|
bots.Do(bot =>
|
||||||
|
dropDownOptions.Add(new Pair<string, Action>("Bot: {0}".F(bot),
|
||||||
|
() => orderManager.IssueOrder(Order.Command("slot_bot {0} {1}".F(slot.Index, bot))))));
|
||||||
|
}
|
||||||
|
|
||||||
|
DropDownButtonWidget.ShowDropDown( name,
|
||||||
|
dropDownOptions,
|
||||||
|
(ac, w) => new LabelWidget
|
||||||
|
{
|
||||||
|
Bounds = new Rectangle(0, 0, w, 24),
|
||||||
|
Text = " {0}".F(ac.First),
|
||||||
|
OnMouseUp = mi => { ac.Second(); return true; },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void UpdatePlayerList()
|
void UpdatePlayerList()
|
||||||
{
|
{
|
||||||
@@ -240,40 +269,15 @@ namespace OpenRA.Widgets.Delegates
|
|||||||
var btn = template.GetWidget<ButtonWidget>("JOIN");
|
var btn = template.GetWidget<ButtonWidget>("JOIN");
|
||||||
btn.GetText = () => "Spectate in this slot";
|
btn.GetText = () => "Spectate in this slot";
|
||||||
name.GetText = () => s.Closed ? "Closed" : "Open";
|
name.GetText = () => s.Closed ? "Closed" : "Open";
|
||||||
name.OnMouseUp = _ =>
|
name.OnMouseDown = _ => { ShowDropDown(s, name, false); return true; };
|
||||||
{
|
|
||||||
if (s.Closed)
|
|
||||||
{
|
|
||||||
orderManager.IssueOrder(Order.Command("slot_open " + s.Index));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
orderManager.IssueOrder(Order.Command("slot_close " + s.Index));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
template = EmptySlotTemplateHost.Clone();
|
template = EmptySlotTemplateHost.Clone();
|
||||||
var name = template.GetWidget<ButtonWidget>("NAME");
|
var name = template.GetWidget<ButtonWidget>("NAME");
|
||||||
name.GetText = () => s.Closed ? "Closed" : (s.Bot == null) ? "Open" : "Bot: " + s.Bot;
|
name.GetText = () => s.Closed ? "Closed" : (s.Bot == null) ? "Open" : "Bot: " + s.Bot;
|
||||||
name.OnMouseUp = _ =>
|
name.OnMouseDown = _ => { ShowDropDown(s, name, Map.Players[ s.MapPlayer ].AllowBots); return true; };
|
||||||
{
|
|
||||||
if (s.Closed)
|
|
||||||
{
|
|
||||||
s.Bot = null;
|
|
||||||
orderManager.IssueOrder(Order.Command("slot_open " + s.Index));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (s.Bot == null && Map.Players[s.MapPlayer].AllowBots)
|
|
||||||
orderManager.IssueOrder(Order.Command("slot_bot {0} HackyAI".F(s.Index)));
|
|
||||||
else
|
|
||||||
orderManager.IssueOrder(Order.Command("slot_close " + s.Index));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ Background@SERVER_LOBBY:
|
|||||||
Height:30
|
Height:30
|
||||||
Visible:false
|
Visible:false
|
||||||
Children:
|
Children:
|
||||||
Button@NAME: -- TODO: replace with dropdown
|
DropDownButton@NAME: -- TODO: replace with dropdown
|
||||||
Id:NAME
|
Id:NAME
|
||||||
Text:Name
|
Text:Name
|
||||||
Width:155
|
Width:155
|
||||||
|
|||||||
Reference in New Issue
Block a user