diff --git a/src/Config.cpp b/src/Config.cpp index 6ed928e..d8a666f 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -27,6 +27,14 @@ void ApplyProperty(uint32_t& propertyToSet, const std::string_view& va propertyToSet = atoi(valStr.c_str()); } +template<> +void ApplyProperty(int32_t& propertyToSet, const std::string_view& value) +{ + // Why, C++? + std::string valStr = std::string(value); + propertyToSet = atoi(valStr.c_str()); +} + template<> void ApplyProperty(double& propertyToSet, const std::string_view& value) { @@ -53,6 +61,30 @@ void ApplyProperty(bool& propertyToSet, const std::string_view& value) } } +template<> +void ApplyProperty>(std::pair& propertyToSet, const std::string_view& value) +{ + // TODO: Ignore escaped delimiter (e.g. \, is the same as ,) + const char delim = ','; + const char* whitespace = " \t"; + size_t delimPos = value.find(delim); + if (delimPos == std::string::npos) + { + propertyToSet = {std::string(value), 0}; + return; + } + std::string_view before = value.substr(0, delimPos); + std::string_view after = value.substr(delimPos + 1); + + // Strip whitespaces for before + size_t beginBefore = before.find_first_not_of(whitespace); + size_t endBefore = before.find_last_not_of(whitespace); + before = before.substr(beginBefore, endBefore - beginBefore + 1); + + ApplyProperty(propertyToSet.first, before); + ApplyProperty(propertyToSet.second, after); +} + template void AddConfigVar(const std::string& propertyName, T& propertyToSet, std::string_view line, bool& setConfig) { @@ -161,6 +193,21 @@ void Config::Load() AddConfigVar("AudioMinVolume", config.audioMinVolume, lineView, foundProperty); AddConfigVar("AudioMaxVolume", config.audioMaxVolume, lineView, foundProperty); + std::pair buf; + bool hasntFoundProperty = !foundProperty; + AddConfigVar("SNIIconSize", buf, lineView, foundProperty); + if (foundProperty && hasntFoundProperty) + { + // This was found + config.sniIconSizes[buf.first] = buf.second; + } + hasntFoundProperty = !foundProperty; + AddConfigVar("SNIPaddingTop", buf, lineView, foundProperty); + if (foundProperty && hasntFoundProperty) + { + config.sniPaddingTop[buf.first] = buf.second; + } + if (foundProperty == false) { LOG("Warning: unknown config var: " << lineView); diff --git a/src/Config.h b/src/Config.h index 674c5bc..0c268a8 100644 --- a/src/Config.h +++ b/src/Config.h @@ -2,6 +2,7 @@ #include #include #include +#include class Config { @@ -39,6 +40,10 @@ public: uint32_t checkUpdateInterval = 5 * 60; // Interval to run the "checkPackagesCommand". In seconds + // SNIIconSize: ["Title String"], ["Size"] + std::unordered_map sniIconSizes; + std::unordered_map sniPaddingTop; + // Only affects outputs (i.e.: speakers, not microphones). This remaps the range of the volume; In percent double audioMinVolume = 0.f; // Map the minimum volume to this value double audioMaxVolume = 100.f; // Map the maximum volume to this value diff --git a/src/SNI.cpp b/src/SNI.cpp index 8e73c9d..e105eea 100644 --- a/src/SNI.cpp +++ b/src/SNI.cpp @@ -326,6 +326,33 @@ namespace SNI LOG("SNI: Add " << item.name << " to widget"); auto texture = Widget::Create(); + bool wasExplicitOverride = false; + for (auto& [filter, size] : Config::Get().sniIconSizes) + { + if (item.tooltip.find(filter) != std::string::npos) + { + wasExplicitOverride = true; + texture->ForceHeight(size); + } + else if (filter == "*" && !wasExplicitOverride) + { + texture->ForceHeight(size); + } + } + wasExplicitOverride = false; + for (auto& [filter, padding] : Config::Get().sniPaddingTop) + { + if (item.tooltip.find(filter) != std::string::npos) + { + LOG("Padding " << padding); + wasExplicitOverride = true; + texture->AddPaddingTop(padding); + } + else if (filter == "*" && !wasExplicitOverride) + { + texture->AddPaddingTop(padding); + } + } texture->SetHorizontalTransform({0, true, Alignment::Fill}); texture->SetBuf(item.w, item.h, item.iconData); texture->SetTooltip(item.tooltip); diff --git a/src/Widget.cpp b/src/Widget.cpp index 955ab14..f69e1ac 100644 --- a/src/Widget.cpp +++ b/src/Widget.cpp @@ -520,13 +520,15 @@ void Texture::Draw(cairo_t* cr) { GtkAllocation dim; gtk_widget_get_allocation(m_Widget, &dim); - double ratio = (double)m_Width / (double)m_Height; - gtk_widget_set_size_request(m_Widget, dim.height * ratio, dim.height); - double scale = (double)dim.height / (double)m_Height; + double height = m_ForcedHeight != 0 ? m_ForcedHeight : dim.height; + double scale = (double)height / (double)m_Height; + double width = (double)m_Width * scale; + + gtk_widget_set_size_request(m_Widget, width + 2, height); cairo_scale(cr, scale, scale); - cairo_rectangle(cr, 0.f, 0.f, m_Width, m_Height); - gdk_cairo_set_source_pixbuf(cr, m_Pixbuf, 0, 0); + cairo_rectangle(cr, (dim.width - width) / 2.0, m_Padding + (dim.height - height) / 2.0, m_Width, m_Height); + gdk_cairo_set_source_pixbuf(cr, m_Pixbuf, (dim.width - width) / 2.0, m_Padding + (dim.height - height) / 2.0); cairo_fill(cr); } diff --git a/src/Widget.h b/src/Widget.h index 231748e..bfb2e95 100644 --- a/src/Widget.h +++ b/src/Widget.h @@ -277,11 +277,16 @@ public: // Non-Owning, ARGB32 void SetBuf(size_t width, size_t height, uint8_t* buf); + void ForceHeight(size_t height) { m_ForcedHeight = height; }; + void AddPaddingTop(int32_t topPadding) { m_Padding = topPadding; }; + private: void Draw(cairo_t* cr) override; size_t m_Width; size_t m_Height; + size_t m_ForcedHeight = 0; + int32_t m_Padding = 0; GBytes* m_Bytes; GdkPixbuf* m_Pixbuf; };