Created
December 18, 2024 08:23
-
-
Save memononen/460c86488a29bebe4b3a2540f6ef8b68 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Named color names (theme specific) | |
enum MIcolorNames { | |
MI_COLOR_NEUTRAL, | |
MI_COLOR_ACCENT_A, | |
}; | |
// Tones per name (theme specific) | |
enum MIcolorTone { | |
MI_COLORTONE_50, | |
MI_COLORTONE_75, | |
MI_COLORTONE_100, | |
MI_COLORTONE_200, | |
MI_COLORTONE_300, | |
MI_COLORTONE_400, | |
MI_COLORTONE_500, | |
MI_COLORTONE_600, | |
MI_COLORTONE_700, | |
MI_COLORTONE_800, | |
MI_COLORTONE_900, | |
MI_COUNT_COLORTONES, | |
}; | |
static float scaled(float v, float scale) | |
{ | |
return froundf(v * scale); | |
} | |
void miInitTestTheme(float scale) | |
{ | |
// Setup color palette | |
MIcolor neutralColors[MI_COUNT_COLORTONES] = { | |
miRGBA(29,29,29, 255), // 50 | |
miRGBA(38,38,38, 255), // 75 | |
miRGBA(50,50,50, 255), // 100 | |
miRGBA(63,63,63, 255), // 200 | |
miRGBA(84,84,84, 255), // 300 | |
miRGBA(112,112,112, 255), // 400 | |
miRGBA(144,144,144, 255), // 500 | |
miRGBA(178,178,178, 255), // 600 | |
miRGBA(209,209,209, 255), // 700 | |
miRGBA(235,235,235, 255), // 800 | |
miRGBA(255,255,255, 255), // 900 | |
}; | |
MIcolor accentAColors[MI_COUNT_COLORTONES] = { | |
miRGBA(76,161,169, 29), // 50 | |
miRGBA(76,161,169, 38), // 75 | |
miRGBA(76,161,169, 50), // 100 - window background | |
miRGBA(76,161,169, 63), // 200 | |
miRGBA(76,161,169, 84), // 300 | |
miRGBA(76,161,169, 112), // 400 | |
miRGBA(76,161,169, 144), // 500 | |
miRGBA(76,161,169, 178), // 600 | |
miRGBA(76,161,169, 209), // 700 - text | |
miRGBA(76,161,169, 235), // 800 | |
miRGBA(76,161,169, 255), // 900 | |
}; | |
miSetColorTokenScale(MI_COLOR_NEUTRAL, neutralColors, MI_COUNT_COLORTONES); | |
miSetColorTokenScale(MI_COLOR_ACCENT_A, accentAColors, MI_COUNT_COLORTONES); | |
// Common design tokens | |
float defaultWidgetHeight = scaled(22, scale); | |
float defaultWidgetWidth = scaled(100, scale); | |
float defaultFontSize = scaled(13, scale); | |
float smallFontSize = scaled(11, scale); | |
float defaultIconSize = scaled(18, scale); | |
float smallRounding = scaled(1, scale); | |
float normalRounding = scaled(2, scale); | |
float mediumRounding = scaled(4, scale); | |
float largeRounding = scaled(8, scale); | |
MIsize defaultWidgetSize = { defaultWidgetWidth, defaultWidgetHeight }; | |
float scrollbarSize = scaled(10, scale); | |
float sliderTrackSize = scaled(4, scale); | |
MIpadding contentPadding = { scaled(8, scale), scaled(0, scale) }; | |
MIpadding windowPadding = { scaled(4, scale), scaled(4, scale) }; | |
MIpadding windowPaddingSmall = { scaled(2, scale), scaled(2, scale) }; | |
float windowSpacing = scaled(6, scale); | |
float smallSpacing = scaled(2, scale); | |
float defaultSpacing = scaled(4, scale); | |
float strokeWidth = scaled(1, scale); | |
float caretWidth = scaled(2, scale); | |
// Common fonts | |
MIfontStyle normalFont = { | |
.face = MI_FONT_NORMAL, | |
.size = defaultFontSize, | |
.lineHeight = 1.4f, | |
}; | |
MIfontStyle normalSmallFont = { | |
.face = MI_FONT_NORMAL, | |
.size = smallFontSize, | |
.lineHeight = 1.4f, | |
}; | |
MIfontStyle boldFont = { | |
.face = MI_FONT_BOLD, | |
.size = defaultFontSize, | |
.lineHeight = 1.4f, | |
}; | |
MIfontStyle iconFont = { | |
.face = MI_FONT_ICON, | |
.size = defaultIconSize, | |
}; | |
// The styles are defined using a macro, which adds (hopefully) a but more typesafety. | |
// The type name gets hashed to the lookup key. | |
// | |
// The macro is kinda annoying for syntax highlighting, though. I wish I could od without it. | |
// | |
// #define MI_THEME_DEFINE_STYLE(name, type, ...) miThemeDefineStyle(name, #type, &(type) { __VA_ARGS__ }, sizeof(type)) | |
// #define MI_THEME_GET_STYLE(name, type) (type*)miThemeGetStyle(name, #type, sizeof(type)) | |
// Styles | |
MI_THEME_DEFINE_STYLE("label", MIthemeTextStyle, | |
.font = normalFont, | |
.color = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_500), | |
.align = MI_ALIGN_LEFT | MI_ALIGN_MIDDLE, | |
.minSize = { 0.f, defaultWidgetHeight } // width based on content | |
); | |
MI_THEME_DEFINE_STYLE("text", MIthemeTextStyle, | |
.font = normalFont, | |
.color = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_700), | |
.align = MI_ALIGN_LEFT | MI_ALIGN_MIDDLE, | |
.minSize = { 0.f, defaultWidgetHeight } // width based on content | |
); | |
MI_THEME_DEFINE_STYLE("paragraph", MIthemeTextStyle, | |
.font = normalFont, | |
.color = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_700), | |
.align = MI_ALIGN_LEFT | MI_ALIGN_MIDDLE, | |
.minSize = { 0.f, defaultWidgetHeight } // width based on content | |
); | |
MI_THEME_DEFINE_STYLE("icon", MIthemeTextStyle, | |
.font = iconFont, | |
.color = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_500), | |
.align = MI_ALIGN_LEFT | MI_ALIGN_MIDDLE, | |
.minSize = { defaultIconSize, defaultWidgetHeight } | |
); | |
MI_THEME_DEFINE_STYLE("input", MIinputStyle, | |
.text = { | |
.font = normalFont, | |
.color = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_700), | |
.states = { | |
.active = miColorModDeltaTone(1), | |
.disabled = miColorModDeltaTone(-2) | |
}, | |
.align = MI_ALIGN_LEFT | MI_ALIGN_MIDDLE, | |
}, | |
.box = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_50), | |
.strokeColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_200), | |
.strokeStates = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}, | |
.strokeWidth = strokeWidth, | |
.rounding = smallRounding, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.defaultSize = defaultWidgetSize, | |
.padding = contentPadding, | |
.caretWidth = caretWidth, | |
.caretColor = miNamedColor(MI_COLOR_ACCENT_A, MI_COLORTONE_900), | |
.selectionColor = miNamedColor(MI_COLOR_ACCENT_A, MI_COLORTONE_500), | |
); | |
MI_THEME_DEFINE_STYLE("slider", MIsliderStyle, | |
.track = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_50), | |
.fillStates = { 0 }, | |
.rounding = sliderTrackSize/2, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.range = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_300), | |
.fillStates = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}, | |
.rounding = sliderTrackSize/2, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.thumb = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_600), | |
.fillStates = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}, | |
.strokeColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_75), | |
.strokeWidth = strokeWidth, | |
.rounding = defaultWidgetHeight/4, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.defaultSize = defaultWidgetSize, | |
.thumbSize = (MIsize) { defaultWidgetHeight/2, defaultWidgetHeight }, | |
.trackSize = sliderTrackSize, | |
); | |
MI_THEME_DEFINE_STYLE("scrollbar", MIsliderStyle, | |
.track = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_75), | |
.fillStates = {0}, | |
.rounding = scrollbarSize/2, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.thumb = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_200), | |
.fillStates = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}, | |
.strokeColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_50), | |
.strokeStates = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}, | |
.strokeWidth = strokeWidth, | |
.rounding = scrollbarSize/2, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.defaultSize = (MIsize){ scrollbarSize, scrollbarSize }, | |
.thumbSize = (MIsize) { scrollbarSize, scrollbarSize }, | |
.trackSize = scrollbarSize, | |
); | |
MI_THEME_DEFINE_STYLE("button", MIbuttonStyle, | |
.text = { | |
.font = normalFont, | |
.align = MI_ALIGN_CENTER | MI_ALIGN_MIDDLE, | |
.color = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_700), | |
.states = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
} | |
}, | |
.box = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_200), | |
.fillStates = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}, | |
.strokeColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_50), | |
.strokeStates = { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(1), | |
}, | |
.strokeWidth = strokeWidth, | |
.rounding = mediumRounding, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.defaultSize = { 0.f, defaultWidgetHeight }, | |
.padding = contentPadding | |
); | |
MI_THEME_DEFINE_STYLE("window", MIwindowStyle, | |
.box = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_100), | |
.strokeColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_75), | |
.strokeWidth = strokeWidth, | |
.rounding = normalRounding, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.padding = windowPadding, | |
.spacing = windowSpacing, | |
); | |
MI_THEME_DEFINE_STYLE("popup", MIwindowStyle, | |
.box = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_75), | |
.strokeColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_50), | |
.strokeWidth = strokeWidth, | |
.rounding = normalRounding, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.padding = windowPadding, | |
.spacing = windowSpacing, | |
.offset = smallSpacing, | |
); | |
MI_THEME_DEFINE_STYLE("tooltip", MIwindowStyle, | |
.box = { | |
.fillColor = miNamedColor(MI_COLOR_NEUTRAL, MI_COLORTONE_50), | |
.rounding = smallRounding, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.padding = windowPaddingSmall, | |
.spacing = defaultSpacing, | |
.offset = smallSpacing, | |
); | |
{ | |
// Menu item is compount widget. | |
// | |
// [icon] Text detail [>] | |
// | |
MIthemeTextStyle smallLabel = *MI_THEME_GET_STYLE("label", MIthemeTextStyle); | |
smallLabel.font = normalSmallFont; | |
smallLabel.states = (MIcolorModStates) { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}; | |
MIthemeTextStyle text = *MI_THEME_GET_STYLE("text", MIthemeTextStyle); | |
text.states = (MIcolorModStates) { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}; | |
MIthemeTextStyle icon = *MI_THEME_GET_STYLE("icon", MIthemeTextStyle); | |
icon.states = (MIcolorModStates) { | |
.hover = miColorModDeltaTone(1), | |
.active = miColorModDeltaTone(2), | |
}; | |
MI_THEME_DEFINE_STYLE("menuitem", MImenuItemStyle, | |
.icon = icon, | |
.text = text, | |
.detail = smallLabel, | |
.subMenu = icon, | |
.background = { | |
.fillColor = miNamedColor(MI_COLOR_ACCENT_A, MI_COLORTONE_500), | |
.fillStates = { | |
.normal = miColorModClear(), | |
.active = miColorModDeltaTone(4), | |
}, | |
.rounding = smallRounding, | |
.roundingMask = MI_ROUND_ALL, | |
}, | |
.defaultSize = { 0.f, defaultWidgetHeight }, | |
.padding = { defaultSpacing, 0 }, | |
.spacing = defaultSpacing, | |
.checkIcon = /*ICON_CHECK*/ "\xee\x97\x8a", | |
.subMenuIcon = /*ICON_CHEVRON_RIGHT*/ "\xee\x97\x8c", | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment