2009-05-08 13:28:41 +00:00
|
|
|
/*
|
|
|
|
* OpenClonk, http://www.openclonk.org
|
|
|
|
*
|
2009-06-05 13:41:20 +00:00
|
|
|
* Copyright (c) 2004-2009 Sven Eberhardt
|
2010-12-23 00:01:24 +00:00
|
|
|
* Copyright (c) 2005-2006, 2009-2010 Günther Brammer
|
2009-06-05 13:41:20 +00:00
|
|
|
* Copyright (c) 2005, 2007 Peter Wortmann
|
|
|
|
* Copyright (c) 2006 Florian Groß
|
|
|
|
* Copyright (c) 2007 Matthes Bender
|
2010-12-23 00:01:24 +00:00
|
|
|
* Copyright (c) 2010 Benjamin Herr
|
2009-05-08 13:28:41 +00:00
|
|
|
* Copyright (c) 2004-2009, RedWolf Design GmbH, http://www.clonk.de
|
|
|
|
*
|
|
|
|
* Portions might be copyrighted by other authors who have contributed
|
|
|
|
* to OpenClonk.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
* See isc_license.txt for full license and disclaimer.
|
|
|
|
*
|
|
|
|
* "Clonk" is a registered trademark of Matthes Bender.
|
|
|
|
* See clonk_trademark_license.txt for full license.
|
|
|
|
*/
|
|
|
|
// dialogs for network information
|
|
|
|
|
|
|
|
#include "C4Include.h"
|
|
|
|
#include "C4Network2Dialogs.h"
|
|
|
|
|
|
|
|
#include "C4Network2.h"
|
|
|
|
#include "C4Network2Stats.h"
|
|
|
|
#include "C4Viewport.h"
|
|
|
|
#include "C4GameOptions.h"
|
2009-06-05 18:00:23 +00:00
|
|
|
#include <C4Game.h>
|
2009-06-12 23:09:32 +00:00
|
|
|
#include <C4PlayerList.h>
|
2009-06-15 22:06:37 +00:00
|
|
|
#include <C4GameControl.h>
|
2010-06-27 00:42:48 +00:00
|
|
|
#include <C4GraphicsResource.h>
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
#ifndef HAVE_WINSOCK
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
// C4Network2ClientDlg
|
|
|
|
|
|
|
|
C4Network2ClientDlg::C4Network2ClientDlg(int iForClientID)
|
2010-03-28 18:58:01 +00:00
|
|
|
: C4GUI::InfoDialog(LoadResStr("IDS_NET_CLIENT_INFO"), 10), iClientID(iForClientID)
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// initial text update
|
|
|
|
UpdateText();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientDlg::UpdateText()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// begin updating (clears previous text)
|
|
|
|
BeginUpdateText();
|
|
|
|
// get core
|
|
|
|
const C4Client *pClient = Game.Clients.getClientByID(iClientID);
|
|
|
|
if (!pClient)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// client ID unknown
|
|
|
|
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_UNKNOWNID"), iClientID);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// get client (may be NULL for local info)
|
|
|
|
C4Network2Client *pNetClient = pClient->getNetClient();
|
|
|
|
// show some info
|
2008-06-11 20:17:42 +00:00
|
|
|
StdCopyStrBuf strInfo;
|
|
|
|
if (!pClient->isActivated()) { strInfo.Append(LoadResStr("IDS_MSG_INACTIVE")); strInfo.Append(" "); }
|
|
|
|
if (pClient->isLocal()) { strInfo.Append(LoadResStr("IDS_MSG_LOCAL")); strInfo.Append(" "); }
|
|
|
|
strInfo.AppendFormat("%s %s (ID #%d)%s",
|
|
|
|
LoadResStr(pClient->isHost() ? "IDS_MSG_HOST" : "IDS_MSG_CLIENT"),
|
|
|
|
pClient->getName(),
|
|
|
|
iClientID,
|
|
|
|
::Network.isHost() && pNetClient && !pNetClient->isReady() ? " (!ack)" : "");
|
|
|
|
AddLine(strInfo.getData());
|
2009-05-08 13:28:41 +00:00
|
|
|
// show addresses
|
|
|
|
int iCnt;
|
2010-01-25 04:00:59 +00:00
|
|
|
if ((iCnt=pNetClient->getAddrCnt()))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
AddLine(LoadResStr("IDS_NET_CLIENT_INFO_ADDRESSES"));
|
|
|
|
for (int i=0; i<iCnt; ++i)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4Network2Address addr = pNetClient->getAddr(i);
|
|
|
|
AddLineFmt(" %d: %s",
|
2010-03-28 18:58:01 +00:00
|
|
|
i, // adress index
|
|
|
|
addr.toString().getData());
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
|
|
|
AddLine(LoadResStr("IDS_NET_CLIENT_INFO_NOADDRESSES"));
|
|
|
|
// show connection
|
|
|
|
if (pNetClient)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// connections
|
2010-03-28 18:58:01 +00:00
|
|
|
if (pNetClient->isConnected())
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNECTIONS"),
|
2010-03-28 18:58:01 +00:00
|
|
|
pNetClient->getMsgConn() == pNetClient->getDataConn() ? "Msg/Data" : "Msg",
|
|
|
|
::Network.NetIO.getNetIOName(pNetClient->getMsgConn()->getNetClass()),
|
|
|
|
inet_ntoa(pNetClient->getMsgConn()->getPeerAddr().sin_addr),
|
|
|
|
htons(pNetClient->getMsgConn()->getPeerAddr().sin_port),
|
|
|
|
pNetClient->getMsgConn()->getPingTime());
|
|
|
|
if (pNetClient->getMsgConn() != pNetClient->getDataConn())
|
|
|
|
AddLineFmt(LoadResStr("IDS_NET_CLIENT_INFO_CONNDATA"),
|
|
|
|
::Network.NetIO.getNetIOName(pNetClient->getDataConn()->getNetClass()),
|
|
|
|
inet_ntoa(pNetClient->getDataConn()->getPeerAddr().sin_addr),
|
|
|
|
htons(pNetClient->getDataConn()->getPeerAddr().sin_port),
|
|
|
|
pNetClient->getDataConn()->getPingTime());
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
|
|
|
AddLine(LoadResStr("IDS_NET_CLIENT_INFO_NOCONNECTIONS"));
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// update done
|
|
|
|
EndUpdateText();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
// C4Network2ClientListBox::ClientListItem
|
|
|
|
|
|
|
|
C4Network2ClientListBox::ClientListItem::ClientListItem(class C4Network2ClientListBox *pForDlg, int iClientID) // ctor
|
2010-03-28 18:58:01 +00:00
|
|
|
: ListItem(pForDlg, iClientID), pStatusIcon(NULL), pName(NULL), pPing(NULL), pActivateBtn(NULL), pKickBtn(NULL)
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// get associated client
|
|
|
|
const C4Client *pClient = GetClient();
|
|
|
|
// get size
|
2010-06-27 00:42:48 +00:00
|
|
|
int iIconSize = ::GraphicsResource.TextFont.GetLineHeight();
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pForDlg->IsStartup()) iIconSize *= 2;
|
|
|
|
int iWidth = pForDlg->GetItemWidth();
|
|
|
|
int iVerticalIndent = 2;
|
|
|
|
SetBounds(C4Rect(0, 0, iWidth, iIconSize+2*iVerticalIndent));
|
|
|
|
C4GUI::ComponentAligner ca(GetContainedClientRect(), 0,iVerticalIndent);
|
|
|
|
// create subcomponents
|
|
|
|
bool fIsHost = pClient && pClient->isHost();
|
|
|
|
pStatusIcon = new C4GUI::Icon(ca.GetFromLeft(iIconSize), fIsHost ? C4GUI::Ico_Host : C4GUI::Ico_Client);
|
|
|
|
StdStrBuf sNameLabel;
|
|
|
|
if (pClient)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pForDlg->IsStartup())
|
|
|
|
sNameLabel.Ref(pClient->getName());
|
|
|
|
else
|
|
|
|
sNameLabel.Format("%s:%s", pClient->getName(), pClient->getNick());
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
sNameLabel.Ref("???");
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
pName = new C4GUI::Label(sNameLabel.getData(), iIconSize + IconLabelSpacing,iVerticalIndent, ALeft);
|
|
|
|
int iPingRightPos = GetBounds().Wdt - IconLabelSpacing;
|
2009-06-05 15:19:46 +00:00
|
|
|
if (::Network.isHost()) iPingRightPos -= 48;
|
|
|
|
if (::Network.isHost() && pClient && !pClient->isHost())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// activate/deactivate and kick btns for clients at host
|
|
|
|
if (!pForDlg->IsStartup())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pActivateBtn = new C4GUI::CallbackButtonEx<C4Network2ClientListBox::ClientListItem, C4GUI::IconButton>(C4GUI::Ico_Active, GetToprightCornerRect(Max(iIconSize, 16),Max(iIconSize, 16),2,1,1), 0, this, &ClientListItem::OnButtonActivate);
|
|
|
|
fShownActive = true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
pKickBtn = new C4GUI::CallbackButtonEx<C4Network2ClientListBox::ClientListItem, C4GUI::IconButton>(C4GUI::Ico_Kick, GetToprightCornerRect(Max(iIconSize, 16),Max(iIconSize, 16),2,1,0), 0, this, &ClientListItem::OnButtonKick);
|
|
|
|
pKickBtn->SetToolTip(LoadResStrNoAmp("IDS_NET_KICKCLIENT"));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!pForDlg->IsStartup()) if (pClient && !pClient->isLocal())
|
|
|
|
{
|
2010-03-28 18:58:01 +00:00
|
|
|
// wait time
|
|
|
|
pPing = new C4GUI::Label("???", iPingRightPos, iVerticalIndent, ARight);
|
|
|
|
pPing->SetToolTip(LoadResStr("IDS_DESC_CONTROLWAITTIME"));
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
|
|
|
// add components
|
|
|
|
AddElement(pStatusIcon); AddElement(pName);
|
|
|
|
if (pPing) AddElement(pPing);
|
|
|
|
if (pActivateBtn) AddElement(pActivateBtn);
|
|
|
|
if (pKickBtn) AddElement(pKickBtn);
|
|
|
|
// add to listbox (will eventually get moved)
|
|
|
|
pForDlg->AddElement(this);
|
|
|
|
// first-time update
|
|
|
|
Update();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListBox::ClientListItem::Update()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// update wait label
|
|
|
|
if (pPing)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-06-15 22:06:37 +00:00
|
|
|
int iWait = ::Control.Network.ClientPerfStat(iClientID);
|
2009-05-11 13:09:53 +00:00
|
|
|
pPing->SetText(FormatString("%d ms", iWait).getData());
|
2011-03-11 02:37:27 +00:00
|
|
|
pPing->SetColor(C4RGB(
|
2010-03-28 18:58:01 +00:00
|
|
|
BoundBy(255-Abs(iWait)*5, 0, 255),
|
|
|
|
BoundBy(255-iWait*5, 0, 255),
|
|
|
|
BoundBy(255+iWait*5, 0, 255)));
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// update activation status
|
|
|
|
const C4Client *pClient = GetClient(); if (!pClient) return;
|
|
|
|
bool fIsActive = pClient->isActivated();
|
|
|
|
if (fIsActive != fShownActive)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
fShownActive = fIsActive;
|
|
|
|
if (!pClient->isHost()) pStatusIcon->SetIcon(fIsActive ? C4GUI::Ico_Client : C4GUI::Ico_ObserverClient);
|
|
|
|
if (pActivateBtn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pActivateBtn->SetIcon(fIsActive ? C4GUI::Ico_Active : C4GUI::Ico_Inactive);
|
|
|
|
pActivateBtn->SetToolTip(LoadResStrNoAmp(fIsActive ? "IDS_NET_DEACTIVATECLIENT" : "IDS_NET_ACTIVATECLIENT"));
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// update players in tooltip
|
|
|
|
StdStrBuf sCltPlrs(Game.PlayerInfos.GetActivePlayerNames(false, iClientID));
|
|
|
|
pName->SetToolTip(sCltPlrs.getData());
|
|
|
|
// update icon: Network status
|
|
|
|
C4GUI::Icons icoStatus = C4GUI::Ico_UnknownClient;
|
|
|
|
C4Network2Client *pClt = pClient->getNetClient();
|
|
|
|
if (pClt)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
switch (pClt->getStatus())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
|
|
|
case NCS_Joining: // waiting for join data
|
|
|
|
case NCS_Chasing: // client is behind (status not acknowledged, isn't waited for)
|
|
|
|
case NCS_NotReady: // client is behind (status not acknowledged)
|
|
|
|
icoStatus = C4GUI::Ico_Loading;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NCS_Ready: // client acknowledged network status
|
|
|
|
icoStatus = C4GUI::Ico_Ready;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NCS_Remove: // client is to be removed
|
|
|
|
icoStatus = C4GUI::Ico_Kick;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: // whatever
|
|
|
|
assert(false);
|
|
|
|
icoStatus = C4GUI::Ico_Loading;
|
|
|
|
break;
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// network OK - control ready?
|
|
|
|
if (!pForDlg->IsStartup() && (icoStatus == C4GUI::Ico_Ready))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-06-15 22:06:37 +00:00
|
|
|
if (!::Control.Network.ClientReady(iClientID, ::Control.ControlTick))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// control not ready
|
|
|
|
icoStatus = C4GUI::Ico_NetWait;
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// set new icon
|
|
|
|
pStatusIcon->SetIcon(icoStatus);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
const C4Client *C4Network2ClientListBox::ClientListItem::GetClient() const
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
return Game.Clients.getClientByID(iClientID);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListBox::ClientListItem::OnButtonActivate(C4GUI::Control *pButton)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// league: Do not deactivate clients with players
|
2009-06-12 23:09:32 +00:00
|
|
|
if (Game.Parameters.isLeague() && ::Players.GetAtClient(iClientID))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
Log(LoadResStr("IDS_LOG_COMMANDNOTALLOWEDINLEAGUE"));
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// change to status that is not currently shown
|
2009-06-15 22:06:37 +00:00
|
|
|
::Control.DoInput(CID_ClientUpdate, new C4ControlClientUpdate(iClientID, CUT_Activate, !fShownActive), CDT_Sync);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListBox::ClientListItem::OnButtonKick(C4GUI::Control *pButton)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// try kick
|
|
|
|
// league: Kick needs voting
|
2010-03-28 18:58:01 +00:00
|
|
|
if (Game.Parameters.isLeague() && ::Players.GetAtClient(iClientID))
|
2009-06-05 15:19:46 +00:00
|
|
|
::Network.Vote(VT_Kick, true, iClientID);
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
|
|
|
Game.Clients.CtrlRemove(GetClient(), LoadResStr(pForDlg->IsStartup() ? "IDS_MSG_KICKFROMSTARTUPDLG" : "IDS_MSG_KICKFROMCLIENTLIST"));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
// C4Network2ClientListBox::ConnectionListItem
|
|
|
|
|
|
|
|
C4Network2ClientListBox::ConnectionListItem::ConnectionListItem(class C4Network2ClientListBox *pForDlg, int32_t iClientID, int32_t iConnectionID) // ctor
|
2010-03-28 18:58:01 +00:00
|
|
|
: ListItem(pForDlg, iClientID), iConnID(iConnectionID), pDesc(NULL), pPing(NULL), pReconnectBtn(NULL), pDisconnectBtn(NULL)
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// get size
|
2010-06-27 00:42:48 +00:00
|
|
|
CStdFont &rUseFont = ::GraphicsResource.TextFont;
|
2009-05-08 13:28:41 +00:00
|
|
|
int iIconSize = rUseFont.GetLineHeight();
|
|
|
|
int iWidth = pForDlg->GetItemWidth();
|
|
|
|
int iVerticalIndent = 2;
|
|
|
|
SetBounds(C4Rect(0, 0, iWidth, iIconSize+2*iVerticalIndent));
|
|
|
|
C4GUI::ComponentAligner ca(GetContainedClientRect(), 0,iVerticalIndent);
|
|
|
|
// left indent
|
|
|
|
ca.ExpandLeft(-iIconSize*2);
|
|
|
|
// create subcomponents
|
|
|
|
// reconnect/disconnect buttons
|
|
|
|
//pReconnectBtn = new C4GUI::CallbackButtonEx<C4Network2ClientListBox::ConnectionListItem, C4GUI::IconButton>(C4GUI::Ico_Notify, ca.GetFromRight(iIconSize, iIconSize), 0, this, &ConnectionListItem::OnButtonReconnect);
|
|
|
|
if (!Game.Parameters.isLeague())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pDisconnectBtn = new C4GUI::CallbackButtonEx<C4Network2ClientListBox::ConnectionListItem, C4GUI::IconButton>(C4GUI::Ico_Disconnect, ca.GetFromRight(iIconSize, iIconSize), 0, this, &ConnectionListItem::OnButtonDisconnect);
|
|
|
|
pDisconnectBtn->SetToolTip(LoadResStr("IDS_MENU_DISCONNECT"));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
|
|
|
pDisconnectBtn = NULL;
|
|
|
|
// ping time
|
|
|
|
int32_t sx=40, sy=iIconSize;
|
|
|
|
rUseFont.GetTextExtent("???? ms", sx,sy, true);
|
|
|
|
pPing = new C4GUI::Label("???", ca.GetFromRight(sx, sy), ARight);
|
|
|
|
pPing->SetToolTip(LoadResStr("IDS_NET_CONTROL_PING"));
|
|
|
|
// main description item
|
|
|
|
pDesc = new C4GUI::Label("???", ca.GetAll(), ALeft);
|
|
|
|
// add components
|
|
|
|
AddElement(pDesc);
|
|
|
|
AddElement(pPing);
|
|
|
|
//AddElement(pReconnectBtn);
|
|
|
|
if (pDisconnectBtn) AddElement(pDisconnectBtn);
|
|
|
|
// add to listbox (will eventually get moved)
|
|
|
|
pForDlg->AddElement(this);
|
|
|
|
// first-time update
|
|
|
|
Update();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
C4Network2IOConnection *C4Network2ClientListBox::ConnectionListItem::GetConnection() const
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// get connection by connection ID
|
2009-06-05 15:19:46 +00:00
|
|
|
C4Network2Client *pNetClient = ::Network.Clients.GetClientByID(iClientID);
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!pNetClient) return NULL;
|
|
|
|
if (iConnID == 0) return pNetClient->getDataConn();
|
|
|
|
if (iConnID == 1) return pNetClient->getMsgConn();
|
|
|
|
return NULL;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListBox::ConnectionListItem::Update()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4Network2IOConnection *pConn = GetConnection();
|
|
|
|
if (!pConn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// No connection: Shouldn't happen
|
|
|
|
pDesc->SetText("???");
|
|
|
|
pPing->SetText("???");
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// update connection ping
|
|
|
|
int iPing = pConn->getLag();
|
|
|
|
pPing->SetText(FormatString("%d ms", iPing).getData());
|
|
|
|
// update description
|
|
|
|
// get connection usage
|
|
|
|
const char *szConnType;
|
2009-06-05 15:19:46 +00:00
|
|
|
C4Network2Client *pNetClient = ::Network.Clients.GetClientByID(iClientID);
|
2009-05-08 13:28:41 +00:00
|
|
|
if (pNetClient->getDataConn() == pNetClient->getMsgConn())
|
|
|
|
szConnType = "Data/Msg";
|
|
|
|
else if (iConnID)
|
|
|
|
szConnType = "Msg";
|
|
|
|
else
|
|
|
|
szConnType = "Data";
|
|
|
|
// display info
|
|
|
|
pDesc->SetText(FormatString("%s: %s (%s:%d l%d)",
|
2010-03-28 18:58:01 +00:00
|
|
|
szConnType,
|
|
|
|
::Network.NetIO.getNetIOName(pConn->getNetClass()),
|
|
|
|
inet_ntoa(pConn->getPeerAddr().sin_addr),
|
|
|
|
htons(pConn->getPeerAddr().sin_port),
|
|
|
|
pConn->getPacketLoss()).getData());
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListBox::ConnectionListItem::OnButtonDisconnect(C4GUI::Control *pButton)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// close connection
|
|
|
|
C4Network2IOConnection *pConn = GetConnection();
|
|
|
|
if (pConn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pConn->Close();
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListBox::ConnectionListItem::OnButtonReconnect(C4GUI::Control *pButton)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// 2do
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
// C4Network2ClientListBox
|
|
|
|
|
|
|
|
C4Network2ClientListBox::C4Network2ClientListBox(C4Rect &rcBounds, bool fStartup) : ListBox(rcBounds), fStartup(fStartup)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// hook into timer callback
|
|
|
|
Application.Add(this);
|
|
|
|
// initial update
|
|
|
|
Update();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListBox::Update()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// sync with client list
|
|
|
|
ListItem *pItem = static_cast<ListItem *>(pClientWindow->GetFirst()), *pNext;
|
|
|
|
const C4Client *pClient = NULL;
|
2010-01-25 04:00:59 +00:00
|
|
|
while ((pClient = Game.Clients.getClient(pClient)))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// skip host in startup board
|
|
|
|
if (IsStartup() && pClient->isHost()) continue;
|
|
|
|
// deleted client(s) present? this will also delete unneeded client connections of previous client
|
|
|
|
while (pItem && (pItem->GetClientID() < pClient->getID()))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pNext = static_cast<ListItem *>(pItem->GetNext());
|
|
|
|
delete pItem; pItem = pNext;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// same present for update?
|
|
|
|
// need not check for connection ID, because a client item will always be placed before the corresponding connection items
|
|
|
|
if (pItem && pItem->GetClientID() == pClient->getID())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pItem->Update();
|
|
|
|
pItem = static_cast<ListItem *>(pItem->GetNext());
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
|
|
|
// not present: insert (or add if pItem=NULL)
|
|
|
|
InsertElement(new ClientListItem(this, pClient->getID()), pItem);
|
|
|
|
// update connections for client
|
|
|
|
// but no connections in startup board
|
|
|
|
if (IsStartup()) continue;
|
|
|
|
// enumerate client connections
|
|
|
|
C4Network2Client *pNetClient = pClient->getNetClient();
|
|
|
|
if (!pNetClient) continue; // local client does not have connections
|
|
|
|
C4Network2IOConnection *pLastConn = NULL;
|
|
|
|
for (int i = 0; i<2; ++i)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4Network2IOConnection *pConn = i ? pNetClient->getMsgConn() : pNetClient->getDataConn();
|
|
|
|
if (!pConn) continue;
|
|
|
|
if (pConn == pLastConn) continue; // combined connection: Display only one
|
|
|
|
pLastConn = pConn;
|
|
|
|
// del leading items
|
|
|
|
while (pItem && ((pItem->GetClientID() < pClient->getID()) || ((pItem->GetClientID() == pClient->getID()) && (pItem->GetConnectionID() < i))))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pNext = static_cast<ListItem *>(pItem->GetNext());
|
|
|
|
delete pItem; pItem = pNext;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// update connection item
|
|
|
|
if (pItem && pItem->GetClientID() == pClient->getID() && pItem->GetConnectionID() == i)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pItem->Update();
|
|
|
|
pItem = static_cast<ListItem *>(pItem->GetNext());
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// new connection: create it
|
|
|
|
InsertElement(new ConnectionListItem(this, pClient->getID(), i), pItem);
|
|
|
|
}
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// del trailing items
|
|
|
|
while (pItem)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
pNext = static_cast<ListItem *>(pItem->GetNext());
|
|
|
|
delete pItem; pItem = pNext;
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
// C4Network2ClientListDlg
|
|
|
|
|
|
|
|
// singleton
|
|
|
|
C4Network2ClientListDlg *C4Network2ClientListDlg::pInstance = NULL;
|
|
|
|
|
|
|
|
C4Network2ClientListDlg::C4Network2ClientListDlg()
|
2010-03-28 18:58:01 +00:00
|
|
|
: Dialog(::pGUI->GetPreferredDlgRect().Wdt*3/4, ::pGUI->GetPreferredDlgRect().Hgt*3/4, LoadResStr("IDS_NET_CAPTION"), false)
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// component layout
|
2010-06-27 00:42:48 +00:00
|
|
|
CStdFont *pUseFont = &::GraphicsResource.TextFont;
|
2009-05-08 13:28:41 +00:00
|
|
|
C4GUI::ComponentAligner caAll(GetContainedClientRect(), 0,0);
|
|
|
|
C4Rect rcStatus = caAll.GetFromBottom(pUseFont->GetLineHeight());
|
|
|
|
// create game options; max 1/2 of dialog height
|
|
|
|
pGameOptions = new C4GameOptionsList(caAll.GetFromTop(caAll.GetInnerHeight()/2), true, true);
|
|
|
|
pGameOptions->SetDecoration(false, NULL, true, false);
|
|
|
|
pGameOptions->SetSelectionDiabled();
|
|
|
|
// but resize to actually used height
|
|
|
|
int32_t iFreedHeight = pGameOptions->ContractToElementHeight();
|
|
|
|
caAll.ExpandTop(iFreedHeight);
|
|
|
|
AddElement(pGameOptions);
|
|
|
|
// create client list box
|
|
|
|
AddElement(pListBox = new C4Network2ClientListBox(caAll.GetAll(), false));
|
|
|
|
// create status label
|
|
|
|
AddElement(pStatusLabel = new C4GUI::Label("", rcStatus));
|
|
|
|
// add timer
|
|
|
|
Application.Add(this);
|
|
|
|
// initial update
|
|
|
|
Update();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Network2ClientListDlg::Update()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Compose status text
|
|
|
|
StdStrBuf sStatusText;
|
|
|
|
sStatusText.Format("Tick %d, Behind %d, Rate %d, PreSend %d, ACT: %d",
|
2010-03-28 18:58:01 +00:00
|
|
|
(int)::Control.ControlTick, (int)::Control.Network.GetBehind(::Control.ControlTick),
|
|
|
|
(int)::Control.ControlRate, (int)::Control.Network.getControlPreSend(),
|
|
|
|
(int)::Control.Network.getAvgControlSendTime());
|
2009-05-08 13:28:41 +00:00
|
|
|
// Update status label
|
|
|
|
pStatusLabel->SetText(sStatusText.getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
bool C4Network2ClientListDlg::Toggle()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// toggle off?
|
|
|
|
if (pInstance) { pInstance->Close(true); return true; }
|
2010-03-27 16:05:02 +00:00
|
|
|
// toggle on!
|
2009-06-05 16:53:56 +00:00
|
|
|
return ::pGUI->ShowRemoveDlg(pInstance = new C4Network2ClientListDlg());
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------
|
|
|
|
// C4Network2StartWaitDlg
|
|
|
|
|
|
|
|
C4Network2StartWaitDlg::C4Network2StartWaitDlg()
|
2010-03-28 18:58:01 +00:00
|
|
|
: C4GUI::Dialog(DialogWidth, DialogHeight, LoadResStr("IDS_NET_CAPTION"), false), pClientListBox(NULL)
|
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4GUI::ComponentAligner caAll(GetContainedClientRect(), C4GUI_DefDlgIndent, C4GUI_DefDlgIndent);
|
|
|
|
C4GUI::ComponentAligner caButtonArea(caAll.GetFromBottom(C4GUI_ButtonAreaHgt), 0,0);
|
|
|
|
// create top label
|
|
|
|
C4GUI::Label *pLbl;
|
|
|
|
AddElement(pLbl = new C4GUI::Label(LoadResStr("IDS_NET_WAITFORSTART"), caAll.GetFromTop(25), ACenter));
|
|
|
|
// create client list box
|
|
|
|
AddElement(pClientListBox = new C4Network2ClientListBox(caAll.GetAll(), true));
|
|
|
|
// place abort button
|
|
|
|
C4GUI::Button *pBtnAbort = new C4GUI::CancelButton(caButtonArea.GetCentered(C4GUI_DefButtonWdt, C4GUI_ButtonHgt));
|
|
|
|
AddElement(pBtnAbort); //pBtnAbort->SetToolTip(LoadResStr("IDS_DLGTIP_CANCEL"));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------
|
|
|
|
// C4GameOptionButtons
|
|
|
|
|
|
|
|
C4GameOptionButtons::C4GameOptionButtons(const C4Rect &rcBounds, bool fNetwork, bool fHost, bool fLobby)
|
2010-12-10 00:06:38 +00:00
|
|
|
: C4GUI::Window(), fNetwork(fNetwork), fHost(fHost), fLobby(fLobby), fCountdown(false)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
SetBounds(rcBounds);
|
|
|
|
// calculate button size from area
|
|
|
|
int32_t iButtonCount = fNetwork ? fHost ? 6 : 3 : 2;
|
|
|
|
int32_t iIconSize = Min<int32_t>(C4GUI_IconExHgt, rcBounds.Hgt), iIconSpacing = rcBounds.Wdt/(rcBounds.Wdt >= 400 ? 64 : 128);
|
|
|
|
if ((iIconSize+iIconSpacing*2)*iButtonCount > rcBounds.Wdt)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (iIconSize*iButtonCount <= rcBounds.Wdt)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
iIconSpacing = Max<int32_t>(0, (rcBounds.Wdt-iIconSize*iButtonCount)/(iButtonCount*2)-1);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
iIconSpacing = 0;
|
|
|
|
iIconSize = rcBounds.Wdt / iButtonCount;
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
C4GUI::ComponentAligner caButtonArea(rcBounds,0,0,true);
|
|
|
|
C4GUI::ComponentAligner caButtons(caButtonArea.GetCentered((iIconSize+2*iIconSpacing)*iButtonCount, iIconSize),iIconSpacing,0);
|
|
|
|
// add buttons
|
|
|
|
if (fNetwork && fHost)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
bool fIsInternet = !!Config.Network.MasterServerSignUp, fIsDisabled = false;
|
|
|
|
// league currently implies master server signup, and can thus not be turned off
|
|
|
|
if (fLobby && Game.Parameters.isLeague())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
fIsInternet = true;
|
|
|
|
fIsDisabled = true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
btnInternet = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(fIsInternet ? C4GUI::Ico_Ex_InternetOn : C4GUI::Ico_Ex_InternetOff, caButtons.GetFromLeft(iIconSize, iIconSize), 'I' /* 2do */, &C4GameOptionButtons::OnBtnInternet, this);
|
|
|
|
btnInternet->SetToolTip(LoadResStr("IDS_DLGTIP_STARTINTERNETGAME"));
|
|
|
|
btnInternet->SetEnabled(!fIsDisabled);
|
|
|
|
AddElement(btnInternet);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else btnInternet = NULL;
|
|
|
|
bool fIsLeague = false;
|
2010-11-09 12:17:02 +00:00
|
|
|
// League button disabled (#479, re-enable when an OC league exists)
|
|
|
|
if (0 && fNetwork)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4GUI::Icons eLeagueIcon;
|
|
|
|
fIsLeague = fLobby ? Game.Parameters.isLeague() : !!Config.Network.LeagueServerSignUp;
|
|
|
|
eLeagueIcon = fIsLeague ? C4GUI::Ico_Ex_LeagueOn : C4GUI::Ico_Ex_LeagueOff;
|
|
|
|
btnLeague = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(eLeagueIcon, caButtons.GetFromLeft(iIconSize, iIconSize), 'L' /* 2do */, &C4GameOptionButtons::OnBtnLeague, this);
|
|
|
|
btnLeague->SetToolTip(LoadResStr("IDS_DLGTIP_STARTLEAGUEGAME"));
|
|
|
|
btnLeague->SetEnabled(fHost && !fLobby);
|
|
|
|
AddElement(btnLeague);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else btnLeague=NULL;
|
|
|
|
if (fNetwork && fHost)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-06-05 15:19:46 +00:00
|
|
|
btnPassword = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(::Network.isPassworded() ? C4GUI::Ico_Ex_Locked : C4GUI::Ico_Ex_Unlocked, caButtons.GetFromLeft(iIconSize, iIconSize), 'P' /* 2do */, &C4GameOptionButtons::OnBtnPassword, this);
|
2009-05-08 13:28:41 +00:00
|
|
|
btnPassword->SetToolTip(LoadResStr("IDS_NET_PASSWORD_DESC"));
|
|
|
|
AddElement(btnPassword);
|
|
|
|
btnComment = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(C4GUI::Ico_Ex_Comment, caButtons.GetFromLeft(iIconSize, iIconSize), 'M' /* 2do */, &C4GameOptionButtons::OnBtnComment, this);
|
|
|
|
btnComment->SetToolTip(LoadResStr("IDS_DESC_COMMENTDESCRIPTIONFORTHIS"));
|
|
|
|
AddElement(btnComment);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else btnPassword=btnComment=NULL;
|
|
|
|
btnRecord = new C4GUI::CallbackButton<C4GameOptionButtons, C4GUI::IconButton>(Game.Record || fIsLeague ? C4GUI::Ico_Ex_RecordOn : C4GUI::Ico_Ex_RecordOff, caButtons.GetFromLeft(iIconSize, iIconSize), 'R' /* 2do */, &C4GameOptionButtons::OnBtnRecord, this);
|
|
|
|
btnRecord->SetEnabled(!fIsLeague);
|
|
|
|
btnRecord->SetToolTip(LoadResStr("IDS_DLGTIP_RECORD"));
|
|
|
|
AddElement(btnRecord);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::OnBtnInternet(C4GUI::Control *btn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!fNetwork || !fHost) return;
|
2010-01-25 04:00:59 +00:00
|
|
|
bool fCheck = (Config.Network.MasterServerSignUp = !Config.Network.MasterServerSignUp);
|
2009-05-08 13:28:41 +00:00
|
|
|
// in lobby mode, do actual termination from masterserver
|
|
|
|
if (fLobby)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (fCheck)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-06-05 15:19:46 +00:00
|
|
|
fCheck = ::Network.LeagueSignupEnable();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-06-05 15:19:46 +00:00
|
|
|
::Network.LeagueSignupDisable();
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
btnInternet->SetIcon(fCheck ? C4GUI::Ico_Ex_InternetOn : C4GUI::Ico_Ex_InternetOff);
|
|
|
|
// also update league button, because turning off masterserver also turns off the league
|
|
|
|
if (!fCheck)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
Config.Network.LeagueServerSignUp = false;
|
2010-11-09 12:17:02 +00:00
|
|
|
if (btnLeague)
|
|
|
|
btnLeague->SetIcon(C4GUI::Ico_Ex_LeagueOff);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// re-set in config for the case of failure
|
|
|
|
Config.Network.MasterServerSignUp = fCheck;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::OnBtnLeague(C4GUI::Control *btn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!fNetwork || !fHost) return;
|
2010-01-25 04:00:59 +00:00
|
|
|
bool fCheck = (Config.Network.LeagueServerSignUp = !Config.Network.LeagueServerSignUp);
|
2009-05-08 13:28:41 +00:00
|
|
|
btnLeague->SetIcon(fCheck ? C4GUI::Ico_Ex_LeagueOn : C4GUI::Ico_Ex_LeagueOff);
|
2010-03-28 18:58:01 +00:00
|
|
|
if (!Game.Record) OnBtnRecord(btnRecord);
|
2009-05-08 13:28:41 +00:00
|
|
|
btnRecord->SetEnabled(!fCheck);
|
|
|
|
// if the league is turned on, the game must be signed up at the masterserver
|
|
|
|
if (fCheck && !Config.Network.MasterServerSignUp) OnBtnInternet(btnInternet);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::OnBtnRecord(C4GUI::Control *btn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-03-09 22:28:19 +00:00
|
|
|
bool fCheck = Config.General.DefRec = Game.Record = !Game.Record;
|
2009-05-08 13:28:41 +00:00
|
|
|
btnRecord->SetIcon(fCheck ? C4GUI::Ico_Ex_RecordOn : C4GUI::Ico_Ex_RecordOff);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::OnBtnPassword(C4GUI::Control *btn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!fNetwork || !fHost) return;
|
|
|
|
// password is currently set - a single click only clears the password
|
2009-06-05 15:19:46 +00:00
|
|
|
if (::Network.GetPassword() && *::Network.GetPassword())
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
StdStrBuf empty;
|
|
|
|
OnPasswordSet(empty);
|
|
|
|
return;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// password button pressed: Show dialog to set/change current password
|
|
|
|
C4GUI::InputDialog *pDlg;
|
|
|
|
GetScreen()->ShowRemoveDlg(pDlg=new C4GUI::InputDialog(LoadResStr("IDS_MSG_ENTERPASSWORD"), LoadResStr("IDS_DLG_PASSWORD"), C4GUI::Ico_Ex_LockedFrontal, new C4GUI::InputCallback<C4GameOptionButtons>(this, &C4GameOptionButtons::OnPasswordSet), false));
|
|
|
|
pDlg->SetMaxText(CFG_MaxString);
|
2009-06-05 15:19:46 +00:00
|
|
|
const char *szPassPreset = ::Network.GetPassword();
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!szPassPreset || !*szPassPreset) szPassPreset = Config.Network.LastPassword;
|
|
|
|
if (*szPassPreset) pDlg->SetInputText(szPassPreset);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::OnPasswordSet(const StdStrBuf &rsNewPassword)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// password input dialog answered with OK: Set/clear network password
|
|
|
|
const char *szPass;
|
2009-06-05 15:19:46 +00:00
|
|
|
::Network.SetPassword(szPass=rsNewPassword.getData());
|
2009-05-08 13:28:41 +00:00
|
|
|
// update icon to reflect if a password is set
|
|
|
|
UpdatePasswordBtn();
|
|
|
|
// remember password for next round
|
|
|
|
bool fHasPassword = (szPass && *szPass);
|
|
|
|
if (fHasPassword)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
SCopy(szPass, Config.Network.LastPassword, CFG_MaxString);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// acoustic feedback
|
|
|
|
C4GUI::GUISound("Connect");
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::UpdatePasswordBtn()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// update icon to reflect if a password is set
|
2009-06-05 15:19:46 +00:00
|
|
|
const char *szPass = ::Network.GetPassword();
|
2009-05-08 13:28:41 +00:00
|
|
|
bool fHasPassword = szPass && *szPass;
|
|
|
|
//btnPassword->SetHighlight(fHasPassword);
|
|
|
|
btnPassword->SetIcon(fHasPassword ? C4GUI::Ico_Ex_Locked : C4GUI::Ico_Ex_Unlocked);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::OnBtnComment(C4GUI::Control *btn)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// password button pressed: Show dialog to set/change current password
|
|
|
|
C4GUI::InputDialog *pDlg;
|
|
|
|
GetScreen()->ShowRemoveDlg(pDlg=new C4GUI::InputDialog(LoadResStr("IDS_CTL_ENTERCOMMENT"), LoadResStr("IDS_CTL_COMMENT"), C4GUI::Ico_Ex_Comment, new C4GUI::InputCallback<C4GameOptionButtons>(this, &C4GameOptionButtons::OnCommentSet), false));
|
|
|
|
pDlg->SetMaxText(C4MaxComment);
|
|
|
|
pDlg->SetInputText(Config.Network.Comment.getData());
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::OnCommentSet(const StdStrBuf &rsNewComment)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// check for change; no reference invalidation if not changed
|
|
|
|
if (rsNewComment == Config.Network.Comment) return;
|
2010-03-27 16:05:02 +00:00
|
|
|
// Set in configuration, update reference
|
2009-05-08 13:28:41 +00:00
|
|
|
Config.Network.Comment.CopyValidated(rsNewComment.getData());
|
2010-03-27 16:05:02 +00:00
|
|
|
::Network.InvalidateReference();
|
2009-05-08 13:28:41 +00:00
|
|
|
// message feedback
|
|
|
|
Log(LoadResStr("IDS_NET_COMMENTCHANGED"));
|
|
|
|
// acoustic feedback
|
|
|
|
C4GUI::GUISound("Connect");
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4GameOptionButtons::SetCountdown(bool fToVal)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
fCountdown = fToVal;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// ---------------------------------------------------
|
|
|
|
// C4Chart
|
|
|
|
|
|
|
|
int GetValueDecade(int iVal)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// get enclosing decade
|
|
|
|
int iDec = 1;
|
|
|
|
while (iVal) { iVal/=10; iDec*=10; }
|
|
|
|
return iDec;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
int GetAxisStepRange(int iRange, int iMaxSteps)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// try in steps of 5s and 10s
|
|
|
|
int iDec = GetValueDecade(iRange);
|
|
|
|
if (iDec == 1) return 1;
|
|
|
|
int iNextStepDivider = 2;
|
|
|
|
while (iDec>=iNextStepDivider && iNextStepDivider*iRange/iDec <= iMaxSteps)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
iDec/=iNextStepDivider;
|
2010-03-27 16:05:02 +00:00
|
|
|
iNextStepDivider = 7 - iNextStepDivider;
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
return iDec;
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4Chart::DrawElement(C4TargetFacet &cgo)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
typedef C4Graph::ValueType ValueType;
|
|
|
|
typedef C4Graph::TimeType TimeType;
|
|
|
|
// transparent w/o graph
|
|
|
|
if (!pDisplayGraph) return;
|
|
|
|
int iSeriesCount = pDisplayGraph->GetSeriesCount();
|
|
|
|
if (!iSeriesCount) return;
|
|
|
|
assert(iSeriesCount>0);
|
|
|
|
StdStrBuf sbuf;
|
|
|
|
pDisplayGraph->Update(); // update averages, etc.
|
|
|
|
// calc metrics
|
2010-06-27 00:42:48 +00:00
|
|
|
CStdFont &rFont = ::GraphicsResource.MiniFont;
|
2009-05-08 13:28:41 +00:00
|
|
|
int YAxisWdt = 5,
|
2011-08-03 23:30:37 +00:00
|
|
|
XAxisHgt = 15;
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
const int AxisArrowLen = 6,
|
2011-08-03 23:30:37 +00:00
|
|
|
AxisMarkerLen = 5,
|
|
|
|
AxisArrowThickness = 3,
|
|
|
|
AxisArrowIndent= 2; // margin between axis arrow and last value
|
2009-05-08 13:28:41 +00:00
|
|
|
int32_t YAxisMinStepHgt, XAxisMinStepWdt;
|
|
|
|
// get value range
|
|
|
|
int iMinTime = pDisplayGraph->GetStartTime();
|
|
|
|
int iMaxTime = pDisplayGraph->GetEndTime() - 1;
|
|
|
|
if (iMinTime >= iMaxTime) return;
|
|
|
|
ValueType iMinVal = pDisplayGraph->GetMinValue();
|
|
|
|
ValueType iMaxVal = pDisplayGraph->GetMaxValue();
|
|
|
|
if (iMinVal == iMaxVal) ++iMaxVal;
|
|
|
|
if (iMinVal > 0 && iMaxVal/iMinVal >= 2) iMinVal = 0; // go zero-based if this creates less than 50% unused space
|
|
|
|
else if (iMaxVal < 0 && iMinVal/iMaxVal >= 2) iMaxVal = 0;
|
|
|
|
int ddv;
|
|
|
|
if (iMaxVal>0 && (ddv=GetValueDecade(int(iMaxVal))/50))
|
|
|
|
iMaxVal = ((iMaxVal-(iMaxVal>0))/ddv+(iMaxVal>0))*ddv;
|
|
|
|
if (iMinVal && (ddv=GetValueDecade(int(iMinVal))/50))
|
|
|
|
iMinVal = ((iMinVal-(iMinVal<0))/ddv+(iMinVal<0))*ddv;
|
|
|
|
ValueType dv=iMaxVal-iMinVal; TimeType dt=iMaxTime-iMinTime;
|
|
|
|
// axis calculations
|
|
|
|
sbuf.Format("-%d", (int) Max(Abs(iMaxVal), Abs(iMinVal)));
|
|
|
|
rFont.GetTextExtent(sbuf.getData(), XAxisMinStepWdt, YAxisMinStepHgt, false);
|
|
|
|
YAxisWdt += XAxisMinStepWdt; XAxisHgt += YAxisMinStepHgt;
|
|
|
|
XAxisMinStepWdt += 2; YAxisMinStepHgt += 2;
|
|
|
|
int tw = rcBounds.Wdt - YAxisWdt;
|
|
|
|
int th = rcBounds.Hgt - XAxisHgt;
|
|
|
|
int tx = rcBounds.x + int(cgo.TargetX) + YAxisWdt;
|
|
|
|
int ty = rcBounds.y + int(cgo.TargetY);
|
|
|
|
// show a legend, if more than one graph is shown
|
|
|
|
if (iSeriesCount > 1)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
int iSeries = 0; const C4Graph *pSeries;
|
|
|
|
int32_t iLegendWdt = 0, Q,W;
|
2010-01-25 04:00:59 +00:00
|
|
|
while ((pSeries = pDisplayGraph->GetSeries(iSeries++)))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
rFont.GetTextExtent(pSeries->GetTitle(), W, Q, true);
|
|
|
|
iLegendWdt = Max(iLegendWdt, W);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
tw -= iLegendWdt+1;
|
|
|
|
iSeries = 0;
|
|
|
|
int iYLegendDraw = (th - iSeriesCount*Q)/2 + ty;
|
2010-01-25 04:00:59 +00:00
|
|
|
while ((pSeries = pDisplayGraph->GetSeries(iSeries++)))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->TextOut(pSeries->GetTitle(), rFont, 1.0f, cgo.Surface, tx+tw, iYLegendDraw, pSeries->GetColorDw() | 0xff000000, ALeft, true);
|
2009-05-08 13:28:41 +00:00
|
|
|
iYLegendDraw += Q;
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// safety: too small?
|
|
|
|
if (tw < 10 || th < 10) return;
|
|
|
|
// draw axis
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->DrawLineDw(cgo.Surface, tx, ty+th, tx+tw-1, ty+th, C4RGB(0x91, 0x91, 0x91));
|
|
|
|
pDraw->DrawLineDw(cgo.Surface, tx+tw-1, ty+th, tx+tw-1-AxisArrowLen, ty+th-AxisArrowThickness, C4RGB(0x91, 0x91, 0x91));
|
|
|
|
pDraw->DrawLineDw(cgo.Surface, tx+tw-1, ty+th, tx+tw-1-AxisArrowLen, ty+th+AxisArrowThickness, C4RGB(0x91, 0x91, 0x91));
|
|
|
|
pDraw->DrawLineDw(cgo.Surface, tx, ty, tx, ty+th, C4RGB(0x91, 0x91, 0x91));
|
|
|
|
pDraw->DrawLineDw(cgo.Surface, tx, ty, tx-AxisArrowThickness, ty+AxisArrowLen, C4RGB(0x91, 0x91, 0x91));
|
|
|
|
pDraw->DrawLineDw(cgo.Surface, tx, ty, tx+AxisArrowThickness, ty+AxisArrowLen, C4RGB(0x91, 0x91, 0x91));
|
2009-05-08 13:28:41 +00:00
|
|
|
tw -= AxisArrowLen + AxisArrowIndent;
|
|
|
|
th -= AxisArrowLen + AxisArrowIndent; ty += AxisArrowLen + AxisArrowIndent;
|
|
|
|
// do axis numbering
|
|
|
|
int iXAxisSteps = GetAxisStepRange(dt, tw / XAxisMinStepWdt),
|
2010-03-28 18:58:01 +00:00
|
|
|
iYAxisSteps = GetAxisStepRange(int(dv), th / YAxisMinStepHgt);
|
2009-05-08 13:28:41 +00:00
|
|
|
int iX, iY, iTime, iVal;
|
2010-01-25 04:00:59 +00:00
|
|
|
iY = 0;
|
2009-05-08 13:28:41 +00:00
|
|
|
iTime = ((iMinTime-(iMinTime>0))/iXAxisSteps+(iMinTime>0))*iXAxisSteps;
|
|
|
|
for (; iTime <= iMaxTime; iTime += iXAxisSteps)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
iX = tx + tw * (iTime-iMinTime) / dt;
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->DrawLineDw(cgo.Surface, iX, ty+th+1, iX, ty+th+AxisMarkerLen, C4RGB(0x91, 0x91, 0x91));
|
2009-05-08 13:28:41 +00:00
|
|
|
sbuf.Format("%d", (int) iTime);
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->TextOut(sbuf.getData(), rFont, 1.0f, cgo.Surface, iX, ty+th+AxisMarkerLen, 0xff7f7f7f, ACenter, false);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
iVal = int( ((iMinVal-(iMinVal>0))/iYAxisSteps+(iMinVal>0))*iYAxisSteps );
|
|
|
|
for (; iVal <= iMaxVal; iVal += iYAxisSteps)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
iY = ty+th - int((iVal-iMinVal) / dv * th);
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->DrawLineDw(cgo.Surface, tx-AxisMarkerLen, iY, tx-1, iY, C4RGB(0x91, 0x91, 0x91));
|
2009-05-08 13:28:41 +00:00
|
|
|
sbuf.Format("%d", (int) iVal);
|
2011-10-03 14:30:18 +00:00
|
|
|
pDraw->TextOut(sbuf.getData(), rFont, 1.0f, cgo.Surface, tx-AxisMarkerLen, iY-rFont.GetLineHeight()/2, 0xff7f7f7f, ARight, false);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
// draw graph series(es)
|
|
|
|
int iSeries = 0;
|
|
|
|
while (const C4Graph *pSeries = pDisplayGraph->GetSeries(iSeries++))
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
int iThisMinTime = Max(iMinTime, pSeries->GetStartTime());
|
|
|
|
int iThisMaxTime = Min(iMaxTime, pSeries->GetEndTime());
|
|
|
|
bool fAnyVal = false;
|
|
|
|
for (iX = 0; iX<tw; ++iX)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
iTime = iMinTime + dt*iX/tw;
|
|
|
|
if (!Inside(iTime, iThisMinTime, iThisMaxTime)) continue;
|
|
|
|
int iY2 = int((-pSeries->GetValue(iTime) + iMinVal) * th / dv) + ty+th;
|
2011-10-03 14:30:18 +00:00
|
|
|
if (fAnyVal) pDraw->DrawLineDw(cgo.Surface, (float) (tx+iX-1), (float) iY, (float) (tx+iX), (float) iY2, pSeries->GetColorDw());
|
2009-05-08 13:28:41 +00:00
|
|
|
iY = iY2;
|
|
|
|
fAnyVal = true;
|
|
|
|
}
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
C4Chart::C4Chart(C4Rect &rcBounds) : Element(), pDisplayGraph(NULL), fOwnGraph(false)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
this->rcBounds = rcBounds;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
C4Chart::~C4Chart()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
if (fOwnGraph && pDisplayGraph) delete pDisplayGraph;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
// singleton
|
|
|
|
C4ChartDialog *C4ChartDialog::pChartDlg=NULL;
|
|
|
|
|
|
|
|
C4ChartDialog::C4ChartDialog() : Dialog(DialogWidth, DialogHeight, LoadResStr("IDS_NET_STATISTICS"), false), pChartTabular(NULL)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// register singleton
|
|
|
|
pChartDlg = this;
|
|
|
|
// add main chart switch component
|
|
|
|
C4GUI::ComponentAligner caAll(GetContainedClientRect(), 5,5);
|
|
|
|
pChartTabular = new C4GUI::Tabular(caAll.GetAll(), C4GUI::Tabular::tbTop);
|
|
|
|
AddElement(pChartTabular);
|
|
|
|
// add some graphs as subcomponents
|
|
|
|
AddChart(StdStrBuf("oc"));
|
|
|
|
AddChart(StdStrBuf("FPS"));
|
|
|
|
AddChart(StdStrBuf("NetIO"));
|
2009-06-05 15:19:46 +00:00
|
|
|
if (::Network.isEnabled())
|
2009-05-08 13:28:41 +00:00
|
|
|
AddChart(StdStrBuf("Pings"));
|
|
|
|
AddChart(StdStrBuf("Control"));
|
|
|
|
AddChart(StdStrBuf("APM"));
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4ChartDialog::AddChart(const StdStrBuf &rszName)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// get graph by name
|
2010-10-30 00:08:58 +00:00
|
|
|
if (!Game.pNetworkStatistics || !pChartTabular) return;
|
2009-05-08 13:28:41 +00:00
|
|
|
bool fOwnGraph = false;
|
|
|
|
C4Graph *pGraph = Game.pNetworkStatistics->GetGraphByName(rszName, fOwnGraph);
|
|
|
|
if (!pGraph) return;
|
|
|
|
// add sheet for name
|
|
|
|
C4GUI::Tabular::Sheet *pSheet = pChartTabular->AddSheet(rszName.getData());
|
|
|
|
if (!pSheet) { if (fOwnGraph) delete pGraph; return; }
|
|
|
|
// add chart to sheet
|
|
|
|
C4Chart *pNewChart = new C4Chart(pSheet->GetClientRect());
|
|
|
|
pNewChart->SetGraph(pGraph, fOwnGraph);
|
|
|
|
pSheet->AddElement(pNewChart);
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4ChartDialog::Toggle()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// close if open
|
|
|
|
if (pChartDlg) { pChartDlg->Close(false); return; }
|
|
|
|
// otherwise, open
|
|
|
|
C4ChartDialog *pDlg = new C4ChartDialog();
|
2009-06-05 16:53:56 +00:00
|
|
|
if (!::pGUI->ShowRemoveDlg(pDlg)) if (pChartDlg) delete pChartDlg;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|