kas_core/theme/
style.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Theme style components
7
8use crate::dir::Direction;
9
10/// Margin size
11///
12/// Default value: [`MarginStyle::Large`].
13#[crate::impl_default(MarginStyle::Large)]
14#[derive(Copy, Clone, Debug, PartialEq)]
15pub enum MarginStyle {
16    /// No margins
17    None,
18    /// Inner margin, used to draw highlight/selection boxes
19    ///
20    /// Guide size: 1px at 100%, 2px at 125%, 2px at 150%, 3px at 200%.
21    ///
22    /// This is the smallest of the fixed margin sizes, and only really
23    /// useful to reserve space for drawing selection boxes.
24    Inner,
25    /// A small margin for inner layout
26    ///
27    /// Guide size: 2px at 100%, 3px at 125%, 4px at 150%, 5px at 200%.
28    Tiny,
29    /// Small external margin size
30    ///
31    /// Guide size: 4px at 100%, 5px at 125%, 7px at 150%, 9px at 200%.
32    Small,
33    /// Large margin, used between elements such as buttons
34    ///
35    /// Guide size: 7px at 100%, 9px at 125%, 11px at 150%, 15px at 200%.
36    Large,
37    /// Text margins
38    ///
39    /// Margins for use around standard text elements (may be asymmetric).
40    Text,
41    /// Specify in pixels (scaled)
42    Px(f32),
43    /// Specify in Em (font size)
44    Em(f32),
45}
46
47/// Style of marks
48#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
49pub enum MarkStyle {
50    /// A chevron (i.e. arrow without stalk) pointing in the given direction
51    Chevron(Direction),
52    /// A cross rotated 45°
53    X,
54}
55
56/// Various features which may be sized and drawn
57///
58/// Includes most types of features excepting text and frames.
59#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
60pub enum Feature {
61    Separator,
62    Mark(MarkStyle),
63    CheckBox,
64    RadioBox,
65    ScrollBar(Direction),
66    Slider(Direction),
67    ProgressBar(Direction),
68}
69
70impl From<MarkStyle> for Feature {
71    fn from(style: MarkStyle) -> Self {
72        Feature::Mark(style)
73    }
74}
75
76/// Style of a frame
77///
78/// A "frame" is an element surrounding another element.
79#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash)]
80pub enum FrameStyle {
81    /// No frame, just draw the background
82    #[default]
83    None,
84    /// A frame for grouping content
85    Frame,
86    /// A frame around pop-ups
87    Popup,
88    /// Border around a pop-up menu entry
89    MenuEntry,
90    /// Frame used to indicate navigation focus
91    NavFocus,
92    /// Border of a button
93    Button,
94    /// Border of a tab
95    Tab,
96    /// Box used to contain editable text
97    EditBox,
98    /// Window decoration (excludes top buttons)
99    Window,
100}
101
102/// Selection style hint
103///
104/// How to draw selections
105#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
106pub enum SelectionStyle {
107    /// Adjust background color
108    Highlight,
109    /// Draw a frame around the selection
110    Frame,
111    /// Both
112    Both,
113}
114
115impl SelectionStyle {
116    /// True if an external margin is required
117    ///
118    /// Margin size is [`SizeCx::inner_margins`](super::SizeCx::inner_margins)
119    pub fn is_external(self) -> bool {
120        matches!(self, SelectionStyle::Frame | SelectionStyle::Both)
121    }
122}
123
124/// Class of text drawn
125///
126/// Themes choose font, font size, colour, and alignment based on this.
127#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
128#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
129pub enum TextClass {
130    /// Label text is drawn over the background colour
131    ///
132    /// This takes one parameter: `multi_line`. Text is wrapped only if true.
133    Label(bool),
134    /// Scrollable label
135    ///
136    /// This is similar to `Label(true)`, but may occupy less vertical space.
137    /// Usually it also implies that the text is both scrollable and selectable,
138    /// but these are characteristics of the widget, not the text object.
139    LabelScroll,
140    /// Label with access keys
141    ///
142    /// This takes one parameter: `multi_line`. Text is wrapped only if true.
143    ///
144    /// This is identical to `Label` except that effects are only drawn if
145    /// access key mode is activated (usually the `Alt` key).
146    AccessLabel(bool),
147    /// Button text is drawn over a button
148    ///
149    /// Same as `AccessLabel(false)`, though theme may differentiate.
150    Button,
151    /// Menu label (single line, does not stretch)
152    ///
153    /// Similar to `AccessLabel(false)`, but with horizontal stretching disabled.
154    MenuLabel,
155    /// Editable text, usually encapsulated in some type of box
156    ///
157    /// This takes one parameter: `multi_line`. Text is wrapped only if true.
158    Edit(bool),
159}
160
161impl TextClass {
162    /// True if text is single-line only
163    #[inline]
164    pub fn single_line(self) -> bool {
165        !self.multi_line()
166    }
167
168    /// True if text is multi-line and should automatically line-wrap
169    #[inline]
170    pub fn multi_line(self) -> bool {
171        use TextClass::*;
172        matches!(
173            self,
174            Label(true) | LabelScroll | AccessLabel(true) | Edit(true)
175        )
176    }
177
178    /// True if text effects should only be shown dependant on access key
179    /// mode being active
180    #[inline]
181    pub fn is_access_key(self) -> bool {
182        use TextClass::*;
183        matches!(self, AccessLabel(_) | Button | MenuLabel)
184    }
185}