Refactor status drawing

This commit is contained in:
Michael Theall 2020-04-22 17:15:23 -05:00
parent fdcadc2997
commit 8aaf564138
7 changed files with 190 additions and 191 deletions

View File

@ -28,6 +28,7 @@
#include <chrono>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
class FtpServer;
@ -46,6 +47,9 @@ public:
/// \param port_ Port to listen on
static UniqueFtpServer create (std::uint16_t port_);
/// \brief Get free space
static std::string getFreeSpace ();
/// \brief Update free space
static void updateFreeSpace ();

View File

@ -21,6 +21,7 @@
#include "platform.h"
#include "fs.h"
#include "ftpServer.h"
#include "log.h"
#include "imgui_citro3d.h"
@ -250,7 +251,7 @@ void drawStatus ()
// calculate battery icon position
auto const p1 = ImVec2 (screenWidth - batteryWidth, 0.0f);
auto const p2 = ImVec2 (screenWidth, batteryHeight);
auto const p2 = ImVec2 (p1.x + batteryWidth, p1.y + batteryHeight);
// calculate battery icon uv coords
auto const uv1 = ImVec2 (battery->left, battery->top);
@ -269,8 +270,8 @@ void drawStatus ()
auto const wifiHeight = wifi->height;
// calculate wifi icon position
auto const p3 = ImVec2 (p1.x - wifiWidth - 2.0f, 0.0f);
auto const p4 = ImVec2 (p1.x - 2.0f, wifiHeight);
auto const p3 = ImVec2 (p1.x - wifiWidth - style.FramePadding.x, 0.0f);
auto const p4 = ImVec2 (p3.x + wifiWidth, p3.y + wifiHeight);
// calculate wifi icon uv coords
auto const uv3 = ImVec2 (wifi->left, wifi->top);
@ -279,36 +280,22 @@ void drawStatus ()
// draw wifi icon
ImGui::GetForegroundDrawList ()->AddImage (
&s_gfxTexture, p3, p4, uv3, uv4, ImGui::GetColorU32 (ImGuiCol_Text));
#endif
// draw current timestamp
char timeBuffer[16];
auto const now = std::time (nullptr);
std::strftime (timeBuffer, sizeof (timeBuffer), "%H:%M:%S", std::localtime (&now));
#ifdef CLASSIC
static std::string statusString;
// draw free space
char buffer[64];
auto const freeSpace = FtpServer::getFreeSpace ();
std::string newStatusString (256, '\0');
newStatusString.resize (std::sprintf (&newStatusString[0],
"\x1b[0;0H\x1b[32;1m%s \x1b[36;1m%s%s \x1b[37;1m%s\x1b[K",
STATUS_STRING,
s_addr ? inet_ntoa (in_addr{s_addr}) : "Waiting",
s_addr ? ":5000" : "",
timeBuffer));
std::snprintf (
buffer, sizeof (buffer), "%s %s", timeBuffer, freeSpace.empty () ? "" : freeSpace.c_str ());
if (newStatusString != statusString)
{
statusString = std::move (newStatusString);
consoleSelect (&g_statusConsole);
std::fputs (statusString.c_str (), stdout);
std::fflush (stdout);
}
#else
ImGui::GetForegroundDrawList ()->AddText (ImVec2 (p3.x - 65.0f, style.FramePadding.y),
ImGui::GetColorU32 (ImGuiCol_Text),
timeBuffer);
auto const size = ImGui::CalcTextSize (buffer);
auto const p5 = ImVec2 (p3.x - size.x - style.FramePadding.x, style.FramePadding.y);
ImGui::GetForegroundDrawList ()->AddText (p5, ImGui::GetColorU32 (ImGuiCol_Text), buffer);
#endif
}
}
@ -428,7 +415,6 @@ void platform::render ()
drawStatus ();
#ifdef CLASSIC
drawLog ();
gfxFlushBuffers ();
gspWaitForVBlank ();
gfxSwapBuffers ();

View File

@ -32,6 +32,7 @@
#endif
#include <arpa/inet.h>
#include <sys/statvfs.h>
#include <unistd.h>
#include <chrono>
@ -90,6 +91,32 @@ void FtpServer::draw ()
#endif
#ifdef CLASSIC
{
char port[7];
#ifndef NDS
auto lock = std::scoped_lock (m_lock);
#endif
if (m_socket)
std::sprintf (port, ":%u", m_socket->sockName ().port ());
consoleSelect (&g_statusConsole);
std::printf ("\x1b[0;0H\x1b[32;1m%s \x1b[36;1m%s%s",
STATUS_STRING,
m_socket ? m_socket->sockName ().name () : "Waiting on WiFi",
m_socket ? port : "");
#ifndef NDS
char timeBuffer[16];
auto const now = std::time (nullptr);
std::strftime (timeBuffer, sizeof (timeBuffer), "%H:%M:%S", std::localtime (&now));
std::printf (" \x1b[37;1m%s", timeBuffer);
#endif
std::fputs ("\x1b[K", stdout);
std::fflush (stdout);
}
{
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
@ -115,9 +142,11 @@ void FtpServer::draw ()
session->draw ();
if (&session != &m_sessions.back ())
std::fputc ('\n', stdout);
std::fflush (stdout);
}
std::fflush (stdout);
}
drawLog ();
#else
auto const &io = ImGui::GetIO ();
auto const width = io.DisplaySize.x;
@ -130,38 +159,29 @@ void FtpServer::draw ()
#else
ImGui::SetNextWindowSize (ImVec2 (width, height));
#endif
ImGui::Begin (STATUS_STRING,
nullptr,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
{
auto const lock = std::scoped_lock (s_lock);
if (!s_freeSpace.empty ())
char title[64];
{
ImGui::SameLine ();
ImGui::TextUnformatted (s_freeSpace.c_str ());
auto const serverLock = std::scoped_lock (m_lock);
std::snprintf (title,
sizeof (title),
STATUS_STRING " %s###ftpd",
m_socket ? m_name.c_str () : "Waiting for WiFi...");
}
ImGui::Begin (title,
nullptr,
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize);
}
{
ImGui::SameLine ();
auto const lock = std::scoped_lock (m_lock);
if (m_socket)
ImGui::TextUnformatted (m_name.c_str ());
else
ImGui::TextUnformatted ("Waiting for network...");
}
ImGui::Separator ();
#ifdef _3DS
// Fill rest of top screen window
ImGui::BeginChild ("Logs", ImVec2 (0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
#else
#ifndef _3DS
ImGui::BeginChild ("Logs", ImVec2 (0, 200), false, ImGuiWindowFlags_HorizontalScrollbar);
#endif
drawLog ();
#ifndef _3DS
ImGui::EndChild ();
#endif
#ifdef _3DS
ImGui::End ();
@ -192,19 +212,31 @@ UniqueFtpServer FtpServer::create (std::uint16_t const port_)
return UniqueFtpServer (new FtpServer (port_));
}
std::string FtpServer::getFreeSpace ()
{
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
#endif
return s_freeSpace;
}
void FtpServer::updateFreeSpace ()
{
#if defined(_3DS) || defined(__SWITCH__)
struct statvfs st;
#if defined(NDS) || defined(_3DS) || defined(__SWITCH__)
if (::statvfs ("sdmc:/", &st) != 0)
#else
if (::statvfs ("/", &st) != 0)
#endif
return;
auto freeSpace = fs::printSize (static_cast<std::uint64_t> (st.f_bsize) * st.f_bfree);
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);
#endif
if (freeSpace != s_freeSpace)
s_freeSpace = std::move (freeSpace);
#endif
}
std::time_t FtpServer::startTime ()

View File

@ -20,6 +20,8 @@
#include "platform.h"
#include "ftpServer.h"
#include "imgui.h"
#include <glad/glad.h>
@ -188,6 +190,19 @@ bool platform::loop ()
void platform::render ()
{
auto const freeSpace = FtpServer::getFreeSpace ();
if (!freeSpace.empty ())
{
auto const &io = ImGui::GetIO ();
auto const &style = ImGui::GetStyle ();
auto const size = ImGui::CalcTextSize (freeSpace.c_str ());
auto const x = io.DisplaySize.x - size.x - style.FramePadding.x;
ImGui::GetForegroundDrawList ()->AddText (ImVec2 (x, style.FramePadding.y),
ImGui::GetColorU32 (ImGuiCol_Text),
freeSpace.c_str ());
}
ImGui::Render ();
glClearColor (0.45f, 0.55f, 0.60f, 1.00f);

View File

@ -209,7 +209,6 @@ void addLog (LogLevel const level_, char const *const fmt_, va_list ap_)
static char buffer[1024];
std::vsnprintf (buffer, sizeof (buffer), fmt_, ap_);
buffer[sizeof (buffer) - 1] = '\0';
#ifndef NDS
auto const lock = std::scoped_lock (s_lock);

View File

@ -108,13 +108,6 @@ bool platform::loop ()
void platform::render ()
{
swiWaitForVBlank ();
consoleSelect (&g_statusConsole);
std::printf ("\n%s %s%s",
STATUS_STRING,
s_addr.s_addr ? inet_ntoa (s_addr) : "Waiting on WiFi",
s_addr.s_addr ? ":5000" : "");
std::fflush (stdout);
drawLog ();
}
void platform::exit ()

View File

@ -21,6 +21,7 @@
#include "platform.h"
#include "fs.h"
#include "ftpServer.h"
#include "log.h"
#include "imgui_deko3d.h"
@ -396,139 +397,109 @@ void deko3dExit ()
}
#endif
/// \brief Draw time status
void drawTimeStatus ()
{
#ifndef CLASSIC
auto const &io = ImGui::GetIO ();
auto const &style = ImGui::GetStyle ();
#endif
// draw current timestamp
char timeBuffer[64];
auto const now = std::time (nullptr);
std::strftime (timeBuffer, sizeof (timeBuffer), "%H:%M:%S", std::localtime (&now));
#ifdef CLASSIC
static std::string statusString;
std::string newStatusString (256, '\0');
newStatusString.resize (std::sprintf (&newStatusString[0],
"\x1b[0;0H\x1b[32;1m%s \x1b[36;1m%s%s \x1b[37;1m%s\x1b[K",
STATUS_STRING,
s_addr ? inet_ntoa (in_addr{s_addr}) : "Waiting",
s_addr ? ":5000" : "",
timeBuffer));
if (newStatusString != statusString)
{
statusString = std::move (newStatusString);
consoleSelect (&g_statusConsole);
std::fputs (statusString.c_str (), stdout);
std::fflush (stdout);
}
#else
ImGui::GetForegroundDrawList ()->AddText (
ImVec2 (io.DisplaySize.x - 240.0f, style.FramePadding.y),
ImGui::GetColorU32 (ImGuiCol_Text),
timeBuffer);
#endif
}
/// \brief Draw network status
void drawNetworkStatus ()
{
#ifndef CLASSIC
TextureIndex netIcon = AIRPLANE_ICON;
NifmInternetConnectionType type;
std::uint32_t wifiStrength;
NifmInternetConnectionStatus status;
if (R_SUCCEEDED (nifmGetInternetConnectionStatus (&type, &wifiStrength, &status)))
{
if (type == NifmInternetConnectionType_Ethernet)
{
if (status == NifmInternetConnectionStatus_Connected)
netIcon = ETH_ICON;
else
netIcon = ETH_NONE_ICON;
}
else
{
if (wifiStrength >= 3)
netIcon = WIFI3_ICON;
else if (wifiStrength == 2)
netIcon = WIFI3_ICON;
else if (wifiStrength == 1)
netIcon = WIFI3_ICON;
else if (wifiStrength == 0)
netIcon = WIFI_NONE_ICON;
}
}
auto const &io = ImGui::GetIO ();
auto const &style = ImGui::GetStyle ();
auto const x1 = io.DisplaySize.x - ICON_WIDTH - 100.0f;
auto const x2 = x1 + ICON_WIDTH;
auto const y1 = style.FramePadding.y;
auto const y2 = y1 + ICON_HEIGHT;
ImGui::GetForegroundDrawList ()->AddImage (
imgui::deko3d::makeTextureID (dkMakeTextureHandle (netIcon, 1)),
ImVec2 (x1, y1),
ImVec2 (x2, y2),
ImVec2 (0, 0),
ImVec2 (1, 1),
ImGui::GetColorU32 (ImGuiCol_Text));
#endif
}
/// \brief Draw power status
void drawPowerStatus ()
{
#ifndef CLASSIC
std::uint32_t batteryCharge = 0;
psmGetBatteryChargePercentage (&batteryCharge);
ChargerType charger = ChargerType_None;
psmGetChargerType (&charger);
TextureIndex powerIcon = BATTERY_ICON;
if (charger != ChargerType_None)
powerIcon = CHARGING_ICON;
auto const &io = ImGui::GetIO ();
auto const &style = ImGui::GetStyle ();
auto const x1 = io.DisplaySize.x - ICON_WIDTH - style.FramePadding.x;
auto const x2 = x1 + ICON_WIDTH;
auto const y1 = style.FramePadding.y;
auto const y2 = y1 + ICON_HEIGHT;
ImGui::GetForegroundDrawList ()->AddImage (
imgui::deko3d::makeTextureID (dkMakeTextureHandle (powerIcon, 1)),
ImVec2 (x1, y1),
ImVec2 (x2, y2),
ImVec2 (0, 0),
ImVec2 (1, 1),
ImGui::GetColorU32 (ImGuiCol_Text));
char buffer[16];
std::sprintf (buffer, "%3u%%", batteryCharge);
ImGui::GetForegroundDrawList ()->AddText (
ImVec2 (x1 - 70.0f, y1), ImGui::GetColorU32 (ImGuiCol_Text), buffer);
#endif
}
/// \brief Draw status
void drawStatus ()
{
drawTimeStatus ();
drawNetworkStatus ();
drawPowerStatus ();
#ifndef CLASSIC
auto const &io = ImGui::GetIO ();
auto const &style = ImGui::GetStyle ();
auto pos = ImVec2 (io.DisplaySize.x, style.FramePadding.y);
{
std::uint32_t batteryCharge = 0;
psmGetBatteryChargePercentage (&batteryCharge);
ChargerType charger = ChargerType_None;
psmGetChargerType (&charger);
TextureIndex powerIcon = BATTERY_ICON;
if (charger != ChargerType_None)
powerIcon = CHARGING_ICON;
// draw battery/charging icon
pos.x -= ICON_WIDTH + style.FramePadding.x;
ImGui::GetForegroundDrawList ()->AddImage (
imgui::deko3d::makeTextureID (dkMakeTextureHandle (powerIcon, 1)),
pos,
ImVec2 (pos.x + ICON_WIDTH, pos.y + ICON_HEIGHT),
ImVec2 (0, 0),
ImVec2 (1, 1),
ImGui::GetColorU32 (ImGuiCol_Text));
char buffer[16];
std::sprintf (buffer, "%u%%", batteryCharge);
// draw battery percentage
auto const fullWidth = ImGui::CalcTextSize ("100%").x;
auto const partWidth = ImGui::CalcTextSize (buffer).x;
auto const diffWidth = fullWidth - partWidth;
// janky right-align
pos.x -= partWidth + style.FramePadding.x;
ImGui::GetForegroundDrawList ()->AddText (pos, ImGui::GetColorU32 (ImGuiCol_Text), buffer);
pos.x -= diffWidth;
}
{
TextureIndex netIcon = AIRPLANE_ICON;
NifmInternetConnectionType type;
std::uint32_t wifiStrength;
NifmInternetConnectionStatus status;
if (R_SUCCEEDED (nifmGetInternetConnectionStatus (&type, &wifiStrength, &status)))
{
if (type == NifmInternetConnectionType_Ethernet)
{
if (status == NifmInternetConnectionStatus_Connected)
netIcon = ETH_ICON;
else
netIcon = ETH_NONE_ICON;
}
else
{
if (wifiStrength >= 3)
netIcon = WIFI3_ICON;
else if (wifiStrength == 2)
netIcon = WIFI3_ICON;
else if (wifiStrength == 1)
netIcon = WIFI3_ICON;
else if (wifiStrength == 0)
netIcon = WIFI_NONE_ICON;
}
}
// draw network icon
pos.x -= ICON_WIDTH + style.FramePadding.x;
ImGui::GetForegroundDrawList ()->AddImage (
imgui::deko3d::makeTextureID (dkMakeTextureHandle (netIcon, 1)),
pos,
ImVec2 (pos.x + ICON_WIDTH, pos.y + ICON_HEIGHT),
ImVec2 (0, 0),
ImVec2 (1, 1),
ImGui::GetColorU32 (ImGuiCol_Text));
}
{
// draw free space
auto const freeSpace = FtpServer::getFreeSpace ();
pos.x -= ImGui::CalcTextSize (freeSpace.c_str ()).x + style.FramePadding.x;
ImGui::GetForegroundDrawList ()->AddText (
pos, ImGui::GetColorU32 (ImGuiCol_Text), freeSpace.c_str ());
}
{
// get current timestamp
char timeBuffer[16];
auto const now = std::time (nullptr);
std::strftime (timeBuffer, sizeof (timeBuffer), "%H:%M:%S", std::localtime (&now));
// draw time (centered)
pos.x = (io.DisplaySize.x - ImGui::CalcTextSize (timeBuffer).x) / 2.0f;
ImGui::GetForegroundDrawList ()->AddText (
pos, ImGui::GetColorU32 (ImGuiCol_Text), timeBuffer);
}
#endif
}
}
@ -621,7 +592,6 @@ bool platform::loop ()
void platform::render ()
{
#ifdef CLASSIC
drawLog ();
consoleUpdate (&g_statusConsole);
consoleUpdate (&g_logConsole);
consoleUpdate (&g_sessionConsole);