diff --git a/OpenRA.Mods.Cnc/Widgets/CncMapChooserLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncMapChooserLogic.cs index 8da2891f4d..6438f30367 100644 --- a/OpenRA.Mods.Cnc/Widgets/CncMapChooserLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncMapChooserLogic.cs @@ -23,7 +23,7 @@ namespace OpenRA.Mods.Cnc.Widgets { Map map; Widget scrollpanel; - Widget itemTemplate; + ScrollItemWidget itemTemplate; [ObjectCreator.UseCtor] internal CncMapChooserLogic([ObjectCreator.Param] Widget widget, @@ -52,7 +52,7 @@ namespace OpenRA.Mods.Cnc.Widgets panel.GetWidget("BUTTON_INSTALL").OnClick = () => InstallMap(); scrollpanel = panel.GetWidget("MAP_LIST"); - itemTemplate = scrollpanel.GetWidget("MAP_TEMPLATE"); + itemTemplate = scrollpanel.GetWidget("MAP_TEMPLATE"); EnumerateMaps(); } @@ -65,14 +65,11 @@ namespace OpenRA.Mods.Cnc.Widgets if (!m.Selectable) continue; - var template = itemTemplate.Clone() as ContainerWidget; - template.GetBackground = () => (template.RenderBounds.Contains(Viewport.LastMousePos) ? "button-hover" : (m == map) ? "button-pressed" : null); - template.OnMouseDown = mi => { if (mi.Button != MouseButton.Left) return false; map = m; return true; }; - template.IsVisible = () => true; - template.GetWidget("TITLE").GetText = () => m.Title; - template.GetWidget("PLAYERS").GetText = () => "{0}".F(m.PlayerCount); - template.GetWidget("TYPE").GetText = () => m.Type; - scrollpanel.AddChild(template); + var item = ScrollItemWidget.Setup(itemTemplate, () => m == map, () => map = m); + item.GetWidget("TITLE").GetText = () => m.Title; + item.GetWidget("PLAYERS").GetText = () => "{0}".F(m.PlayerCount); + item.GetWidget("TYPE").GetText = () => m.Type; + scrollpanel.AddChild(item); } } diff --git a/OpenRA.Mods.Cnc/Widgets/CncMenuButton.cs b/OpenRA.Mods.Cnc/Widgets/CncMenuButton.cs index 44da530db8..d9cad49448 100644 --- a/OpenRA.Mods.Cnc/Widgets/CncMenuButton.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncMenuButton.cs @@ -337,5 +337,43 @@ namespace OpenRA.Mods.Cnc.Widgets ShowDropPanel(w, dropDown, dismissAfter, () => true); } } + + public class ScrollItemWidget : CncMenuButtonWidget + { + public ScrollItemWidget() + : base() + { + IsVisible = () => false; + } + + protected ScrollItemWidget(ScrollItemWidget other) + : base(other) + { + IsVisible = () => false; + } + + public Func IsSelected = () => false; + + public override void DrawInner() + { + var state = IsSelected() ? "button-pressed" : + RenderBounds.Contains(Viewport.LastMousePos) ? "button-hover" : + null; + + if (state != null) + WidgetUtils.DrawPanel(state, RenderBounds); + } + + public override Widget Clone() { return new ScrollItemWidget(this); } + + public static ScrollItemWidget Setup(ScrollItemWidget template, Func isSelected, Action onClick) + { + var w = template.Clone() as ScrollItemWidget; + w.IsVisible = () => true; + w.IsSelected = isSelected; + w.OnClick = onClick; + return w; + } + } } diff --git a/OpenRA.Mods.Cnc/Widgets/CncModBrowserLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncModBrowserLogic.cs index 098e781723..c9823f1189 100644 --- a/OpenRA.Mods.Cnc/Widgets/CncModBrowserLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncModBrowserLogic.cs @@ -58,19 +58,16 @@ namespace OpenRA.Mods.Cnc.Widgets currentMod = Mod.AllMods[Game.modData.Manifest.Mods[0]]; // Mod list - var modTemplate = modList.GetWidget("MOD_TEMPLATE"); + var modTemplate = modList.GetWidget("MOD_TEMPLATE"); foreach (var m in Mod.AllMods) { var mod = m.Value; - var template = modTemplate.Clone() as ContainerWidget; - template.GetBackground = () => (template.RenderBounds.Contains(Viewport.LastMousePos) ? "button-hover" : (currentMod == mod) ? "button-pressed" : null); - template.OnMouseDown = mi => { if (mi.Button != MouseButton.Left) return false; currentMod = mod; return true; }; - template.IsVisible = () => true; - template.GetWidget("TITLE").GetText = () => mod.Title; - template.GetWidget("VERSION").GetText = () => mod.Version; - template.GetWidget("AUTHOR").GetText = () => mod.Author; - modList.AddChild(template); + var item = ScrollItemWidget.Setup(modTemplate, () => currentMod == mod, () => currentMod = mod); + item.GetWidget("TITLE").GetText = () => mod.Title; + item.GetWidget("VERSION").GetText = () => mod.Version; + item.GetWidget("AUTHOR").GetText = () => mod.Author; + modList.AddChild(item); } diff --git a/OpenRA.Mods.Cnc/Widgets/CncMusicPlayerLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncMusicPlayerLogic.cs index 67d9a1b760..b0c576100b 100644 --- a/OpenRA.Mods.Cnc/Widgets/CncMusicPlayerLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncMusicPlayerLogic.cs @@ -104,28 +104,18 @@ namespace OpenRA.Mods.Cnc.Widgets random = music.Shuffle(Game.CosmeticRandom).ToArray(); var ml = panel.GetWidget("MUSIC_LIST"); - var itemTemplate = ml.GetWidget("MUSIC_TEMPLATE"); + var itemTemplate = ml.GetWidget("MUSIC_TEMPLATE"); foreach (var s in music) { var song = s; if (currentSong == null) currentSong = song; - - var template = itemTemplate.Clone() as ContainerWidget; - template.GetBackground = () => (template.RenderBounds.Contains(Viewport.LastMousePos) ? "button-hover" : (song == currentSong) ? "button-pressed" : null); - template.OnMouseDown = mi => - { - if (mi.Button != MouseButton.Left) return false; - currentSong = song; - Play(); - return true; - }; - - template.IsVisible = () => true; - template.GetWidget("TITLE").GetText = () => Rules.Music[song].Title; - template.GetWidget("LENGTH").GetText = () => SongLengthLabel(song); - ml.AddChild(template); + + var item = ScrollItemWidget.Setup(itemTemplate, () => currentSong == song, () => { currentSong = song; Play(); }); + item.GetWidget("TITLE").GetText = () => Rules.Music[song].Title; + item.GetWidget("LENGTH").GetText = () => SongLengthLabel(song); + ml.AddChild(item); } } diff --git a/OpenRA.Mods.Cnc/Widgets/CncReplayBrowserLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncReplayBrowserLogic.cs index 3a8fa15988..c64cbe819b 100644 --- a/OpenRA.Mods.Cnc/Widgets/CncReplayBrowserLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncReplayBrowserLogic.cs @@ -36,7 +36,7 @@ namespace OpenRA.Mods.Cnc.Widgets var rl = panel.GetWidget("REPLAY_LIST"); var replayDir = Path.Combine(Platform.SupportDir, "Replays"); - var template = panel.GetWidget("REPLAY_TEMPLATE"); + var template = panel.GetWidget("REPLAY_TEMPLATE"); rl.RemoveChildren(); if (Directory.Exists(replayDir)) @@ -92,15 +92,14 @@ namespace OpenRA.Mods.Cnc.Widgets } } - void AddReplay(ScrollPanelWidget list, string filename, Widget template) + void AddReplay(ScrollPanelWidget list, string filename, ScrollItemWidget template) { - var entry = template.Clone() as ContainerWidget; + var item = ScrollItemWidget.Setup(template, + () => currentSummary != null && currentSummary.Filename == filename, + () => SelectReplay(filename)); var f = Path.GetFileName(filename); - entry.GetWidget("TITLE").GetText = () => f; - entry.GetBackground = () => (entry.RenderBounds.Contains(Viewport.LastMousePos) ? "button-hover" : (currentSummary != null && currentSummary.Filename == filename) ? "button-pressed" : null); - entry.OnMouseDown = mi => { if (mi.Button != MouseButton.Left) return false; SelectReplay(filename); return true; }; - entry.IsVisible = () => true; - list.AddChild(entry); + item.GetWidget("TITLE").GetText = () => f; + list.AddChild(item); } } } diff --git a/OpenRA.Mods.Cnc/Widgets/CncServerBrowserLogic.cs b/OpenRA.Mods.Cnc/Widgets/CncServerBrowserLogic.cs index a114c10a11..32c43ddfdf 100644 --- a/OpenRA.Mods.Cnc/Widgets/CncServerBrowserLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/CncServerBrowserLogic.cs @@ -57,7 +57,7 @@ namespace OpenRA.Mods.Cnc.Widgets public class CncServerBrowserLogic : IWidgetDelegate { GameServer currentServer; - Widget serverTemplate; + ScrollItemWidget serverTemplate; bool refreshing; enum SearchStatus { @@ -120,7 +120,7 @@ namespace OpenRA.Mods.Cnc.Widgets panel.GetWidget("BACK_BUTTON").OnClick = () => { Widget.CloseWindow(); onExit(); }; // Server list - serverTemplate = sl.GetWidget("SERVER_TEMPLATE"); + serverTemplate = sl.GetWidget("SERVER_TEMPLATE"); // Display the progress label over the server list // The text is only visible when the list is empty @@ -194,17 +194,14 @@ namespace OpenRA.Mods.Cnc.Widgets { var game = loop; - var template = serverTemplate.Clone() as ContainerWidget; - template.GetBackground = () => (template.RenderBounds.Contains(Viewport.LastMousePos) ? "button-hover" : (currentServer == game) ? "button-pressed" : null); - template.OnMouseDown = mi => { if (mi.Button != MouseButton.Left) return false; currentServer = game; return true; }; - template.IsVisible = () => true; - template.GetWidget("TITLE").GetText = () => game.Name; + var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => currentServer = game); + item.GetWidget("TITLE").GetText = () => game.Name; // TODO: Use game.MapTitle once the server supports it - template.GetWidget("MAP").GetText = () => {var map = GetMap(game.Map); return map == null ? "Unknown" : map.Title;}; + item.GetWidget("MAP").GetText = () => {var map = GetMap(game.Map); return map == null ? "Unknown" : map.Title;}; // TODO: Use game.MaxPlayers once the server supports it - template.GetWidget("PLAYERS").GetText = () => GetPlayersLabel(game); - template.GetWidget("IP").GetText = () => game.Address; - sl.AddChild(template); + item.GetWidget("PLAYERS").GetText = () => GetPlayersLabel(game); + item.GetWidget("IP").GetText = () => game.Address; + sl.AddChild(item); if (i == 0) currentServer = game; i++; diff --git a/mods/cnc/chrome/mapchooser.yaml b/mods/cnc/chrome/mapchooser.yaml index 331dacd674..bec7ee2d0f 100644 --- a/mods/cnc/chrome/mapchooser.yaml +++ b/mods/cnc/chrome/mapchooser.yaml @@ -38,13 +38,12 @@ Container@MAPCHOOSER_PANEL: Width:504 Height:455 Children: - Container@MAP_TEMPLATE: + ScrollItem@MAP_TEMPLATE: Id:MAP_TEMPLATE Width:PARENT_RIGHT-27 Height:25 X:2 Y:0 - Visible:false Children: Label@TITLE: X:10 diff --git a/mods/cnc/chrome/modchooser.yaml b/mods/cnc/chrome/modchooser.yaml index e1cd0de76d..dc9b4854aa 100644 --- a/mods/cnc/chrome/modchooser.yaml +++ b/mods/cnc/chrome/modchooser.yaml @@ -25,7 +25,7 @@ Container@MODS_PANEL: Width:710 Height:455 Children: - Container@MOD_TEMPLATE: + ScrollItem@MOD_TEMPLATE: Id:MOD_TEMPLATE Width:PARENT_RIGHT-27 Height:25 diff --git a/mods/cnc/chrome/music.yaml b/mods/cnc/chrome/music.yaml index 9abd600744..c461fe958d 100644 --- a/mods/cnc/chrome/music.yaml +++ b/mods/cnc/chrome/music.yaml @@ -25,7 +25,7 @@ Container@MUSIC_PANEL: Width:330 Height:275 Children: - Container@MUSIC_TEMPLATE: + ScrollItem@MUSIC_TEMPLATE: Id:MUSIC_TEMPLATE Width:PARENT_RIGHT-27 Height:25 diff --git a/mods/cnc/chrome/replaybrowser.yaml b/mods/cnc/chrome/replaybrowser.yaml index 45fdb23aa7..77b718fd27 100644 --- a/mods/cnc/chrome/replaybrowser.yaml +++ b/mods/cnc/chrome/replaybrowser.yaml @@ -25,7 +25,7 @@ Container@REPLAYBROWSER_PANEL: Width:286 Height:270 Children: - Container@REPLAY_TEMPLATE: + ScrollItem@REPLAY_TEMPLATE: Id:REPLAY_TEMPLATE Width:PARENT_RIGHT-27 Height:25 diff --git a/mods/cnc/chrome/serverbrowser.yaml b/mods/cnc/chrome/serverbrowser.yaml index 2475014644..9ea5a29183 100644 --- a/mods/cnc/chrome/serverbrowser.yaml +++ b/mods/cnc/chrome/serverbrowser.yaml @@ -25,13 +25,12 @@ Container@SERVERBROWSER_PANEL: Width:710 Height:315 Children: - Container@SERVER_TEMPLATE: + ScrollItem@SERVER_TEMPLATE: Id:SERVER_TEMPLATE Width:PARENT_RIGHT-27 Height:25 X:2 Y:0 - Visible:false Children: Label@TITLE: X:10