Добавить docs.html

This commit is contained in:
KoDer 2026-08-23 17:59:01 +00:00
parent 237adfcddf
commit 00e372a571

522
docs.html Normal file
View File

@ -0,0 +1,522 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GUI Library Documentation</title>
<!-- Подключаем шрифты и иконки -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css">
<style>
:root {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--bg-tertiary: #334155;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--accent: #38bdf8;
--accent-hover: #0ea5e9;
--success: #22c55e;
--border: #334155;
--code-bg: #0d1117;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
display: flex;
min-height: 100vh;
}
/* Скроллбар */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg-primary); }
::-webkit-scrollbar-thumb { background: var(--bg-tertiary); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }
/* Боковая панель */
.sidebar {
width: 280px;
background-color: var(--bg-secondary);
border-right: 1px solid var(--border);
position: fixed;
height: 100vh;
overflow-y: auto;
padding: 2rem 1.5rem;
z-index: 100;
}
.logo {
font-size: 1.5rem;
font-weight: 700;
color: var(--accent);
margin-bottom: 2rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.search-box {
width: 100%;
padding: 0.75rem;
background: var(--bg-primary);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-primary);
font-family: 'Inter', sans-serif;
margin-bottom: 1.5rem;
outline: none;
transition: border-color 0.2s;
}
.search-box:focus { border-color: var(--accent); }
.nav-group { margin-bottom: 1.5rem; }
.nav-title {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-secondary);
margin-bottom: 0.5rem;
font-weight: 600;
}
.nav-link {
display: block;
padding: 0.5rem 0.75rem;
color: var(--text-secondary);
text-decoration: none;
border-radius: 6px;
font-size: 0.9rem;
transition: all 0.2s;
}
.nav-link:hover, .nav-link.active {
background-color: var(--bg-tertiary);
color: var(--accent);
}
/* Основной контент */
.main-content {
margin-left: 280px;
flex: 1;
padding: 3rem 4rem;
max-width: 1200px;
}
h1 { font-size: 2.5rem; margin-bottom: 1rem; color: var(--text-primary); }
h2 { font-size: 1.8rem; margin-top: 3rem; margin-bottom: 1rem; color: var(--accent); border-bottom: 1px solid var(--border); padding-bottom: 0.5rem; }
h3 { font-size: 1.3rem; margin-top: 2rem; margin-bottom: 0.75rem; color: var(--text-primary); }
p { margin-bottom: 1rem; color: var(--text-secondary); }
.badge {
display: inline-block;
padding: 0.25rem 0.5rem;
background: var(--bg-tertiary);
color: var(--accent);
border-radius: 4px;
font-size: 0.75rem;
font-family: 'JetBrains Mono', monospace;
margin-right: 0.5rem;
}
/* Блоки кода */
.code-wrapper {
position: relative;
margin: 1.5rem 0;
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border);
}
.code-header {
background: var(--bg-secondary);
padding: 0.5rem 1rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
font-size: 0.85rem;
color: var(--text-secondary);
}
.copy-btn {
background: transparent;
border: 1px solid var(--border);
color: var(--text-secondary);
padding: 0.25rem 0.75rem;
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
transition: all 0.2s;
}
.copy-btn:hover { background: var(--bg-tertiary); color: var(--text-primary); }
.copy-btn.copied { border-color: var(--success); color: var(--success); }
pre { margin: 0 !important; border-radius: 0 !important; background: var(--code-bg) !important; }
code { font-family: 'JetBrains Mono', monospace !important; font-size: 0.9rem !important; }
/* Таблицы */
table {
width: 100%;
border-collapse: collapse;
margin: 1.5rem 0;
background: var(--bg-secondary);
border-radius: 8px;
overflow: hidden;
}
th, td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid var(--border);
}
th { background: var(--bg-tertiary); color: var(--text-primary); font-weight: 600; }
td { color: var(--text-secondary); }
td code { background: var(--bg-primary); padding: 0.2rem 0.4rem; border-radius: 4px; color: var(--accent); }
/* Аккордеон для API */
details {
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 8px;
margin-bottom: 1rem;
overflow: hidden;
}
summary {
padding: 1rem;
cursor: pointer;
font-weight: 600;
color: var(--text-primary);
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
}
summary::-webkit-details-marker { display: none; }
summary::after { content: '+'; font-size: 1.5rem; color: var(--accent); }
details[open] summary::after { content: '−'; }
details[open] summary { border-bottom: 1px solid var(--border); }
.details-content { padding: 1.5rem; }
.highlight { color: var(--accent); font-weight: 600; }
@media (max-width: 768px) {
.sidebar { transform: translateX(-100%); transition: transform 0.3s; }
.sidebar.open { transform: translateX(0); }
.main-content { margin-left: 0; padding: 2rem; }
}
</style>
</head>
<body>
<!-- Боковая навигация -->
<nav class="sidebar">
<div class="logo">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></svg>
X11 GUI Lib
</div>
<input type="text" class="search-box" placeholder="Поиск по документации..." id="searchInput">
<div class="nav-group">
<div class="nav-title">Начало работы</div>
<a href="#intro" class="nav-link">Введение</a>
<a href="#quickstart" class="nav-link">Быстрый старт</a>
<a href="#architecture" class="nav-link">Архитектура</a>
</div>
<div class="nav-group">
<div class="nav-title">Компоненты</div>
<a href="#eventbus" class="nav-link">EventBus</a>
<a href="#rawpicture" class="nav-link">RawPicture</a>
<a href="#widgets" class="nav-link">Виджеты</a>
</div>
<div class="nav-group">
<div class="nav-title">API Справочник</div>
<a href="#api-window" class="nav-link">gui::window</a>
<a href="#api-page" class="nav-link">gui::page</a>
<a href="#api-combat" class="nav-link">gui::combat</a>
<a href="#api-widget" class="nav-link">gui::Widget</a>
</div>
</nav>
<!-- Основной контент -->
<main class="main-content">
<section id="intro">
<h1>Документация GUI Библиотеки</h1>
<p>Легковесная, кроссплатформенная (X11) библиотека для создания графических интерфейсов на C++. Поддерживает программный рендеринг, анимации, иерархию виджетов и событийно-ориентированную архитектуру.</p>
</section>
<section id="quickstart">
<h2>🚀 Быстрый старт</h2>
<p>Минимальный пример создания окна с кнопкой и обработкой события.</p>
<div class="code-wrapper">
<div class="code-header">
<span>main.cpp</span>
<button class="copy-btn" onclick="copyCode(this)">Копировать</button>
</div>
<pre><code class="language-cpp">#include "gui.h"
int main() {
// 1. Создаем окно
gui::window win("Мое Приложение");
// 2. Добавляем страницу
win.addPAGE("main");
// 3. Настраиваем страницу виджетами
win.configur_page("main", [](gui::page& p) {
// Создаем кнопку
gui::WidgetData btnData;
btnData.id = "my_button";
btnData.text = "Нажми меня!";
btnData.x = 50; btnData.y = 50;
btnData.width = 150; btnData.height = 40;
btnData.bg_color = 0x2563EB; // Синий
btnData.fg_color = 0xFFFFFF; // Белый текст
p.Button(btnData);
}, true); // true = сделать активной сразу
// 4. Подписываемся на событие
gui::EventBus::get().on("button.click", [](const gui::EventData& e) {
if (e.source_id == "my_button") {
std::cout << "Кнопка нажата!" << std::endl;
}
});
// 5. Главный цикл
while (true) {
win.update(); // Обработка событий X11 и отрисовка
// Добавьте std::this_thread::sleep_for для экономии CPU
}
return 0;
}</code></pre>
</div>
</section>
<section id="architecture">
<h2>🏛 Архитектура</h2>
<p>Библиотека построена на строгой иерархии:</p>
<table>
<thead>
<tr><th>Уровень</th><th>Класс</th><th>Описание</th></tr>
</thead>
<tbody>
<tr><td><span class="badge">1</span></td><td><code>gui::window</code></td><td>Управляет соединением с X11, главным циклом (`update`) и вкладками.</td></tr>
<tr><td><span class="badge">2</span></td><td><code>gui::page</code></td><td>Представляет собой вкладку или экран. Наследуется от <code>combat</code>.</td></tr>
<tr><td><span class="badge">3</span></td><td><code>gui::combat</code></td><td>Базовый контейнер. Хранит коллекцию виджетов и предоставляет фабричные методы для их создания.</td></tr>
<tr><td><span class="badge">4</span></td><td><code>gui::Widget</code></td><td>Конкретный элемент интерфейса (кнопка, ввод, слайдер). Также наследуется от <code>combat</code>, позволяя создавать вложенные структуры (например, деревья).</td></tr>
</tbody>
</table>
</section>
<section id="eventbus">
<h2>📡 EventBus</h2>
<p>Глобальная шина событий для слабой связи между компонентами. Реализована как Singleton.</p>
<div class="code-wrapper">
<div class="code-header"><span>Использование EventBus</span><button class="copy-btn" onclick="copyCode(this)">Копировать</button></div>
<pre><code class="language-cpp">// Подписка на событие
int token = gui::EventBus::get().on("slider.change", [](const gui::EventData& e) {
std::cout << "Widget: " << e.source_id << ", Value: " << e.value << std::endl;
});
// Генерация события (обычно делается внутри библиотеки, но можно и вручную)
gui::EventBus::get().emit("custom.event", {"widget_id", "some text", 0.5f, 0, true});
// Отписка
gui::EventBus::get().off(token);</code></pre>
</div>
<p>Структура <code>EventData</code> содержит: <code>source_id</code> (ID виджета), <code>text</code>, <code>value</code> (для слайдеров/прогресса), <code>index</code> (для списков), <code>flag</code> (для чекбоксов).</p>
</section>
<section id="rawpicture">
<h2>🎨 RawPicture</h2>
<p>Класс для программного рендеринга в буфер. Поддерживает 8, 16, 24 и 32-битные форматы.</p>
<ul>
<li><strong>Примитивы:</strong> <code>drawLine</code>, <code>fillRect</code>, <code>drawCircle</code>, <code>fillPolygon</code>, <code>drawText</code>.</li>
<li><strong>Загрузка:</strong> <code>load("image.bmp")</code> или <code>load("image.ppm")</code>.</li>
<li><strong>Отображение:</strong> <code>present(display, window, gc, x, y)</code> для вывода на экран X11.</li>
</ul>
</section>
<section id="widgets">
<h2>🧩 Доступные виджеты</h2>
<p>Все виджеты создаются через методы класса <code>combat</code> (или <code>page</code>) путем передачи структуры <code>WidgetData</code>.</p>
<table>
<thead><tr><th>Метод</th><th>Тип</th><th>Описание</th></tr></thead>
<tbody>
<tr><td><code>Button()</code></td><td><code>BUTTON</code></td><td>Стандартная кнопка. Поддерживает <code>on_page_click</code> и <code>on_window_click</code>.</td></tr>
<tr><td><code>Label()</code></td><td><code>LABEL</code></td><td>Текстовая метка.</td></tr>
<tr><td><code>Input()</code></td><td><code>INPUT</code></td><td>Поле ввода текста. Перехватывает фокус клавиатуры.</td></tr>
<tr><td><code>Checkbox()</code></td><td><code>CHECKBOX</code></td><td>Флажок. Состояние в <code>data.checked</code>.</td></tr>
<tr><td><code>Radiobutton()</code></td><td><code>RADIO</code></td><td>Радиокнопка. Автоматически снимает выделение с других радио-кнопок с тем же <code>id</code> на странице.</td></tr>
<tr><td><code>Slider()</code></td><td><code>SLIDER</code></td><td>Ползунок. Значение 0.0 - 1.0 в <code>data.value</code>. Поддерживает перетаскивание.</td></tr>
<tr><td><code>Progressbar()</code></td><td><code>PROGRESS</code></td><td>Индикатор прогресса. Поддерживает анимацию <code>indeterminate</code>.</td></tr>
<tr><td><code>Listbox()</code></td><td><code>LISTBOX</code></td><td>Список элементов. Элементы задаются через <code>data.items</code>.</td></tr>
<tr><td><code>Dropdown()</code></td><td><code>DROPDOWN</code></td><td>Выпадающий список с анимацией открытия.</td></tr>
<tr><td><code>TreeView()</code></td><td><code>TREE_VIEW</code></td><td>Контейнер для древовидной структуры. Использует <code>TreeNode</code> как детей.</td></tr>
<tr><td><code>ScrollView()</code></td><td><code>SCROLL</code></td><td>Область с прокруткой содержимого.</td></tr>
<tr><td><code>RawPictureWidget()</code></td><td><code>RAW_PIC</code></td><td>Отображает объект <code>RawPicture</code> из <code>data.picture</code>.</td></tr>
</tbody>
</table>
</section>
<section id="api-window">
<h2>📚 API Справочник: gui::window</h2>
<details>
<summary><code>window(std::string title)</code></summary>
<div class="details-content">
<p>Конструктор. Инициализирует соединение с X11, создает окно заданного размера (по умолчанию 1200x600) и настраивает маску событий.</p>
</div>
</details>
<details>
<summary><code>void update()</code></summary>
<div class="details-content">
<p>Главный метод цикла. Обрабатывает все накопленные события X11, обновляет анимации виджетов (<code>tick</code>), очищает окно и перерисовывает вкладки и активную страницу. <strong>Должен вызываться постоянно.</strong></p>
</div>
</details>
<details>
<summary><code>void addPAGE(std::string name)</code> / <code>void configur_page(...)</code></summary>
<div class="details-content">
<p><code>addPAGE</code> создает пустую страницу. <code>configur_page</code> создает (если нет), применяет лямбда-функцию для наполнения виджетами и может сделать её активной (<code>active = true</code>).</p>
</div>
</details>
<details>
<summary><code>void openPAGE(std::string name)</code></summary>
<div class="details-content">
<p>Делает указанную страницу активной, деактивируя остальные. Генерирует событие <code>"page.open"</code>.</p>
</div>
</details>
</section>
<section id="api-combat">
<h2>📚 API Справочник: gui::combat</h2>
<p>Базовый класс для контейнеров. Все методы создания виджетов возвращают ссылку на созданный <code>Widget</code>, что позволяет сохранять его для последующего изменения.</p>
<details>
<summary>Фабричные методы (<code>Button</code>, <code>Label</code>, <code>Input</code> и т.д.)</summary>
<div class="details-content">
<p>Принимают объект <code>WidgetData</code>. Автоматически устанавливают соответствующий <code>WidgetType</code>, добавляют виджет во внутренний вектор и возвращают на него ссылку.</p>
</div>
</details>
<details>
<summary><code>Widget* find(const std::string& id)</code></summary>
<div class="details-content">
<p>Рекурсивный поиск виджета по его уникальному идентификатору <code>id</code> внутри контейнера и всех его дочерних элементов.</p>
</div>
</details>
<details>
<summary><code>void visit(const std::function<void(Widget&)>& fn)</code></summary>
<div class="details-content">
<p>Применяет переданную лямбда-функцию ко всем виджетам в иерархии. Удобно для массовой модификации (например, отключения всех кнопок).</p>
</div>
</details>
</section>
<section id="api-widget">
<h2>📚 API Справочник: gui::Widget</h2>
<details>
<summary><code>void setValue(float v)</code> / <code>float getValue()</code></summary>
<div class="details-content">
<p>Устанавливает целевое значение. Для прогресс-баров и слайдеров это запускает плавную анимацию изменения <code>data.value</code> к <code>data.target_value</code> внутри метода <code>tick()</code>.</p>
</div>
</details>
<details>
<summary>Анимация и состояние</summary>
<div class="details-content">
<p>Виджет содержит поля <code>anim</code> (для dropdown), <code>phase</code> (для неопределенного прогресса). Метод <code>tick(float dt)</code> автоматически вызывается из <code>window::update()</code> и интерполирует значения.</p>
</div>
</details>
</section>
<section id="tips">
<h2>💡 Советы и лучшие практики</h2>
<ul>
<li><strong>Производительность:</strong> Библиотека использует программный рендеринг (CPU). Для сложных сцен избегайте частого пересоздания <code>RawPicture</code>. Используйте <code>blit</code> для кеширования отрисовки.</li>
<li><strong>ID Виджетов:</strong> Всегда задавайте уникальное поле <code>id</code> в <code>WidgetData</code>, если планируете обращаться к виджету позже или слушать его события.</li>
<li><strong>Вложенность:</strong> Виджеты <code>TreeView</code> и <code>ScrollView</code> предназначены для содержания других виджетов. Добавляйте их через стандартные методы, они будут учитываться при расчете высоты контента и прокрутки.</li>
<li><strong>Цвета:</strong> Указываются в формате HEX (например, <code>0xFF0000</code> для красного). Библиотека автоматически преобразует их в формат пикселей X11 при отрисовке.</li>
</ul>
</section>
<footer style="margin-top: 4rem; padding-top: 2rem; border-top: 1px solid var(--border); color: var(--text-secondary); text-align: center; font-size: 0.9rem;">
<p>Сгенерировано для X11 C++ GUI Library. 2026</p>
</footer>
</main>
<!-- Скрипты -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-cpp.min.js"></script>
<script>
// Функция копирования кода
function copyCode(button) {
const codeBlock = button.parentElement.nextElementSibling.querySelector('code');
const text = codeBlock.innerText;
navigator.clipboard.writeText(text).then(() => {
const originalText = button.innerText;
button.innerText = 'Скопировано!';
button.classList.add('copied');
setTimeout(() => {
button.innerText = originalText;
button.classList.remove('copied');
}, 2000);
});
}
// Поиск по документации
const searchInput = document.getElementById('searchInput');
const sections = document.querySelectorAll('section');
const navLinks = document.querySelectorAll('.nav-link');
searchInput.addEventListener('input', (e) => {
const term = e.target.value.toLowerCase();
sections.forEach(section => {
const text = section.innerText.toLowerCase();
if (text.includes(term)) {
section.style.display = 'block';
} else {
section.style.display = term === '' ? 'block' : 'none';
}
});
// Подсветка активных ссылок в сайдбаре
navLinks.forEach(link => {
const targetId = link.getAttribute('href').substring(1);
const targetSection = document.getElementById(targetId);
if (targetSection && targetSection.style.display === 'none') {
link.style.display = 'none';
} else {
link.style.display = 'block';
}
});
});
// Плавная прокрутка и активный класс
navLinks.forEach(link => {
link.addEventListener('click', (e) => {
navLinks.forEach(l => l.classList.remove('active'));
link.classList.add('active');
});
});
window.addEventListener('scroll', () => {
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop;
if (pageYOffset >= sectionTop - 100) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href').substring(1) === current) {
link.classList.add('active');
}
});
});
</script>
</body>
</html>