mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 07:33:52 +02:00
154 lines
9.2 KiB
Text
154 lines
9.2 KiB
Text
---
|
|
description: For tasks requiring working with user facing UI components.
|
|
globs:
|
|
alwaysApply: false
|
|
---
|
|
# Telegram Desktop UI Styling
|
|
|
|
## Style Definition Files
|
|
|
|
UI element styles (colors, fonts, paddings, margins, icons, etc.) are defined in `.style` files using a custom syntax. These files are located alongside the C++ source files they correspond to within specific UI component directories (e.g., `Telegram/SourceFiles/ui/chat/chat.style`).
|
|
|
|
Definitions from other `.style` files can be included using the `using` directive at the top of the file:
|
|
```style
|
|
using "ui/basic.style";
|
|
using "ui/widgets/widgets.style";
|
|
```
|
|
|
|
The central definition of named colors happens in `Telegram/SourceFiles/ui/colors.palette`. This file allows for theme generation and loading colors from various sources.
|
|
|
|
### Syntax Overview
|
|
|
|
1. **Built-in Types:** The syntax recognizes several base types inferred from the value assigned:
|
|
* `int`: Integer numbers (e.g., `lineHeight: 20;`)
|
|
* `bool`: Boolean values (e.g., `useShadow: true;`)
|
|
* `pixels`: Pixel values, ending with `px` (e.g., `borderWidth: 1px;`). Generated as `int` in C++.
|
|
* `color`: Named colors defined in `colors.palette` (e.g., `background: windowBg;`)
|
|
* `icon`: Defined inline using a specific syntax (see below). Generates `style::icon`.
|
|
* `margins`: Four pixel values for margins or padding. Requires `margins(top, right, bottom, left)` syntax (e.g., `margin: margins(10px, 5px, 10px, 5px);` or `padding: margins(8px, 8px, 8px, 8px);`). Generates `style::margins` (an alias for `QMargins`).
|
|
* `size`: Two pixel values for width and height (e.g., `iconSize: size(16px, 16px);`). Generates `style::size`.
|
|
* `point`: Two pixel values for x and y coordinates (e.g., `textPos: point(5px, 2px);`). Generates `style::point`.
|
|
* `align`: Alignment keywords (e.g., `textAlign: align(center);` or `iconAlign: align(left);`). Generates `style::align`.
|
|
* `font`: Font definitions (e.g., `font: font(14px semibold);`). Generates `style::font`.
|
|
* `double`: Floating point numbers (e.g., `disabledOpacity: 0.5;`)
|
|
|
|
*Note on Borders:* Borders are typically defined using multiple fields like `border: pixels;` (for width) and `borderFg: color;` (for color), rather than a single CSS-like property.
|
|
|
|
2. **Structure Definition:** You can define complex data structures directly within the `.style` file:
|
|
```style
|
|
MyButtonStyle { // Defines a structure named 'MyButtonStyle'
|
|
textPadding: margins; // Field 'textPadding' expects margins type
|
|
icon: icon; // Field 'icon' of type icon
|
|
height: pixels; // Field 'height' of type pixels
|
|
}
|
|
```
|
|
This generates a `struct MyButtonStyle { ... };` inside the `namespace style`. Fields will have corresponding C++ types (`style::margins`, `style::icon`, `int`).
|
|
|
|
3. **Variable Definition & Inheritance:** Variables are defined using `name: value;` or `groupName { ... }`. They can be of built-in types or custom structures. Structures can be initialized inline or inherit from existing variables.
|
|
|
|
**Icon Definition Syntax:** Icons are defined inline using the `icon{...}` syntax. The generator probes for `.svg` files or `.png` files (including `@2x`, `@3x` variants) based on the provided path stem.
|
|
```style
|
|
// Single-part icon definition:
|
|
myIconSearch: icon{{ "gui/icons/search", iconColor }};
|
|
// Multi-part icon definition (layers drawn bottom-up):
|
|
myComplexIcon: icon{
|
|
{ "gui/icons/background", iconBgColor },
|
|
{ "gui/icons/foreground", iconFgColor }
|
|
};
|
|
// Icon with path modifiers (PNG only for flips, SVG only for size):
|
|
myFlippedIcon: icon{{ "gui/icons/arrow-flip_horizontal", arrowColor }};
|
|
myResizedIcon: icon{{ "gui/icons/logo-128x128", logoColor }}; // Forces 128x128 for SVG
|
|
```
|
|
|
|
**Other Variable Examples:**
|
|
```style
|
|
// Simple variables
|
|
buttonHeight: 30px;
|
|
activeButtonColor: buttonBgActive; // Named color from colors.palette
|
|
|
|
// Variable of a custom structure type, initialized inline
|
|
defaultButton: MyButtonStyle {
|
|
textPadding: margins(10px, 15px, 10px, 15px); // Use margins(...) syntax
|
|
icon: myIconSearch; // Assign the previously defined icon variable
|
|
height: buttonHeight; // Reference another variable
|
|
}
|
|
|
|
// Another variable inheriting from 'defaultButton' and overriding/adding fields
|
|
primaryButton: MyButtonStyle(defaultButton) {
|
|
icon: myComplexIcon; // Override icon with the multi-part one
|
|
backgroundColor: activeButtonColor; // Add a field not in MyButtonStyle definition
|
|
}
|
|
|
|
// Style group (often used for specific UI elements)
|
|
chatInput { // Example using separate border properties and explicit padding
|
|
border: 1px; // Border width
|
|
borderFg: defaultInputFieldBorder; // Border color (named color)
|
|
padding: margins(5px, 10px, 5px, 10px); // Use margins(...) syntax for padding field
|
|
backgroundColor: defaultChatBg; // Background color
|
|
}
|
|
```
|
|
|
|
## Code Generation
|
|
|
|
A code generation tool processes these `.style` files and `colors.palette` to create C++ objects.
|
|
- The `using` directives resolve dependencies between `.style` files.
|
|
- Custom structure definitions (like `MyButtonStyle`) generate corresponding `struct MyButtonStyle { ... };` within the `namespace style`.
|
|
- Style variables/groups (like `defaultButton`, `primaryButton`, `chatInput`) are generated as objects/structs within the `st` namespace (e.g., `st::defaultButton`, `st::primaryButton`, `st::chatInput`). These generated structs contain members corresponding to the fields defined in the `.style` file.
|
|
- Color objects are generated into the `st` namespace as well, based on their names in `colors.palette` (e.g., `st::windowBg`, `st::buttonBgActive`).
|
|
- The generated header files for styles are placed in the `Telegram/SourceFiles/styles/` directory with a `style_` prefix (e.g., `styles/style_widgets.h` for `ui/widgets/widgets.style`). You include them like `#include "styles/style_widgets.h"`.
|
|
|
|
Generated C++ types correspond to the `.style` types: `style::color`, `style::font`, `style::margins` (used for both `margin:` and `padding:` fields), `style::icon`, `style::size`, `style::point`, `style::align`, and `int` or `bool` for simple types.
|
|
|
|
## Style Usage in Code
|
|
|
|
Styles are applied in C++ code by referencing the generated `st::...` objects and their members.
|
|
|
|
```cpp
|
|
// Example: Including the generated style header
|
|
#include "styles/style_widgets.h" // For styles defined in ui/widgets/widgets.style
|
|
|
|
// ... inside some UI class code ...
|
|
|
|
// Accessing members of a generated style struct
|
|
int height = st::primaryButton.height; // Accessing the 'height' field (pixels -> int)
|
|
const style::icon &icon = st::primaryButton.icon; // Accessing the 'icon' field (st::myComplexIcon)
|
|
style::margins padding = st::primaryButton.textPadding; // Accessing 'textPadding'
|
|
style::color bgColor = st::primaryButton.backgroundColor; // Accessing the color (st::activeButtonColor)
|
|
|
|
// Applying styles (conceptual examples)
|
|
myButton->setIcon(st::primaryButton.icon);
|
|
myButton->setHeight(st::primaryButton.height);
|
|
myButton->setPadding(st::primaryButton.textPadding);
|
|
myButton->setBackgroundColor(st::primaryButton.backgroundColor);
|
|
|
|
// Using styles directly in painting
|
|
void MyWidget::paintEvent(QPaintEvent *e) {
|
|
Painter p(this);
|
|
p.fillRect(rect(), st::chatInput.backgroundColor); // Use color from chatInput style
|
|
|
|
// Border painting requires width and color
|
|
int borderWidth = st::chatInput.border; // Access border width (pixels -> int)
|
|
style::color borderColor = st::chatInput.borderFg; // Access border color
|
|
if (borderWidth > 0) {
|
|
p.setPen(QPen(borderColor, borderWidth));
|
|
// Adjust rect for pen width if needed before drawing
|
|
p.drawRect(rect().adjusted(borderWidth / 2, borderWidth / 2, -borderWidth / 2, -borderWidth / 2));
|
|
}
|
|
|
|
// Access padding (style::margins)
|
|
style::margins inputPadding = st::chatInput.padding;
|
|
// ... use inputPadding.top(), inputPadding.left() etc. for content layout ...
|
|
}
|
|
```
|
|
|
|
**Key Points:**
|
|
|
|
* Styles are defined in `.style` files next to their corresponding C++ source files.
|
|
* `using "path/to/other.style";` includes definitions from other style files.
|
|
* Named colors are defined centrally in `ui/colors.palette`.
|
|
* `.style` syntax supports built-in types (like `pixels`, `color`, `margins`, `point`, `size`, `align`, `font`, `double`), custom structure definitions (`Name { field: type; ... }`), variable definitions (`name: value;`), and inheritance (`child: Name(parent) { ... }`).
|
|
* Values must match the expected type (e.g., fields declared as `margins` type, like `margin:` or `padding:`, require `margins(...)` syntax). Borders are typically set via separate `border: pixels;` and `borderFg: color;` fields.
|
|
* Icons are defined inline using `name: icon{{ "path_stem", color }};` or `name: icon{ { "path1", c1 }, ... };` syntax, with optional path modifiers.
|
|
* Code generation creates `struct` definitions in the `style` namespace for custom types and objects/structs in the `st` namespace for defined variables/groups.
|
|
* Generated headers are in `styles/` with a `style_` prefix and must be included.
|
|
* Access style properties via the generated `st::` objects (e.g., `st::primaryButton.height`, `st::chatInput.backgroundColor`).
|