init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
This commit is contained in:
154
.cursor/rules/styling.mdc
Normal file
154
.cursor/rules/styling.mdc
Normal file
@@ -0,0 +1,154 @@
|
||||
---
|
||||
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`).
|
||||
Reference in New Issue
Block a user