Add software column, allow other columns to be dragged, scrollbar can be dragged too.

This commit is contained in:
UnknownShadow200 2015-12-10 23:12:32 +11:00
parent f652953582
commit c33e5e05c4
7 changed files with 163 additions and 106 deletions

View File

@ -21,21 +21,24 @@ namespace Launcher2 {
public override void Tick() {
LauncherTableWidget table = (LauncherTableWidget)widgets[tableIndex];
if( table.DraggingWidth && !game.Window.Mouse[MouseButton.Left] )
table.DraggingWidth = false;
if( !game.Window.Mouse[MouseButton.Left] ) {
table.DraggingColumn = -1;
table.DraggingScrollbar = false;
}
}
protected override void MouseMove( object sender, MouseMoveEventArgs e ) {
base.MouseMove( sender, e );
if( selectedWidget != null && selectedWidget == widgets[tableIndex] ) {
LauncherTableWidget table = (LauncherTableWidget)widgets[tableIndex];
table.MouseMove( e.XDelta, e.YDelta );
table.MouseMove( e.X, e.Y, e.XDelta, e.YDelta );
}
}
void MouseButtonUp( object sender, MouseButtonEventArgs e ) {
LauncherTableWidget table = (LauncherTableWidget)widgets[tableIndex];
table.DraggingWidth = false;
table.DraggingColumn = -1;
table.DraggingScrollbar = false;
}
protected override void OnAddedChar() { FilterList(); }

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
namespace Launcher2 {
public partial class LauncherTableWidget : LauncherWidget {
abstract class TableEntryComparer : IComparer<TableEntry> {
public bool Invert = true;
public abstract int Compare( TableEntry a, TableEntry b );
}
sealed class NameComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
StringComparison comparison = StringComparison.CurrentCultureIgnoreCase;
int value = String.Compare( a.Name, b.Name, comparison );
return Invert ? -value : value;
}
}
sealed class PlayersComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
long valX = Int64.Parse( a.Players.Substring( 0, a.Players.IndexOf( '/' ) ) );
long valY = Int64.Parse( b.Players.Substring( 0, b.Players.IndexOf( '/' ) ) );
int value = valX.CompareTo( valY );
return Invert ? -value : value;
}
}
sealed class UptimeComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
TimeSpan valX = ParseUptimeString( a.Uptime );
TimeSpan valY = ParseUptimeString( b.Uptime );
int value = valX.CompareTo( valY );
return Invert ? -value : value;
}
static TimeSpan ParseUptimeString( string s ) {
int sum = 0;
for( int i = 0; i < s.Length - 1; i++ ) {
sum *= 10;
sum += s[i] - '0';
}
char timeType = s[s.Length - 1];
switch( timeType ) {
case 'w' : return TimeSpan.FromDays( sum * 7 );
case 'd' : return TimeSpan.FromDays( sum );
case 'h' : return TimeSpan.FromHours( sum );
case 'm' : return TimeSpan.FromMinutes( sum );
case 's' : return TimeSpan.FromSeconds( sum );
default: throw new NotSupportedException( "unsupported uptime type: " + timeType );
}
}
}
sealed class SoftwareComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
StringComparison comparison = StringComparison.CurrentCultureIgnoreCase;
int value = String.Compare( a.Software, b.Software, comparison );
return Invert ? -value : value;
}
}
}
}

View File

