295 lines
11 KiB
C++
295 lines
11 KiB
C++
#ifndef AXIOMDESIGNSYSTEM_H
|
|
#define AXIOMDESIGNSYSTEM_H
|
|
|
|
#pragma once
|
|
#include "JuceLibraryCode/BinaryData.h"
|
|
|
|
namespace AXIOM {
|
|
class DesignSystem : public juce::LookAndFeel_V4 {
|
|
public:
|
|
DesignSystem();
|
|
|
|
~DesignSystem() override = default;
|
|
|
|
struct Colours {
|
|
//=====================BASE-COLORS========================//
|
|
static inline const juce::Colour ACCENTCOLOUR = juce::Colour::fromRGB(86, 254, 255); // #56FEFF
|
|
static inline const juce::Colour BACKGROUNDCOLOUR = juce::Colour::fromRGB(51, 51, 51); // #333333
|
|
static inline const juce::Colour FOREGROUNDCOLOUR = juce::Colour::fromRGB(252, 250, 249); // #FCFAF9
|
|
static inline const juce::Colour SURFACECOLOUR = juce::Colour::fromRGB(31, 31, 31); // #1F1F1F
|
|
static inline const juce::Colour MUTEDTEXTCOLOUR = juce::Colour::fromRGB(207, 207, 207); // #CFCFCF
|
|
static inline const juce::Colour ACCENTWEAKCOLOUR = juce::Colour::fromRGB(61, 183, 183); // #3DB7B7
|
|
//=====================HOVER-COLORS========================//
|
|
static inline const juce::Colour ACCENTHOVER = juce::Colour::fromRGB(110, 255, 255); // #6EFFFF
|
|
static inline const juce::Colour BACKGROUNDHOVER = juce::Colour::fromRGB(66, 66, 66); // #424242
|
|
static inline const juce::Colour FOREGROUNDHOVER = juce::Colour::fromRGB(255, 255, 255); // #FFFFFF
|
|
static inline const juce::Colour SURFACEHOVER = juce::Colour::fromRGB(42, 42, 42); // #2A2A2A
|
|
static inline const juce::Colour MUTEDTEXTHOVER = juce::Colour::fromRGB(230, 230, 230); // #E6E6E6
|
|
static inline const juce::Colour ACCENTWEAKHOVER = juce::Colour::fromRGB(82, 210, 210); // #52D2D2
|
|
};
|
|
|
|
struct Typography {
|
|
inline static juce::Typeface::Ptr orbitronFont =
|
|
juce::Typeface::createSystemTypefaceFor(
|
|
BinaryData::OrbitronRegular_ttf,
|
|
BinaryData::OrbitronRegular_ttfSize);
|
|
inline static juce::Typeface::Ptr horizonFont =
|
|
juce::Typeface::createSystemTypefaceFor(
|
|
BinaryData::horizon_otf,
|
|
BinaryData::horizon_otfSize);
|
|
inline static juce::Typeface::Ptr jetBrainsMonoFont =
|
|
juce::Typeface::createSystemTypefaceFor(
|
|
BinaryData::JetBrainsMonoRegular_ttf,
|
|
BinaryData::JetBrainsMonoRegular_ttfSize);
|
|
|
|
|
|
inline static const juce::String primaryFamily{"Orbitron Bold"};
|
|
inline static const juce::String displayFamily{"Horizon"};
|
|
inline static const juce::String monoFamily{"JetBrains Mono"};
|
|
|
|
struct Scale {
|
|
float basePx = 14.0f;
|
|
float ratio = 1.125f;
|
|
|
|
float sizeFor(int step) const noexcept {
|
|
// step = 0 => basePx, step = 1 => base*ratio, step = -1 => base/ratio, ...
|
|
return basePx * std::pow(ratio, static_cast<float>(step));
|
|
}
|
|
};
|
|
|
|
inline static Scale scale{};
|
|
|
|
enum class Style {
|
|
Display,
|
|
H1, H2, H3,
|
|
Subtitle,
|
|
Body,
|
|
Small,
|
|
Caption,
|
|
Button,
|
|
Mono,
|
|
Overline
|
|
};
|
|
|
|
struct TextToken {
|
|
juce::String family;
|
|
int stepFromBase;
|
|
bool bold = false;
|
|
bool italic = false;
|
|
bool uppercase = false;
|
|
float letterSpacing = 0.0f;
|
|
float lineHeight = 1.25f;
|
|
bool useMonospace = false;
|
|
};
|
|
|
|
static TextToken getToken(Style style) noexcept {
|
|
switch (style) {
|
|
case Style::Display: return {displayFamily, 5, true, false, false, 0.0f, 1.15f, false};
|
|
case Style::H1: return {primaryFamily, 4, true, false, false, 0.0f, 1.15f, false};
|
|
case Style::H2: return {primaryFamily, 3, true, false, false, 0.0f, 1.20f, false};
|
|
case Style::H3: return {primaryFamily, 2, false, false, false, 0.0f, 1.20f, false};
|
|
case Style::Subtitle: return {primaryFamily, 1, false, false, false, 0.01f, 1.25f, false};
|
|
case Style::Body: return {primaryFamily, 0, false, false, false, 0.0f, 1.35f, false};
|
|
case Style::Small: return {primaryFamily, -1, false, false, false, 0.0f, 1.35f, false};
|
|
case Style::Caption: return {primaryFamily, -2, false, false, false, 0.02f, 1.40f, false};
|
|
case Style::Button: return {primaryFamily, 0, true, false, false, 0.02f, 1.10f, false};
|
|
case Style::Mono: return {monoFamily, -1, false, false, false, 0.0f, 1.30f, true};
|
|
case Style::Overline: return {primaryFamily, -3, true, false, true, 0.06f, 1.20f, false};
|
|
}
|
|
return {primaryFamily, 0, false, false, false, 0.0f, 1.3f, false};
|
|
}
|
|
|
|
static juce::Font getFont(Style style, float uiScale = 1.0f) {
|
|
const auto t = getToken(style);
|
|
const auto fam = t.family;
|
|
auto height = scale.sizeFor(t.stepFromBase) * uiScale;
|
|
|
|
|
|
juce::Font f{fam, height, juce::Font::plain};
|
|
|
|
if (fam == displayFamily && horizonFont != nullptr) {
|
|
f = juce::Font(horizonFont).withHeight(height);
|
|
} else if (fam == primaryFamily && orbitronFont != nullptr) {
|
|
f = juce::Font(orbitronFont).withHeight(height);
|
|
} else if (fam == monoFamily && jetBrainsMonoFont != nullptr) {
|
|
f = juce::Font(jetBrainsMonoFont).withHeight(height);
|
|
} else
|
|
f.setTypefaceName(fam);
|
|
|
|
f.setBold(t.bold);
|
|
f.setItalic(t.italic);
|
|
f.setExtraKerningFactor(t.letterSpacing);
|
|
|
|
return f;
|
|
}
|
|
|
|
static void applyToLabel(juce::Label &label, Style style, float uiScale = 1.0f) {
|
|
label.setFont(getFont(style, uiScale));
|
|
|
|
if (getToken(style).uppercase)
|
|
label.setText(label.getText().toUpperCase(), juce::NotificationType::dontSendNotification);
|
|
|
|
label.setMinimumHorizontalScale(1.0f);
|
|
}
|
|
|
|
static juce::TextLayout createTextLayout(juce::String text,
|
|
juce::Rectangle<float> bounds,
|
|
Style style,
|
|
juce::Colour colour,
|
|
float uiScale = 1.0f,
|
|
juce::Justification just = juce::Justification::topLeft) {
|
|
const auto token = getToken(style);
|
|
const auto font = getFont(style, uiScale);
|
|
|
|
juce::AttributedString as;
|
|
as.setJustification(just);
|
|
|
|
if (token.uppercase)
|
|
text = text.toUpperCase();
|
|
|
|
as.append(text, font, colour);
|
|
|
|
juce::TextLayout tl;
|
|
tl.createLayout(as, bounds.getWidth());
|
|
return tl;
|
|
}
|
|
};
|
|
|
|
struct Spacing {
|
|
enum class DensityMode {
|
|
Narrow,
|
|
Compact,
|
|
Regular,
|
|
Wide,
|
|
SuperWide
|
|
};
|
|
|
|
static constexpr float getDensityFactor(DensityMode mode) {
|
|
switch (mode) {
|
|
case DensityMode::Narrow: return {0.9f};
|
|
|
|
case DensityMode::Compact: return {0.95f};
|
|
|
|
case DensityMode::Regular: return {1.0f};
|
|
|
|
case DensityMode::Wide: return {1.08f};
|
|
|
|
case DensityMode::SuperWide: return {1.15f};
|
|
}
|
|
return {1.0f};
|
|
};
|
|
|
|
enum class SizeMode {
|
|
XS,
|
|
S,
|
|
M,
|
|
L,
|
|
XL
|
|
};
|
|
|
|
static constexpr int getSizeUnits(SizeMode size) {
|
|
switch (size) {
|
|
case SizeMode::XS: return 1;
|
|
case SizeMode::S: return 2;
|
|
case SizeMode::M: return 3;
|
|
case SizeMode::L: return 4;
|
|
case SizeMode::XL: return 6;
|
|
}
|
|
return 1;
|
|
};
|
|
|
|
enum class SnapMode {
|
|
Nearest, Floor, Ceiling
|
|
};
|
|
|
|
struct Scale {
|
|
float baseUnit = 8.0f;
|
|
float densityFactor = 1.0f;
|
|
float uiScale = 1.0f;
|
|
float uiScaleInfluence = 0.3f;
|
|
static constexpr float MINCLAMP = 4.0f;
|
|
static constexpr float MAXCLAMP = 56.0f;
|
|
|
|
SnapMode snapMode = SnapMode::Nearest;
|
|
float stepUnits = 1.0f;
|
|
|
|
float space(SizeMode size) noexcept {
|
|
float px;
|
|
auto units = static_cast<float>(getSizeUnits(size));
|
|
|
|
px = units * baseUnit;
|
|
px *= densityFactor;
|
|
px *= 1.0f + (uiScale - 1.0f) * uiScaleInfluence;
|
|
px = snapToGrid(px, stepUnits, snapMode);
|
|
return std::clamp(px, MINCLAMP, MAXCLAMP);
|
|
}
|
|
|
|
float snapToGrid(float px, float stepUnits, SnapMode mode) noexcept{
|
|
float grid = baseUnit * stepUnits;
|
|
if (grid <= 0.0f) return px;
|
|
|
|
float units = px / grid;
|
|
float snappedUnits;
|
|
switch (mode) {
|
|
case SnapMode::Nearest: snappedUnits = std::round(units); break;
|
|
case SnapMode::Floor: snappedUnits = std::floor(units + 1e-6f); break;
|
|
case SnapMode::Ceiling: snappedUnits = std::ceil (units - 1e-6f); break;
|
|
}
|
|
return snappedUnits * grid;
|
|
};
|
|
};
|
|
|
|
inline static Scale scale;
|
|
|
|
static void setDensity(DensityMode mode) noexcept {
|
|
scale.densityFactor = getDensityFactor(mode);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
struct Shape {
|
|
};
|
|
|
|
struct Shadows {
|
|
};
|
|
|
|
struct Opacity {
|
|
};
|
|
|
|
struct Motion {
|
|
};
|
|
|
|
struct Components {
|
|
struct ButtonStyles {
|
|
};
|
|
|
|
struct SliderStyles {
|
|
};
|
|
|
|
struct LabelStyles {
|
|
};
|
|
|
|
struct TextInputStyles {
|
|
};
|
|
|
|
struct ComboBoxStyles {
|
|
};
|
|
};
|
|
|
|
struct Assets {
|
|
};
|
|
|
|
struct Layout {
|
|
};
|
|
|
|
|
|
private
|
|
:
|
|
};
|
|
|
|
}
|
|
|
|
|
|
#endif //AXIOMDESIGNSYSTEM_H
|