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}