@ -9,11 +9,14 @@ namespace Launcher2 {
NameComparer nameComp = new NameComparer();
PlayersComparer playerComp = new PlayersComparer();
UptimeComparer uptimeComp = new UptimeComparer();
public bool DraggingWidth = false;
SoftwareComparer softwareComp = new SoftwareComparer();
public int DraggingColumn = -1;
public bool DraggingScrollbar = true;
void HandleOnClick( int mouseX, int mouseY ) {
void HandleOnClick( int mouseX, int mouseY ) {
if( mouseX >= Window.Width - 10 ) {
ScrollbarClick( mouseY );
DraggingScrollbar = true;
lastIndex = -10; return;
}
@ -26,28 +29,41 @@ namespace Launcher2 {
}
void SelectHeader( int mouseX, int mouseY ) {
int x = 0;
for( int i = 0; i < ColumnWidths.Length; i++ ) {
x += ColumnWidths[i] + 10;
if( mouseX >= x - 8 && mouseX < x + 8 ) {
DraggingColumn = i;
lastIndex = -10; return;
}
}
TrySortColumns( mouseX );
}
void TrySortColumns( int mouseX ) {
int x = 0;
lastIndex = -10;
if( mouseX >= x && mouseX < x + ColumnWidths[0] - 10 ) {
SortEntries( nameComp ); return;
}
x += ColumnWidths[0];
if( mouseX >= x + 15 && mouseX < x + ColumnWidths[1] ) {
if( mouseX >= x && mouseX < x + ColumnWidths[1] ) {
SortEntries( playerComp ); return;
}
x += ColumnWidths[1];
if( mouseX >= x ) {
if( mouseX >= x && mouseX < x + ColumnWidths[2] ) {
SortEntries( uptimeComp ); return;
}
DraggingWidth = true;
x += ColumnWidths[2];
if( mouseX >= x ) {
SortEntries( softwareComp ); return;
}
}
void SortEntries( TableEntryComparer comparer ) {
string selHash = SelectedIndex >= 0 ? usedEntries[SelectedIndex].Hash : "";
Array.Sort( usedEntries, 0, Count, comparer );
Array.Sort( entries, 0, entries.Length, comparer );
lastIndex = -10;
comparer.Invert = !comparer.Invert;
SetSelected( selHash );
@ -57,7 +73,7 @@ namespace Launcher2 {
void GetSelectedServer( int mouseX, int mouseY ) {
for( int i = 0; i < Count; i++ ) {
TableEntry entry = usedEntries[i];
if( mouseY < entry.Y || mouseY >= entry.Y + entry.Height ) continue;
if( mouseY < entry.Y || mouseY >= entry.Y + entry.Height + 3 ) continue;
if( lastIndex == i && (DateTime.UtcNow - lastPress).TotalSeconds < 1 ) {
Window.ConnectToServer( servers, entry.Hash );
@ -73,11 +89,14 @@ namespace Launcher2 {
int lastIndex = -10;
DateTime lastPress;
public void MouseMove( int deltaX, int deltaY ) {
if( DraggingWidth ) {
ColumnWidths[0] += deltaX;
Utils.Clamp( ref ColumnWidths[0], 20, Window.Width - 20 );
DesiredColumnWidths[0] = ColumnWidths[0];
public void MouseMove( int x, int y, int deltaX, int deltaY ) {
if( DraggingScrollbar ) {
ScrollbarClick( y );
} else if( DraggingColumn >= 0 ) {
int col = DraggingColumn;
ColumnWidths[col] += deltaX;
Utils.Clamp( ref ColumnWidths[col], 20, Window.Width - 20 );
DesiredColumnWidths[col] = ColumnWidths[col];
NeedRedraw();
}
}

View File

@ -11,8 +11,8 @@ namespace Launcher2 {
OnClick = HandleOnClick;
}
internal static FastColour backGridCol = new FastColour( 20, 20, 10 ),
foreGridCol = new FastColour( 40, 40, 40 );
internal static FastColour backGridCol = new FastColour( 20, 20, 10 ),
foreGridCol = new FastColour( 40, 40, 40 );
public Action NeedRedraw;
public Action<string> SelectedChanged;
public int SelectedIndex = -1;
@ -30,6 +30,7 @@ namespace Launcher2 {
tableEntry.Hash = e.Hash;
tableEntry.Name = e.Name;
tableEntry.Players = e.Players + "/" + e.MaximumPlayers;
tableEntry.Software = e.Software;
tableEntry.Uptime = MakeUptime( e.Uptime );
entries[index] = tableEntry;
@ -52,26 +53,22 @@ namespace Launcher2 {
Count++;
usedEntries[index++] = entry;
}
entries[i] = entry;
}
SetSelected( selHash );
}
public int CurrentIndex, Count;
public int[] ColumnWidths = { 360, 80, 80 };
public int[] DesiredColumnWidths = { 360, 80, 80 };
public int[] ColumnWidths = { 340, 80, 80, 140 };
public int[] DesiredColumnWidths = { 340, 80, 80, 140 };
int defaultInputHeight;
internal struct TableEntry {
public string Hash, Name, Players, Uptime;
public string Hash, Name, Players, Uptime, Software;
public int Y, Height;
}
public void DrawAt( IDrawer2D drawer, Font font, Font titleFont, Font boldFont,
Anchor horAnchor, Anchor verAnchor, int x, int y ) {
DrawTextArgs args = new DrawTextArgs( "I", font, true );
defaultInputHeight = drawer.MeasureSize( ref args ).Height;
CalculateOffset( x, y, horAnchor, verAnchor );
Redraw( drawer, font, titleFont, boldFont );
}
@ -79,17 +76,25 @@ namespace Launcher2 {
static FastColour backCol = new FastColour( 120, 85, 151 ), foreCol = new FastColour( 160, 133, 186 );
static FastColour scrollCol = new FastColour( 200, 184, 216 );
public void Redraw( IDrawer2D drawer, Font font, Font titleFont, Font boldFont ) {
ColumnWidths[0] = DesiredColumnWidths[0];
Utils.Clamp( ref ColumnWidths[0], 20, Window.Width - 20 );
int x = X + 5;
for( int i = 0; i < ColumnWidths.Length; i++ ) {
ColumnWidths[i] = DesiredColumnWidths[i];
Utils.Clamp( ref ColumnWidths[i], 20, Window.Width - 20 );
}
DrawTextArgs args = new DrawTextArgs( "IMP", font, true );
defaultInputHeight = drawer.MeasureSize( ref args ).Height;
int x = X + 5;
DrawGrid( drawer, font, titleFont );
x += DrawColumn( drawer, false, font, titleFont, boldFont,
ResetEntries();
x += DrawColumn( drawer, false, font, titleFont, boldFont,
"Name", ColumnWidths[0], x, e => e.Name ) + 5;
x += DrawColumn( drawer, true, font, titleFont, boldFont,
x += DrawColumn( drawer, true, font, titleFont, boldFont,
"Players", ColumnWidths[1], x, e => e.Players ) + 5;
x += DrawColumn( drawer, true, font, titleFont, boldFont,
"Uptime", ColumnWidths[2], x, e => e.Uptime ) + 5;
x += DrawColumn( drawer, true, font, titleFont, boldFont,
"Software", ColumnWidths[3], x, e => e.Software ) + 5;
Width = Window.Width;
DrawScrollbar( drawer );
@ -106,38 +111,50 @@ namespace Launcher2 {
int bodyStartY = y;
y += 3;
for( int i = CurrentIndex; i < Count; i++ ) {
args = new DrawTextArgs( filter( usedEntries[i] ), font, true );
if( i == SelectedIndex && !separator )
drawer.DrawRect( foreGridCol, 0, y - 3, Width, defaultInputHeight + 4 );
if( !DrawColumnEntry( drawer, ref args, maxWidth, x, ref y, ref usedEntries[i] ) ) {
maxIndex = i;
break;
maxIndex = i; break;
}
}
Height = Window.Height - Y;
if( separator )
drawer.DrawRect( foreCol, x - 7, bodyStartY, 2, Height );
drawer.DrawRect( foreCol, x - 7, Y, 2, Height );
return maxWidth + 5;
}
bool DrawColumnEntry( IDrawer2D drawer, ref DrawTextArgs args,
int maxWidth, int x, ref int y, ref TableEntry entry ) {
Size size = drawer.MeasureSize( ref args );
bool empty = args.Text == "";
if( empty )
size.Height = defaultInputHeight;
if( y + size.Height > Window.Height ) {
y = Window.Height + 3; return false;
}
size.Width = Math.Min( maxWidth, size.Width );
entry.Y = y; entry.Height = size.Height;
args.SkipPartsCheck = false;
drawer.DrawClippedText( ref args, x, y, maxWidth, 30 );
entry.Y = y; entry.Height = size.Height;
if( !empty ) {
size.Width = Math.Min( maxWidth, size.Width );
args.SkipPartsCheck = false;
drawer.DrawClippedText( ref args, x, y, maxWidth, 30 );
}
y += size.Height + 3;
return true;
}
void ResetEntries() {
for( int i = 0; i < Count; i++ ) {
entries[i].Height = 0; usedEntries[i].Height = 0;
entries[i].Y = -10; usedEntries[i].Y = -10;
}
}
int headerStartY, headerEndY;
int numEntries = 0;
void DrawGrid( IDrawer2D drawer, Font font, Font titleFont ) {
@ -146,8 +163,8 @@ namespace Launcher2 {
drawer.DrawRect( foreCol, 0, Y + size.Height + 5, Window.Width, 2 );
headerStartY = Y;
headerEndY = Y + size.Height + 5;
int startY = headerEndY + 3;
headerEndY = Y + size.Height + 5;
int startY = headerEndY + 3;
numEntries = (Window.Height - startY) / (defaultInputHeight + 3);
}
@ -169,7 +186,7 @@ namespace Launcher2 {
SelectedIndex = index;
lastIndex = index;
ClampIndex();
ClampIndex();
if( Count > 0 )
SelectedChanged( usedEntries[index].Hash );
}
@ -201,59 +218,5 @@ namespace Launcher2 {
return (int)t.TotalMinutes + "m";
return (int)t.TotalSeconds + "s";
}
abstract class TableEntryComparer : IComparer<TableEntry> {
public bool Invert = true;
public abstract int Compare( TableEntry a, TableEntry b );
}
sealed class NameComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
StringComparison comparison = StringComparison.CurrentCultureIgnoreCase;
int value = String.Compare( a.Name, b.Name, comparison );
return Invert ? -value : value;
}
}
sealed class PlayersComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
long valX = Int64.Parse( a.Players.Substring( 0, a.Players.IndexOf( '/' ) ) );
long valY = Int64.Parse( b.Players.Substring( 0, b.Players.IndexOf( '/' ) ) );
int value = valX.CompareTo( valY );
return Invert ? -value : value;
}
}
sealed class UptimeComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
TimeSpan valX = ParseUptimeString( a.Uptime );
TimeSpan valY = ParseUptimeString( b.Uptime );
int value = valX.CompareTo( valY );
return Invert ? -value : value;
}
static TimeSpan ParseUptimeString( string s ) {
int sum = 0;
for( int i = 0; i < s.Length - 1; i++ ) {
sum *= 10;
sum += s[i] - '0';
}
char timeType = s[s.Length - 1];
switch( timeType ) {
case 'w' : return TimeSpan.FromDays( sum * 7 );
case 'd' : return TimeSpan.FromDays( sum );
case 'h' : return TimeSpan.FromHours( sum );
case 'm' : return TimeSpan.FromMinutes( sum );
case 's' : return TimeSpan.FromSeconds( sum );
default: throw new NotSupportedException( "unsupported uptime type: " + timeType );
}
}
}
}
}

View File

@ -65,6 +65,7 @@
<Compile Include="Gui\Screens\MainScreen.cs" />
<Compile Include="Gui\Screens\ResourcesScreen.cs" />
<Compile Include="Gui\Screens\UpdatesScreen.cs" />
<Compile Include="Gui\TableWidget\LauncherTableWidget.Comparers.cs" />
<Compile Include="Gui\TableWidget\LauncherTableWidget.cs" />
<Compile Include="Gui\TableWidget\LauncherTableWidget.Input.cs" />
<Compile Include="Gui\Widgets\LauncherBooleanWidget.cs" />

View File

@ -110,7 +110,8 @@ namespace Launcher2 {
(string)obj["hash"], (string)obj["name"],
(string)obj["players"], (string)obj["maxplayers"],
(string)obj["uptime"], (string)obj["mppass"],
(string)obj["ip"], (string)obj["port"] ) );
(string)obj["ip"], (string)obj["port"],
(string)obj["software"] ) );
}
Log( "cc servers took " + sw.ElapsedMilliseconds );
sw.Stop();

View File

@ -27,16 +27,15 @@ namespace Launcher2 {
/// <summary> Mppass specific for the user and this server. </summary>
public string Mppass;
/// <summary> Software the server is running on, may be empty. </summary>
public string Software;
public ServerListEntry( string hash, string name, string players, string maxPlayers,
string uptime, string mppass, string ip, string port ) {
Hash = hash;
Name = name;
Players = players;
MaximumPlayers = maxPlayers;
Uptime = uptime;
Mppass = mppass;
IPAddress = ip;
Port = port;
string uptime, string mppass, string ip, string port, string software ) {
Hash = hash; Name = name; Players = players;
MaximumPlayers = maxPlayers; Uptime = uptime;
Mppass = mppass; IPAddress = ip; Port = port;
Software = software;
}
}
}