mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-19 12:35:52 -04:00
Add software column, allow other columns to be dragged, scrollbar can be dragged too.
This commit is contained in:
parent
f652953582
commit
c33e5e05c4
@ -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(); }
|
||||
|
71
Launcher2/Gui/TableWidget/LauncherTableWidget.Comparers.cs
Normal file
71
Launcher2/Gui/TableWidget/LauncherTableWidget.Comparers.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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" />
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user