mirror of
https://github.com/scorpion-26/gBar.git
synced 2024-11-21 18:52:49 +00:00
Add a Network Widget
This new widget visualizes the up and download speeds for a specified network adapter. It is on by default, but can be disabled.
This commit is contained in:
parent
c901b59ab4
commit
3134c82245
12 changed files with 446 additions and 6 deletions
|
@ -141,6 +141,60 @@
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
.network-data-text {
|
||||
color: #50fa7b;
|
||||
margin-right: 6px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.network-up-under {
|
||||
color: #44475a;
|
||||
}
|
||||
|
||||
.network-up-low {
|
||||
color: #50fa7b;
|
||||
}
|
||||
|
||||
.network-up-mid-low {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
.network-up-mid-high {
|
||||
color: #ffb86c;
|
||||
}
|
||||
|
||||
.network-up-high {
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
.network-up-over {
|
||||
color: #ff5555;
|
||||
}
|
||||
|
||||
.network-down-under {
|
||||
color: #44475a;
|
||||
}
|
||||
|
||||
.network-down-low {
|
||||
color: #50fa7b;
|
||||
}
|
||||
|
||||
.network-down-mid-low {
|
||||
color: #f1fa8c;
|
||||
}
|
||||
|
||||
.network-down-mid-high {
|
||||
color: #ffb86c;
|
||||
}
|
||||
|
||||
.network-down-high {
|
||||
color: #bd93f9;
|
||||
}
|
||||
|
||||
.network-down-over {
|
||||
color: #ff5555;
|
||||
}
|
||||
|
||||
.ws-dead {
|
||||
color: #44475a;
|
||||
font-size: 16px;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["style.scss"],"names":[],"mappings":"AAmBA;EACI;EACA;;;AASJ;EACI,kBA7BC;EA8BD;;;AAGJ;EACI;EACA;;;AAGJ;EACI,WAxBO;;;AA2BX;EACI;EAEA;EAEA,OA5CO;;;AA8CX;EACI;EAGA,OAlDO;;;AAoDX;EACI;EAGA,OAxDO;;;AA2DX;EACI;EAGA,OAzDE;;;AA+DN;EACI;;;AAGJ;EACI;EACA,OAxEK;EAyEL;;;AAGJ;EACI,WApEO;EAqEP,OAvEK;EAwEL;;;AAEJ;EACI;EACA,OA5EK;EA6EL;;;AAEJ;EACI;EACA,OAjFK;EAkFL;;;AAEJ;EACI;EACA,OAtFK;EAuFL;;;AAGJ;EACI,OAhGK;EAiGL,kBAvGO;EAwGP,WA3FO;;;AA6FX;EACI,OArGK;EAsGL;EACA,WAhGO;;;AAmGX;EACI,OA7GK;EA8GL,kBAlHO;;;AAoHX;EACI,OAjHK;EAkHL;EACA,WA1GO;;;AA6GX;EACI,OAnHK;EAoHL,kBA5HO;;;AA8HX;EACI,OAvHK;EAwHL;EACA,WApHO;;;AAuHX;EACI,OAnIG;EAoIH,kBAtIO;;;AAwIX;EACI,OAvIG;EAwIH;EACA,WA9HO;;;AAiIX;EACI,OA5II;EA6IJ,kBAhJO;EAiJP,WApIO;;;AAsIX;EACI,OAjJI;EAkJJ;EACA,WAzIO;;;AA4IX;EACI,OArJG;EAsJH,kBA3JO;EA4JP,WA/IO;;;AAiJX;EACI,OA1JG;EA2JH;EACA,WApJO;;;AAuJX;EACI,OArKO;EAsKP,WAzJO;;;AA2JX;EACI,OAxKO;EAyKP,WA7JO;;;AA+JX;EACI,OA3KG;EA4KH,WAjKO;;;AAmKX;EACI,OAzKK;EA0KL,WArKO;;;AAuKX;EACI,OAlLI;EAmLJ,WAzKO;;;AA6KX;EACI;IACI;;EAEJ;IACI;;;AAGR;EACI;IACI;;EAEJ;IACI;;;AAIR;EACI;IACI,OArMC;;EAuML;IACI,OA7MA;;;AAgNR;EACI;IACI,OAlNA;;EAoNJ;IACI,OAhNC;;;AAoNT;EACI,kBA/NC;EAgOD;;;AAEJ;EACI;EACA;EACA;EACA;EACA,OA1NK;;;AA4NT;EACI;EACA;;;AAEJ;EAgBI;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;;AAxBA;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI,OAlPF;;;AAgQN;EACI,OAjQE;EAkQF,kBAzQO;EA0QP;EACH;EACA;;;AAED;EAaI,OAnRK;EAoRL,kBA5RO;EA6RP;EACA;EACH;EACG;;AAjBA;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;;AAWR;EACI;EACA;EACH;EACG,kBAxSO;EAySP;EACH;EACA;;;AAGD;EAEC;EACG;EACH;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACG;EACH;EACG;EACH,kBA1TQ","file":"style.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["style.scss"],"names":[],"mappings":"AAmBA;EACI;EACA;;;AASJ;EACI,kBA7BC;EA8BD;;;AAGJ;EACI;EACA;;;AAGJ;EACI,WAxBO;;;AA2BX;EACI;EAEA;EAEA,OA5CO;;;AA8CX;EACI;EAGA,OAlDO;;;AAoDX;EACI;EAGA,OAxDO;;;AA2DX;EACI;EAGA,OAzDE;;;AA+DN;EACI;;;AAGJ;EACI;EACA,OAxEK;EAyEL;;;AAGJ;EACI,WApEO;EAqEP,OAvEK;EAwEL;;;AAEJ;EACI;EACA,OA5EK;EA6EL;;;AAEJ;EACI;EACA,OAjFK;EAkFL;;;AAEJ;EACI;EACA,OAtFK;EAuFL;;;AAGJ;EACI,OAhGK;EAiGL,kBAvGO;EAwGP,WA3FO;;;AA6FX;EACI,OArGK;EAsGL;EACA,WAhGO;;;AAmGX;EACI,OA7GK;EA8GL,kBAlHO;;;AAoHX;EACI,OAjHK;EAkHL;EACA,WA1GO;;;AA6GX;EACI,OAnHK;EAoHL,kBA5HO;;;AA8HX;EACI,OAvHK;EAwHL;EACA,WApHO;;;AAuHX;EACI,OAnIG;EAoIH,kBAtIO;;;AAwIX;EACI,OAvIG;EAwIH;EACA,WA9HO;;;AAiIX;EACI,OA5II;EA6IJ,kBAhJO;EAiJP,WApIO;;;AAsIX;EACI,OAjJI;EAkJJ;EACA,WAzIO;;;AA4IX;EACI,OArJG;EAsJH,kBA3JO;EA4JP,WA/IO;;;AAiJX;EACI,OA1JG;EA2JH;EACA,WApJO;;;AAuJX;EACI,OAlKI;EAmKJ;EACA,WA1JO;;;AA8JX;EACI,OA5KO;;;AA+KX;EACI,OA7KI;;;AAgLR;EACI,OA5KK;;;AA+KT;EACI,OApLK;;;AAuLT;EACI,OAtLK;;;AAyLT;EACI,OAzLE;;;AA6LN;EACI,OArMO;;;AAwMX;EACI,OAtMI;;;AAyMR;EACI,OArMK;;;AAwMT;EACI,OA7MK;;;AAgNT;EACI,OA/MK;;;AAkNT;EACI,OAlNE;;;AAqNN;EACI,OA7NO;EA8NP,WAjNO;;;AAmNX;EACI,OAhOO;EAiOP,WArNO;;;AAuNX;EACI,OAnOG;EAoOH,WAzNO;;;AA2NX;EACI,OAjOK;EAkOL,WA7NO;;;AA+NX;EACI,OA1OI;EA2OJ,WAjOO;;;AAqOX;EACI;IACI;;EAEJ;IACI;;;AAGR;EACI;IACI;;EAEJ;IACI;;;AAIR;EACI;IACI,OA7PC;;EA+PL;IACI,OArQA;;;AAwQR;EACI;IACI,OA1QA;;EA4QJ;IACI,OAxQC;;;AA4QT;EACI,kBAvRC;EAwRD;;;AAEJ;EACI;EACA;EACA;EACA;EACA,OAlRK;;;AAoRT;EACI;EACA;;;AAEJ;EAgBI;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;;AAxBA;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;AAEJ;EACI,OA1SF;;;AAwTN;EACI,OAzTE;EA0TF,kBAjUO;EAkUP;EACH;EACA;;;AAED;EAaI,OA3UK;EA4UL,kBApVO;EAqVP;EACA;EACH;EACG;;AAjBA;EACI;EACA;EACA;EACA;;AAEJ;EACI;EACA;EACA;EACA;;;AAWR;EACI;EACA;EACH;EACG,kBAhWO;EAiWP;EACH;EACA;;;AAGD;EAEC;EACG;EACH;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACG;EACH;EACG;EACH,kBAlXQ","file":"style.css"}
|
|
@ -166,6 +166,62 @@ $textsize: 16px;
|
|||
font-size: $textsize;
|
||||
}
|
||||
|
||||
.network-data-text {
|
||||
color: $green;
|
||||
margin-right: 6px;
|
||||
font-size: $textsize;
|
||||
}
|
||||
|
||||
// <= 0% (Below MinUploadBytes)
|
||||
.network-up-under {
|
||||
color: $inactive;
|
||||
}
|
||||
// <= 25%
|
||||
.network-up-low {
|
||||
color: $green;
|
||||
}
|
||||
// <= 50%
|
||||
.network-up-mid-low {
|
||||
color: $yellow;
|
||||
}
|
||||
// <= 75%
|
||||
.network-up-mid-high {
|
||||
color: $orange;
|
||||
}
|
||||
// <= 100%
|
||||
.network-up-high {
|
||||
color: $purple;
|
||||
}
|
||||
// > 100% (Above MaxUploadBytes)
|
||||
.network-up-over {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
// <= 0% (Below MinDownloadBytes)
|
||||
.network-down-under {
|
||||
color: $inactive;
|
||||
}
|
||||
// <= 25%
|
||||
.network-down-low {
|
||||
color: $green;
|
||||
}
|
||||
// <= 50%
|
||||
.network-down-mid-low {
|
||||
color: $yellow;
|
||||
}
|
||||
// <= 75%
|
||||
.network-down-mid-high {
|
||||
color: $orange;
|
||||
}
|
||||
// <= 100%
|
||||
.network-down-high {
|
||||
color: $purple;
|
||||
}
|
||||
// > 100% (Above MaxDownloadBytes)
|
||||
.network-down-over {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
.ws-dead {
|
||||
color: $inactive;
|
||||
font-size: $textsize;
|
||||
|
|
20
data/config
20
data/config
|
@ -1,4 +1,4 @@
|
|||
# Example configuration.
|
||||
# Example configuration.
|
||||
# Everything after '#' is ignored
|
||||
# Format of the variables:
|
||||
# [variable]: [value]
|
||||
|
@ -34,3 +34,21 @@ CenterTime: true
|
|||
|
||||
# Sets the audio slider to be on reveal (Just like the sensors) when true. Only affects the bar.
|
||||
AudioRevealer: false
|
||||
|
||||
# The network adapter to use. You can query /sys/class/net for all possible values
|
||||
NetworkAdapter: eno1
|
||||
|
||||
# Disables the network widget when set to false
|
||||
NetworkWidget: true
|
||||
|
||||
# These set the range for the network widget. The widget changes colors at six intervals:
|
||||
# - Below Min...Bytes ("under")
|
||||
# - Between ]0%;25%]. 0% = Min...Bytes; 100% = Max...Bytes ("low")
|
||||
# - Between ]25%;50%]. 0% = Min...Bytes; 100% = Max...Bytes ("mid-low")
|
||||
# - Between ]50%;75%]. 0% = Min...Bytes; 100% = Max...Bytes ("mid-high")
|
||||
# - Between ]75%;100%]. 0% = Min...Bytes; 100% = Max...Bytes ("high")
|
||||
# - Above Max...Bytes ("over")
|
||||
MinDownloadBytes: 0
|
||||
MaxDownloadBytes: 10485760 # 10 * 1024 * 1024 = 10 MiB
|
||||
MinUploadBytes: 0
|
||||
MaxUploadBytes: 5242880 # 5 * 1024 * 1024 = 5 MiB
|
||||
|
|
57
src/Bar.cpp
57
src/Bar.cpp
|
@ -155,6 +155,23 @@ namespace Bar
|
|||
return TimerResult::Ok;
|
||||
}
|
||||
|
||||
Text* networkText;
|
||||
TimerResult UpdateNetwork(NetworkSensor& sensor)
|
||||
{
|
||||
double bpsUp = System::GetNetworkBpsUpload(updateTime / 1000.0);
|
||||
double bpsDown = System::GetNetworkBpsDownload(updateTime / 1000.0);
|
||||
|
||||
std::string upload = Utils::StorageUnitDynamic(bpsUp, "%0.1f%s");
|
||||
std::string download = Utils::StorageUnitDynamic(bpsDown, "%0.1f%s");
|
||||
|
||||
networkText->SetText(Config::Get().networkAdapter + ": " + upload + " Up/" + download + " Down");
|
||||
|
||||
sensor.SetUp(bpsUp);
|
||||
sensor.SetDown(bpsDown);
|
||||
|
||||
return TimerResult::Ok;
|
||||
}
|
||||
|
||||
TimerResult UpdateTime(Text& text)
|
||||
{
|
||||
text.SetText(System::GetTime());
|
||||
|
@ -311,6 +328,44 @@ namespace Bar
|
|||
}
|
||||
#endif
|
||||
|
||||
void WidgetNetwork(Widget& parent)
|
||||
{
|
||||
auto eventBox = Widget::Create<EventBox>();
|
||||
{
|
||||
auto box = Widget::Create<Box>();
|
||||
box->SetSpacing({0, false});
|
||||
box->SetHorizontalTransform({-1, true, Alignment::Right});
|
||||
{
|
||||
auto revealer = Widget::Create<Revealer>();
|
||||
revealer->SetTransition({TransitionType::SlideLeft, 500});
|
||||
// Add event to eventbox for the revealer to open
|
||||
eventBox->SetEventFn(
|
||||
[textRevealer = revealer.get()](EventBox&, bool hovered)
|
||||
{
|
||||
textRevealer->SetRevealed(hovered);
|
||||
});
|
||||
{
|
||||
auto text = Widget::Create<Text>();
|
||||
text->SetClass("network-data-text");
|
||||
DynCtx::networkText = text.get();
|
||||
revealer->AddChild(std::move(text));
|
||||
}
|
||||
|
||||
auto sensor = Widget::Create<NetworkSensor>();
|
||||
sensor->SetLimitUp({(double)Config::Get().minUploadBytes, (double)Config::Get().maxUploadBytes});
|
||||
sensor->SetLimitDown({(double)Config::Get().minDownloadBytes, (double)Config::Get().maxDownloadBytes});
|
||||
sensor->AddTimer<NetworkSensor>(DynCtx::UpdateNetwork, DynCtx::updateTime);
|
||||
sensor->SetHorizontalTransform({24, true, Alignment::Fill});
|
||||
|
||||
box->AddChild(std::move(revealer));
|
||||
box->AddChild(std::move(sensor));
|
||||
}
|
||||
eventBox->AddChild(std::move(box));
|
||||
}
|
||||
|
||||
parent.AddChild(std::move(eventBox));
|
||||
}
|
||||
|
||||
void WidgetSensors(Widget& parent)
|
||||
{
|
||||
WidgetSensor(parent, DynCtx::UpdateDisk, "disk-util-progress", "disk-data-text", DynCtx::diskText);
|
||||
|
@ -476,6 +531,8 @@ namespace Bar
|
|||
if (RuntimeConfig::Get().hasBlueZ)
|
||||
WidgetBluetooth(*right);
|
||||
#endif
|
||||
if (Config::Get().networkWidget)
|
||||
WidgetNetwork(*right);
|
||||
|
||||
WidgetSensors(*right);
|
||||
|
||||
|
|
27
src/Common.h
27
src/Common.h
|
@ -60,6 +60,33 @@ namespace Utils
|
|||
snprintf(buf, sizeof(buf), fmt, x);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Format must be something like %0.1f %s
|
||||
inline std::string StorageUnitDynamic(double bytes, const char* fmt)
|
||||
{
|
||||
constexpr double KiB = 1024;
|
||||
constexpr double MiB = 1024 * KiB;
|
||||
constexpr double GiB = 1024 * MiB;
|
||||
char buf[128];
|
||||
if (bytes >= GiB)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), fmt, bytes * (1 / GiB), "GiB");
|
||||
return buf;
|
||||
}
|
||||
if (bytes >= MiB)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), fmt, bytes * (1 / MiB), "MiB");
|
||||
return buf;
|
||||
}
|
||||
if (bytes >= KiB)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), fmt, bytes * (1 / KiB), "KiB");
|
||||
return buf;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), fmt, bytes, "B");
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
struct Process
|
||||
|
|
|
@ -119,6 +119,7 @@ void Config::Load()
|
|||
|
||||
bool foundProperty = false;
|
||||
AddConfigVar("CPUThermalZone", config.cpuThermalZone, lineView, foundProperty);
|
||||
AddConfigVar("NetworkAdapter", config.networkAdapter, lineView, foundProperty);
|
||||
AddConfigVar("SuspendCommand", config.suspendCommand, lineView, foundProperty);
|
||||
AddConfigVar("LockCommand", config.lockCommand, lineView, foundProperty);
|
||||
AddConfigVar("ExitCommand", config.exitCommand, lineView, foundProperty);
|
||||
|
@ -132,6 +133,12 @@ void Config::Load()
|
|||
|
||||
AddConfigVar("CenterTime", config.centerTime, lineView, foundProperty);
|
||||
AddConfigVar("AudioRevealer", config.audioRevealer, lineView, foundProperty);
|
||||
AddConfigVar("NetworkWidget", config.networkWidget, lineView, foundProperty);
|
||||
|
||||
AddConfigVar("MinUploadBytes", config.minUploadBytes, lineView, foundProperty);
|
||||
AddConfigVar("MaxUploadBytes", config.maxUploadBytes, lineView, foundProperty);
|
||||
AddConfigVar("MinDownloadBytes", config.minDownloadBytes, lineView, foundProperty);
|
||||
AddConfigVar("MaxDownloadBytes", config.maxDownloadBytes, lineView, foundProperty);
|
||||
|
||||
if (foundProperty == false)
|
||||
{
|
||||
|
|
16
src/Config.h
16
src/Config.h
|
@ -2,19 +2,27 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Config
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
std::string cpuThermalZone = ""; // idk, no standard way of doing this.
|
||||
std::string cpuThermalZone = ""; // idk, no standard way of doing this.
|
||||
std::string networkAdapter = "eno1"; // Is this standard?
|
||||
std::string suspendCommand = "systemctl suspend";
|
||||
std::string lockCommand = ""; // idk, no standard way of doing this.
|
||||
std::string exitCommand = ""; // idk, no standard way of doing this.
|
||||
std::string lockCommand = ""; // idk, no standard way of doing this.
|
||||
std::string exitCommand = ""; // idk, no standard way of doing this.
|
||||
std::string batteryFolder = ""; // this can be BAT0, BAT1, etc. Usually in /sys/class/power_supply
|
||||
std::vector<std::string> workspaceSymbols = std::vector<std::string>(9, "");
|
||||
std::string defaultWorkspaceSymbol = "";
|
||||
|
||||
bool centerTime = true;
|
||||
bool audioRevealer = false;
|
||||
bool networkWidget = true;
|
||||
|
||||
// Controls for color progression of the network widget
|
||||
uint32_t minUploadBytes = 0; // Bottom limit of the network widgets upload. Everything below it is considered "under"
|
||||
uint32_t maxUploadBytes = 4 * 1024 * 1024; // 4 MiB Top limit of the network widgets upload. Everything above it is considered "over"
|
||||
uint32_t minDownloadBytes = 0; // Bottom limit of the network widgets download. Everything above it is considered "under"
|
||||
uint32_t maxDownloadBytes = 10 * 1024 * 1024; // 10 MiB Top limit of the network widgets download. Everything above it is considered "over"
|
||||
|
||||
static void Load();
|
||||
static const Config& Get();
|
||||
|
|
|
@ -463,6 +463,47 @@ namespace System
|
|||
}
|
||||
#endif
|
||||
|
||||
double GetNetworkBpsCommon(double dt, uint64_t& prevBytes, const std::string& deviceFile)
|
||||
{
|
||||
std::ifstream bytes(deviceFile);
|
||||
ASSERT(bytes.is_open(), "Couldn't open " << deviceFile);
|
||||
std::string bytesStr;
|
||||
std::getline(bytes, bytesStr);
|
||||
|
||||
uint64_t curBytes = std::stoull(bytesStr);
|
||||
|
||||
if (prevBytes == UINT64_MAX)
|
||||
{
|
||||
prevBytes = curBytes;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64_t diffBytes = curBytes - prevBytes;
|
||||
prevBytes = curBytes;
|
||||
// Is double precision a problem here?
|
||||
return diffBytes / dt;
|
||||
}
|
||||
}
|
||||
|
||||
double GetNetworkBpsUpload(double dt)
|
||||
{
|
||||
// Better safe than sorry. Isn't 32bit max only a few GB?
|
||||
static uint64_t prevUploadBytes = UINT64_MAX;
|
||||
// Apparently /sys/class/net/.../statistics/[t/r]x_bytes is valid for all net devices under Linux
|
||||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net-statistics
|
||||
return GetNetworkBpsCommon(dt, prevUploadBytes, "/sys/class/net/" + Config::Get().networkAdapter + "/statistics/tx_bytes");
|
||||
}
|
||||
|
||||
double GetNetworkBpsDownload(double dt)
|
||||
{
|
||||
// Better safe than sorry. Isn't 32bit max only a few GB?
|
||||
static uint64_t prevDownloadBytes = UINT64_MAX;
|
||||
// Apparently /sys/class/net/.../statistics/[t/r]x_bytes is valid for all net devices under Linux
|
||||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net-statistics
|
||||
return GetNetworkBpsCommon(dt, prevDownloadBytes, "/sys/class/net/" + Config::Get().networkAdapter + "/statistics/rx_bytes");
|
||||
}
|
||||
|
||||
std::string GetTime()
|
||||
{
|
||||
time_t stdTime = time(NULL);
|
||||
|
|
|
@ -93,6 +93,11 @@ namespace System
|
|||
std::string GetWorkspaceSymbol(int index);
|
||||
#endif
|
||||
|
||||
// Bytes per second upload. dx is time since last call. Will always return 0 on first run
|
||||
double GetNetworkBpsUpload(double dt);
|
||||
// Bytes per second download. dx is time since last call. Will always return 0 on first run
|
||||
double GetNetworkBpsDownload(double dt);
|
||||
|
||||
std::string GetTime();
|
||||
|
||||
void Shutdown();
|
||||
|
|
141
src/Widget.cpp
141
src/Widget.cpp
|
@ -1,5 +1,6 @@
|
|||
#include "Widget.h"
|
||||
#include "Common.h"
|
||||
#include "CSS.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
@ -298,6 +299,146 @@ void Sensor::Draw(cairo_t* cr)
|
|||
gdk_rgba_free(fgCol);
|
||||
}
|
||||
|
||||
static std::string NetworkSensorPercentToCSS(double percent)
|
||||
{
|
||||
if (percent <= 0.)
|
||||
{
|
||||
return "under";
|
||||
}
|
||||
else if (percent <= 0.25)
|
||||
{
|
||||
return "low";
|
||||
}
|
||||
else if (percent <= 0.50)
|
||||
{
|
||||
return "mid-low";
|
||||
}
|
||||
else if (percent <= 0.75)
|
||||
{
|
||||
return "mid-high";
|
||||
}
|
||||
else if (percent <= 1.)
|
||||
{
|
||||
return "high";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "over";
|
||||
}
|
||||
}
|
||||
|
||||
static double NetworkSensorRateToPercent(double rate, Range range)
|
||||
{
|
||||
return (rate - range.min) / (range.max - range.min);
|
||||
}
|
||||
|
||||
void NetworkSensor::Create()
|
||||
{
|
||||
CairoArea::Create();
|
||||
|
||||
// Add virtual children for style context(I know, it is really gross)
|
||||
contextUp = Widget::Create<Box>();
|
||||
contextUp->SetSpacing({0, true});
|
||||
contextUp->SetClass("network-up-under");
|
||||
contextUp->SetHorizontalTransform({0, false, Alignment::Fill});
|
||||
contextUp->Create();
|
||||
|
||||
contextDown = Widget::Create<Box>();
|
||||
contextDown->SetSpacing({0, true});
|
||||
contextDown->SetClass("network-down-under");
|
||||
contextDown->SetHorizontalTransform({0, false, Alignment::Fill});
|
||||
contextDown->Create();
|
||||
}
|
||||
|
||||
void NetworkSensor::SetUp(double val)
|
||||
{
|
||||
if (!contextUp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
up = NetworkSensorRateToPercent(val, limitUp);
|
||||
|
||||
// Add css class
|
||||
std::string newClass = NetworkSensorPercentToCSS(up);
|
||||
contextUp->SetClass("network-up-" + newClass);
|
||||
|
||||
// Schedule redraw
|
||||
if (m_Widget)
|
||||
{
|
||||
gtk_widget_queue_draw(m_Widget);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSensor::SetDown(double val)
|
||||
{
|
||||
if (!contextDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
down = NetworkSensorRateToPercent(val, limitDown);
|
||||
|
||||
// Add css class
|
||||
std::string newClass = NetworkSensorPercentToCSS(down);
|
||||
contextDown->SetClass("network-down-" + newClass);
|
||||
|
||||
// Schedule redraw
|
||||
if (m_Widget)
|
||||
{
|
||||
gtk_widget_queue_draw(m_Widget);
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSensor::Draw(cairo_t* cr)
|
||||
{
|
||||
constexpr double epsilon = 1;
|
||||
|
||||
Quad q = GetQuad();
|
||||
auto virtToPx = [&](double virtPx)
|
||||
{
|
||||
return q.size * (virtPx / 24.f);
|
||||
};
|
||||
|
||||
GdkRGBA* colUp;
|
||||
GdkRGBA* colDown;
|
||||
gtk_style_context_get(gtk_widget_get_style_context(contextUp->Get()), GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_COLOR, &colUp, NULL);
|
||||
gtk_style_context_get(gtk_widget_get_style_context(contextDown->Get()), GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_COLOR, &colDown, NULL);
|
||||
|
||||
// Upload
|
||||
cairo_set_source_rgb(cr, colUp->red, colUp->green, colUp->blue);
|
||||
|
||||
// Triangle
|
||||
cairo_move_to(cr, q.x + virtToPx(6), q.y + virtToPx(0)); // Top mid
|
||||
cairo_line_to(cr, q.x + virtToPx(0), q.y + virtToPx(10)); // Left bottom
|
||||
cairo_line_to(cr, q.x + virtToPx(12), q.y + virtToPx(10)); // Right bottom
|
||||
cairo_close_path(cr);
|
||||
cairo_fill(cr);
|
||||
|
||||
// Rectangle
|
||||
// Go a bit above, to avoid gaps between tri and quad
|
||||
cairo_rectangle(cr, q.x + virtToPx(4), q.y + virtToPx(10 - epsilon), virtToPx(4), virtToPx(12 + epsilon));
|
||||
cairo_fill(cr);
|
||||
|
||||
// Download
|
||||
cairo_set_source_rgb(cr, colDown->red, colDown->green, colDown->blue);
|
||||
|
||||
// Triangle
|
||||
cairo_move_to(cr, q.x + virtToPx(18), q.y + virtToPx(24)); // Bottom mid
|
||||
cairo_line_to(cr, q.x + virtToPx(12), q.y + virtToPx(14)); // Left top
|
||||
cairo_line_to(cr, q.x + virtToPx(24), q.y + virtToPx(14)); // Right top
|
||||
cairo_close_path(cr);
|
||||
cairo_fill(cr);
|
||||
|
||||
// Rectangle
|
||||
// Go a bit below, to avoid gaps between tri and quad
|
||||
cairo_rectangle(cr, q.x + virtToPx(16), q.y + virtToPx(2), virtToPx(4), virtToPx(12 + epsilon));
|
||||
cairo_fill(cr);
|
||||
|
||||
gdk_rgba_free(colUp);
|
||||
gdk_rgba_free(colDown);
|
||||
}
|
||||
|
||||
void Revealer::SetTransition(Transition transition)
|
||||
{
|
||||
m_Transition = transition;
|
||||
|
|
26
src/Widget.h
26
src/Widget.h
|
@ -226,6 +226,32 @@ private:
|
|||
SensorStyle m_Style{};
|
||||
};
|
||||
|
||||
class NetworkSensor : public CairoArea
|
||||
{
|
||||
public:
|
||||
virtual void Create() override;
|
||||
|
||||
void SetLimitUp(Range limit) { limitUp = limit; };
|
||||
void SetLimitDown(Range limit) { limitDown = limit; };
|
||||
|
||||
void SetUp(double val);
|
||||
void SetDown(double val);
|
||||
|
||||
private:
|
||||
void Draw(cairo_t* cr) override;
|
||||
|
||||
// These are in percent
|
||||
double up, down;
|
||||
|
||||
Range limitUp;
|
||||
Range limitDown;
|
||||
|
||||
// What I do here is a little bit gross, but I need a working style context
|
||||
// Just manually creating a style context doesn't work for me.
|
||||
std::unique_ptr<Box> contextUp;
|
||||
std::unique_ptr<Box> contextDown;
|
||||
};
|
||||
|
||||
class Revealer : public Widget
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue