mirror of
https://github.com/koloideal/SortLab.git
synced 2026-08-08 10:01:16 +03:00
step
This commit is contained in:
@@ -29,6 +29,7 @@ set(SORTLAB_SOURCES
|
||||
src/Array.cpp
|
||||
src/Sorter.cpp
|
||||
src/UI.cpp
|
||||
src/Theme.cpp
|
||||
src/OperationsHistory.cpp
|
||||
src/ProgressMap.cpp
|
||||
src/SortHistory.cpp
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "OperationsHistory.hpp"
|
||||
#include "ProgressMap.hpp"
|
||||
#include "SortHistory.hpp"
|
||||
#include "Theme.hpp"
|
||||
|
||||
class App {
|
||||
public:
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
enum class ThemeType {
|
||||
DARK,
|
||||
LIGHT
|
||||
};
|
||||
|
||||
struct ColorPalette {
|
||||
// Основные цвета фона
|
||||
sf::Color windowBackground;
|
||||
sf::Color panelBackground;
|
||||
sf::Color bottomPanelBackground;
|
||||
sf::Color overlayBackground;
|
||||
|
||||
// Цвета текста
|
||||
sf::Color textPrimary;
|
||||
sf::Color textSecondary;
|
||||
sf::Color textTertiary;
|
||||
sf::Color textAccent;
|
||||
|
||||
// Цвета для состояний элементов массива
|
||||
sf::Color stateNormalLow; // Нижняя часть градиента для обычных элементов
|
||||
sf::Color stateNormalHigh; // Верхняя часть градиента для обычных элементов
|
||||
sf::Color stateCompare; // Цвет для сравниваемых элементов
|
||||
sf::Color stateSwap; // Цвет для переставляемых элементов
|
||||
sf::Color stateSorted; // Цвет для отсортированных элементов
|
||||
|
||||
// Цвета UI элементов
|
||||
sf::Color separator;
|
||||
sf::Color histogramLow; // Нижняя часть градиента гистограммы
|
||||
sf::Color histogramHigh; // Верхняя часть градиента гистограммы
|
||||
|
||||
// Цвета для ProgressMap
|
||||
sf::Color progressMapNormal;
|
||||
|
||||
// Цвета для оверлеев
|
||||
sf::Color overlayTitle;
|
||||
sf::Color overlaySubtitle;
|
||||
sf::Color overlaySection;
|
||||
sf::Color overlayBody;
|
||||
sf::Color overlayFooter;
|
||||
|
||||
// Цвета для истории
|
||||
sf::Color historyTableHeader;
|
||||
sf::Color historyRowEven;
|
||||
sf::Color historyRowOdd;
|
||||
sf::Color historyNewestHighlight;
|
||||
sf::Color historyNewestText;
|
||||
sf::Color historySpeedFastest;
|
||||
sf::Color historySpeedSlow;
|
||||
|
||||
// Цвета статусов
|
||||
sf::Color statusFinished;
|
||||
sf::Color statusPlaying;
|
||||
sf::Color statusPaused;
|
||||
};
|
||||
|
||||
class Theme {
|
||||
public:
|
||||
static Theme& getInstance();
|
||||
|
||||
void setTheme(ThemeType type);
|
||||
ThemeType getThemeType() const;
|
||||
void toggleTheme();
|
||||
|
||||
const ColorPalette& getPalette() const;
|
||||
|
||||
private:
|
||||
Theme();
|
||||
Theme(const Theme&) = delete;
|
||||
Theme& operator=(const Theme&) = delete;
|
||||
|
||||
void initDarkTheme();
|
||||
void initLightTheme();
|
||||
|
||||
ThemeType currentTheme_;
|
||||
ColorPalette darkPalette_;
|
||||
ColorPalette lightPalette_;
|
||||
ColorPalette* currentPalette_;
|
||||
};
|
||||
+20
-13
@@ -148,6 +148,10 @@ void App::handleEvents() {
|
||||
}
|
||||
break;
|
||||
|
||||
case sf::Keyboard::T:
|
||||
Theme::getInstance().toggleTheme();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -230,7 +234,8 @@ void App::update(float dt) {
|
||||
}
|
||||
|
||||
void App::render() {
|
||||
window_.clear(sf::Color(10, 12, 20));
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
window_.clear(palette.windowBackground);
|
||||
|
||||
const float topUIHeight = 80.0f;
|
||||
const float bottomPanelHeight = 140.0f;
|
||||
@@ -256,20 +261,20 @@ void App::render() {
|
||||
useGradient = true;
|
||||
break;
|
||||
case Array::State::COMPARE:
|
||||
barColor = sf::Color(0, 220, 255);
|
||||
barColor = palette.stateCompare;
|
||||
break;
|
||||
case Array::State::SWAP:
|
||||
barColor = sf::Color(255, 120, 30);
|
||||
barColor = palette.stateSwap;
|
||||
break;
|
||||
case Array::State::SORTED:
|
||||
barColor = sf::Color(50, 220, 120);
|
||||
barColor = palette.stateSorted;
|
||||
break;
|
||||
}
|
||||
|
||||
if (useGradient) {
|
||||
float normalizedValue = array_.getValue(i) / maxVal;
|
||||
sf::Color bottomColor(60, 80, 140);
|
||||
sf::Color topColor(160, 180, 255);
|
||||
sf::Color bottomColor = palette.stateNormalLow;
|
||||
sf::Color topColor = palette.stateNormalHigh;
|
||||
|
||||
sf::Color gradientTop(
|
||||
static_cast<sf::Uint8>(bottomColor.r + (topColor.r - bottomColor.r) * normalizedValue),
|
||||
@@ -299,7 +304,7 @@ void App::render() {
|
||||
|
||||
sf::RectangleShape separator(sf::Vector2f(window_.getSize().x, 1.0f));
|
||||
separator.setPosition(0.0f, mainAreaBottom);
|
||||
separator.setFillColor(sf::Color(40, 45, 60));
|
||||
separator.setFillColor(palette.separator);
|
||||
window_.draw(separator);
|
||||
|
||||
renderDeltaHistogram();
|
||||
@@ -307,7 +312,7 @@ void App::render() {
|
||||
|
||||
sf::RectangleShape verticalSeparator(sf::Vector2f(1.0f, bottomPanelHeight));
|
||||
verticalSeparator.setPosition(1066.0f, mainAreaBottom);
|
||||
verticalSeparator.setFillColor(sf::Color(40, 45, 60));
|
||||
verticalSeparator.setFillColor(palette.separator);
|
||||
window_.draw(verticalSeparator);
|
||||
|
||||
ui_.draw(window_);
|
||||
@@ -324,6 +329,8 @@ void App::render() {
|
||||
}
|
||||
|
||||
void App::renderDeltaHistogram() {
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
const float startX = 0.0f;
|
||||
const float startY = 760.0f;
|
||||
const float width = 1066.0f;
|
||||
@@ -331,7 +338,7 @@ void App::renderDeltaHistogram() {
|
||||
|
||||
sf::RectangleShape background(sf::Vector2f(width, height));
|
||||
background.setPosition(startX, startY);
|
||||
background.setFillColor(sf::Color(12, 15, 25));
|
||||
background.setFillColor(palette.bottomPanelBackground);
|
||||
window_.draw(background);
|
||||
|
||||
const auto& deltaHistory = opsHistory_.getDeltaHistory();
|
||||
@@ -350,8 +357,8 @@ void App::renderDeltaHistogram() {
|
||||
float y = startY + height - barHeight;
|
||||
|
||||
float normalizedValue = static_cast<float>(deltaHistory[i]) / static_cast<float>(maxDelta);
|
||||
sf::Color lowColor(0, 80, 200);
|
||||
sf::Color highColor(0, 240, 255);
|
||||
sf::Color lowColor = palette.histogramLow;
|
||||
sf::Color highColor = palette.histogramHigh;
|
||||
|
||||
sf::Color barColor(
|
||||
static_cast<sf::Uint8>(lowColor.r + (highColor.r - lowColor.r) * normalizedValue),
|
||||
@@ -370,7 +377,7 @@ void App::renderDeltaHistogram() {
|
||||
|
||||
sf::RectangleShape baseline(sf::Vector2f(width, 1.0f));
|
||||
baseline.setPosition(startX, startY + height - 1.0f);
|
||||
baseline.setFillColor(sf::Color(60, 70, 90));
|
||||
baseline.setFillColor(palette.separator);
|
||||
window_.draw(baseline);
|
||||
|
||||
if (bottomPanelFontLoaded_) {
|
||||
@@ -378,7 +385,7 @@ void App::renderDeltaHistogram() {
|
||||
label.setFont(bottomPanelFont_);
|
||||
label.setString("Delta Comparisons / step");
|
||||
label.setCharacterSize(13);
|
||||
label.setFillColor(sf::Color(180, 180, 180));
|
||||
label.setFillColor(palette.textTertiary);
|
||||
label.setPosition(startX + 10.0f, startY + 5.0f);
|
||||
window_.draw(label);
|
||||
}
|
||||
|
||||
+12
-7
@@ -1,10 +1,13 @@
|
||||
#include "ProgressMap.hpp"
|
||||
#include "Theme.hpp"
|
||||
#include <cmath>
|
||||
|
||||
ProgressMap::ProgressMap() {
|
||||
}
|
||||
|
||||
void ProgressMap::draw(sf::RenderWindow& window, const Array& array, sf::Font& font, bool fontLoaded) {
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
const float startX = 1066.0f;
|
||||
const float startY = 760.0f;
|
||||
const float width = 534.0f;
|
||||
@@ -12,7 +15,7 @@ void ProgressMap::draw(sf::RenderWindow& window, const Array& array, sf::Font& f
|
||||
|
||||
sf::RectangleShape background(sf::Vector2f(width, height));
|
||||
background.setPosition(startX, startY);
|
||||
background.setFillColor(sf::Color(12, 15, 25));
|
||||
background.setFillColor(palette.bottomPanelBackground);
|
||||
window.draw(background);
|
||||
|
||||
if (fontLoaded) {
|
||||
@@ -20,7 +23,7 @@ void ProgressMap::draw(sf::RenderWindow& window, const Array& array, sf::Font& f
|
||||
label.setFont(font);
|
||||
label.setString("Progress Map");
|
||||
label.setCharacterSize(13);
|
||||
label.setFillColor(sf::Color(180, 180, 180));
|
||||
label.setFillColor(palette.textTertiary);
|
||||
label.setPosition(startX + 10.0f, startY + 5.0f);
|
||||
window.draw(label);
|
||||
}
|
||||
@@ -67,16 +70,18 @@ void ProgressMap::draw(sf::RenderWindow& window, const Array& array, sf::Font& f
|
||||
}
|
||||
|
||||
sf::Color ProgressMap::getColorForState(Array::State state) const {
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
switch (state) {
|
||||
case Array::State::NORMAL:
|
||||
return sf::Color(100, 120, 150);
|
||||
return palette.progressMapNormal;
|
||||
case Array::State::COMPARE:
|
||||
return sf::Color(0, 220, 255);
|
||||
return palette.stateCompare;
|
||||
case Array::State::SWAP:
|
||||
return sf::Color(255, 120, 30);
|
||||
return palette.stateSwap;
|
||||
case Array::State::SORTED:
|
||||
return sf::Color(50, 220, 120);
|
||||
return palette.stateSorted;
|
||||
default:
|
||||
return sf::Color(100, 120, 150);
|
||||
return palette.progressMapNormal;
|
||||
}
|
||||
}
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
#include "Theme.hpp"
|
||||
|
||||
Theme& Theme::getInstance() {
|
||||
static Theme instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
Theme::Theme() : currentTheme_(ThemeType::DARK) {
|
||||
initDarkTheme();
|
||||
initLightTheme();
|
||||
currentPalette_ = &darkPalette_;
|
||||
}
|
||||
|
||||
void Theme::initDarkTheme() {
|
||||
// Основные цвета фона
|
||||
darkPalette_.windowBackground = sf::Color(10, 12, 20);
|
||||
darkPalette_.panelBackground = sf::Color(0, 0, 0, 180);
|
||||
darkPalette_.bottomPanelBackground = sf::Color(12, 15, 25);
|
||||
darkPalette_.overlayBackground = sf::Color(8, 10, 18, 230);
|
||||
|
||||
// Цвета текста
|
||||
darkPalette_.textPrimary = sf::Color::White;
|
||||
darkPalette_.textSecondary = sf::Color(220, 220, 220);
|
||||
darkPalette_.textTertiary = sf::Color(160, 160, 160);
|
||||
darkPalette_.textAccent = sf::Color(0, 220, 255);
|
||||
|
||||
darkPalette_.stateNormalLow = sf::Color(60, 80, 140);
|
||||
darkPalette_.stateNormalHigh = sf::Color(160, 180, 255);
|
||||
darkPalette_.stateCompare = sf::Color(0, 220, 255);
|
||||
darkPalette_.stateSwap = sf::Color(255, 120, 30);
|
||||
darkPalette_.stateSorted = sf::Color(50, 220, 120);
|
||||
|
||||
darkPalette_.separator = sf::Color(40, 45, 60);
|
||||
darkPalette_.histogramLow = sf::Color(0, 80, 200);
|
||||
darkPalette_.histogramHigh = sf::Color(0, 240, 255);
|
||||
|
||||
darkPalette_.progressMapNormal = sf::Color(100, 120, 150);
|
||||
|
||||
darkPalette_.overlayTitle = sf::Color::White;
|
||||
darkPalette_.overlaySubtitle = sf::Color(160, 160, 160);
|
||||
darkPalette_.overlaySection = sf::Color(0, 220, 255);
|
||||
darkPalette_.overlayBody = sf::Color(200, 200, 200);
|
||||
darkPalette_.overlayFooter = sf::Color(100, 100, 100);
|
||||
|
||||
darkPalette_.historyTableHeader = sf::Color(0, 220, 255);
|
||||
darkPalette_.historyRowEven = sf::Color(0, 0, 0, 0);
|
||||
darkPalette_.historyRowOdd = sf::Color(15, 18, 25, 100);
|
||||
darkPalette_.historyNewestHighlight = sf::Color(30, 60, 90, 150);
|
||||
darkPalette_.historyNewestText = sf::Color(100, 255, 150);
|
||||
darkPalette_.historySpeedFastest = sf::Color(100, 255, 120);
|
||||
darkPalette_.historySpeedSlow = sf::Color(255, 160, 60);
|
||||
|
||||
darkPalette_.statusFinished = sf::Color::Green;
|
||||
darkPalette_.statusPlaying = sf::Color::Yellow;
|
||||
darkPalette_.statusPaused = sf::Color::White;
|
||||
}
|
||||
|
||||
void Theme::initLightTheme() {
|
||||
lightPalette_.windowBackground = sf::Color(245, 247, 250);
|
||||
lightPalette_.panelBackground = sf::Color(255, 255, 255, 200);
|
||||
lightPalette_.bottomPanelBackground = sf::Color(235, 238, 245);
|
||||
lightPalette_.overlayBackground = sf::Color(250, 252, 255, 240);
|
||||
|
||||
lightPalette_.textPrimary = sf::Color(20, 20, 30);
|
||||
lightPalette_.textSecondary = sf::Color(40, 40, 50);
|
||||
lightPalette_.textTertiary = sf::Color(100, 100, 120);
|
||||
lightPalette_.textAccent = sf::Color(0, 120, 200);
|
||||
|
||||
lightPalette_.stateNormalLow = sf::Color(140, 160, 200);
|
||||
lightPalette_.stateNormalHigh = sf::Color(80, 120, 200);
|
||||
lightPalette_.stateCompare = sf::Color(0, 180, 255);
|
||||
lightPalette_.stateSwap = sf::Color(255, 100, 20);
|
||||
lightPalette_.stateSorted = sf::Color(40, 180, 80);
|
||||
|
||||
lightPalette_.separator = sf::Color(200, 205, 215);
|
||||
lightPalette_.histogramLow = sf::Color(100, 150, 255);
|
||||
lightPalette_.histogramHigh = sf::Color(0, 100, 200);
|
||||
|
||||
lightPalette_.progressMapNormal = sf::Color(160, 170, 190);
|
||||
|
||||
lightPalette_.overlayTitle = sf::Color(20, 20, 30);
|
||||
lightPalette_.overlaySubtitle = sf::Color(100, 100, 120);
|
||||
lightPalette_.overlaySection = sf::Color(0, 120, 200);
|
||||
lightPalette_.overlayBody = sf::Color(40, 40, 50);
|
||||
lightPalette_.overlayFooter = sf::Color(140, 140, 150);
|
||||
|
||||
lightPalette_.historyTableHeader = sf::Color(0, 120, 200);
|
||||
lightPalette_.historyRowEven = sf::Color(0, 0, 0, 0);
|
||||
lightPalette_.historyRowOdd = sf::Color(230, 235, 245, 150);
|
||||
lightPalette_.historyNewestHighlight = sf::Color(200, 230, 255, 180);
|
||||
lightPalette_.historyNewestText = sf::Color(0, 150, 80);
|
||||
lightPalette_.historySpeedFastest = sf::Color(40, 180, 80);
|
||||
lightPalette_.historySpeedSlow = sf::Color(255, 130, 40);
|
||||
|
||||
lightPalette_.statusFinished = sf::Color(0, 150, 60);
|
||||
lightPalette_.statusPlaying = sf::Color(200, 150, 0);
|
||||
lightPalette_.statusPaused = sf::Color(60, 60, 80);
|
||||
}
|
||||
|
||||
void Theme::setTheme(ThemeType type) {
|
||||
currentTheme_ = type;
|
||||
currentPalette_ = (type == ThemeType::DARK) ? &darkPalette_ : &lightPalette_;
|
||||
}
|
||||
|
||||
ThemeType Theme::getThemeType() const {
|
||||
return currentTheme_;
|
||||
}
|
||||
|
||||
void Theme::toggleTheme() {
|
||||
if (currentTheme_ == ThemeType::DARK) {
|
||||
setTheme(ThemeType::LIGHT);
|
||||
} else {
|
||||
setTheme(ThemeType::DARK);
|
||||
}
|
||||
}
|
||||
|
||||
const ColorPalette& Theme::getPalette() const {
|
||||
return *currentPalette_;
|
||||
}
|
||||
+61
-39
@@ -1,5 +1,6 @@
|
||||
#pragma execution_character_set("utf-8")
|
||||
#include "UI.hpp"
|
||||
#include "Theme.hpp"
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
@@ -12,56 +13,58 @@ UI::UI() : fontLoaded_(false), historyOpen_(false) {
|
||||
font_.setSmooth(true);
|
||||
fontLoaded_ = true;
|
||||
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
algorithmText_.setFont(font_);
|
||||
algorithmText_.setCharacterSize(56);
|
||||
algorithmText_.setScale(0.5f, 0.5f);
|
||||
algorithmText_.setFillColor(sf::Color::White);
|
||||
algorithmText_.setFillColor(palette.textPrimary);
|
||||
algorithmText_.setPosition(15.0f, 15.0f);
|
||||
|
||||
stateText_.setFont(font_);
|
||||
stateText_.setCharacterSize(40);
|
||||
stateText_.setScale(0.5f, 0.5f);
|
||||
stateText_.setFillColor(sf::Color::White);
|
||||
stateText_.setFillColor(palette.textPrimary);
|
||||
stateText_.setPosition(15.0f, 50.0f);
|
||||
|
||||
timeComplexityText_.setFont(font_);
|
||||
timeComplexityText_.setCharacterSize(32);
|
||||
timeComplexityText_.setScale(0.5f, 0.5f);
|
||||
timeComplexityText_.setFillColor(sf::Color(160, 160, 160));
|
||||
timeComplexityText_.setFillColor(palette.textTertiary);
|
||||
timeComplexityText_.setPosition(15.0f, 80.0f);
|
||||
|
||||
spaceComplexityText_.setFont(font_);
|
||||
spaceComplexityText_.setCharacterSize(32);
|
||||
spaceComplexityText_.setScale(0.5f, 0.5f);
|
||||
spaceComplexityText_.setFillColor(sf::Color(160, 160, 160));
|
||||
spaceComplexityText_.setFillColor(palette.textTertiary);
|
||||
spaceComplexityText_.setPosition(15.0f, 105.0f);
|
||||
|
||||
comparisonsText_.setFont(font_);
|
||||
comparisonsText_.setCharacterSize(36);
|
||||
comparisonsText_.setScale(0.5f, 0.5f);
|
||||
comparisonsText_.setFillColor(sf::Color(220, 220, 220));
|
||||
comparisonsText_.setFillColor(palette.textSecondary);
|
||||
comparisonsText_.setPosition(15.0f, 135.0f);
|
||||
|
||||
swapsText_.setFont(font_);
|
||||
swapsText_.setCharacterSize(36);
|
||||
swapsText_.setScale(0.5f, 0.5f);
|
||||
swapsText_.setFillColor(sf::Color(220, 220, 220));
|
||||
swapsText_.setFillColor(palette.textSecondary);
|
||||
swapsText_.setPosition(15.0f, 160.0f);
|
||||
|
||||
speedText_.setFont(font_);
|
||||
speedText_.setCharacterSize(36);
|
||||
speedText_.setScale(0.5f, 0.5f);
|
||||
speedText_.setFillColor(sf::Color(220, 220, 220));
|
||||
speedText_.setFillColor(palette.textSecondary);
|
||||
speedText_.setPosition(15.0f, 185.0f);
|
||||
|
||||
controlsText_.setFont(font_);
|
||||
controlsText_.setCharacterSize(30);
|
||||
controlsText_.setScale(0.5f, 0.5f);
|
||||
controlsText_.setFillColor(sf::Color(200, 200, 200));
|
||||
controlsText_.setString("[1-8] Algorithms [Space] Play/Pause [Right] Step [Up/Down] Speed [R] Shuffle");
|
||||
controlsText_.setFillColor(palette.textSecondary);
|
||||
controlsText_.setString("[1-8] Algorithms [Space] Play/Pause [Right] Step [Up/Down] Speed [R] Shuffle [T] Theme");
|
||||
|
||||
leftBackground_.setFillColor(sf::Color(0, 0, 0, 180));
|
||||
rightBackground_.setFillColor(sf::Color(0, 0, 0, 180));
|
||||
leftBackground_.setFillColor(palette.panelBackground);
|
||||
rightBackground_.setFillColor(palette.panelBackground);
|
||||
}
|
||||
|
||||
void UI::update(const Sorter& sorter, bool isPlaying, bool isFinished, int stepsPerFrame, const Array& array) {
|
||||
@@ -69,18 +72,20 @@ void UI::update(const Sorter& sorter, bool isPlaying, bool isFinished, int steps
|
||||
return;
|
||||
}
|
||||
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
algorithmText_.setString("Algorithm: " + sorter.getName());
|
||||
|
||||
std::string state;
|
||||
if (isFinished) {
|
||||
state = "Status: Finished";
|
||||
stateText_.setFillColor(sf::Color::Green);
|
||||
stateText_.setFillColor(palette.statusFinished);
|
||||
} else if (isPlaying) {
|
||||
state = "Status: Playing";
|
||||
stateText_.setFillColor(sf::Color::Yellow);
|
||||
stateText_.setFillColor(palette.statusPlaying);
|
||||
} else {
|
||||
state = "Status: Paused";
|
||||
stateText_.setFillColor(sf::Color::White);
|
||||
stateText_.setFillColor(palette.statusPaused);
|
||||
}
|
||||
stateText_.setString(state);
|
||||
|
||||
@@ -97,6 +102,19 @@ void UI::draw(sf::RenderWindow& window) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
// Обновляем цвета текста и фона при каждой отрисовке (на случай смены темы)
|
||||
algorithmText_.setFillColor(palette.textPrimary);
|
||||
timeComplexityText_.setFillColor(palette.textTertiary);
|
||||
spaceComplexityText_.setFillColor(palette.textTertiary);
|
||||
comparisonsText_.setFillColor(palette.textSecondary);
|
||||
swapsText_.setFillColor(palette.textSecondary);
|
||||
speedText_.setFillColor(palette.textSecondary);
|
||||
controlsText_.setFillColor(palette.textSecondary);
|
||||
leftBackground_.setFillColor(palette.panelBackground);
|
||||
rightBackground_.setFillColor(palette.panelBackground);
|
||||
|
||||
float maxWidth = 0.0f;
|
||||
|
||||
sf::FloatRect algoBounds = algorithmText_.getGlobalBounds();
|
||||
@@ -148,6 +166,8 @@ void UI::drawInfoOverlay(sf::RenderWindow& window) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
auto toSfStr = [](const char* utf8) -> sf::String {
|
||||
std::string s(utf8);
|
||||
return sf::String::fromUtf8(s.begin(), s.end());
|
||||
@@ -158,85 +178,85 @@ void UI::drawInfoOverlay(sf::RenderWindow& window) {
|
||||
|
||||
sf::RectangleShape overlay(sf::Vector2f(windowWidth, windowHeight));
|
||||
overlay.setPosition(0.0f, 0.0f);
|
||||
overlay.setFillColor(sf::Color(8, 10, 18, 230));
|
||||
overlay.setFillColor(palette.overlayBackground);
|
||||
window.draw(overlay);
|
||||
|
||||
sf::Text title;
|
||||
title.setFont(font_);
|
||||
title.setCharacterSize(80);
|
||||
title.setScale(0.5f, 0.5f);
|
||||
title.setFillColor(sf::Color::White);
|
||||
title.setFillColor(palette.overlayTitle);
|
||||
title.setString(toSfStr(u8"SortLab — визуализатор алгоритмов сортировки"));
|
||||
|
||||
sf::Text subtitle;
|
||||
subtitle.setFont(font_);
|
||||
subtitle.setCharacterSize(38);
|
||||
subtitle.setScale(0.5f, 0.5f);
|
||||
subtitle.setFillColor(sf::Color(160, 160, 160));
|
||||
subtitle.setFillColor(palette.overlaySubtitle);
|
||||
subtitle.setString(toSfStr(u8"Учебный инструмент для наглядного изучения алгоритмов сортировки"));
|
||||
|
||||
sf::Text section1;
|
||||
section1.setFont(font_);
|
||||
section1.setCharacterSize(42);
|
||||
section1.setScale(0.5f, 0.5f);
|
||||
section1.setFillColor(sf::Color(0, 220, 255));
|
||||
section1.setFillColor(palette.overlaySection);
|
||||
section1.setString(toSfStr(u8"О программе"));
|
||||
|
||||
sf::Text body1;
|
||||
body1.setFont(font_);
|
||||
body1.setCharacterSize(32);
|
||||
body1.setScale(0.5f, 0.5f);
|
||||
body1.setFillColor(sf::Color(200, 200, 200));
|
||||
body1.setFillColor(palette.overlayBody);
|
||||
body1.setString(toSfStr(u8"SortLab визуализирует работу алгоритмов сортировки в реальном времени.\nКаждый столбик — это элемент массива. Высота = значение элемента.\nЦвета: серый — обычный, голубой — сравнение, оранжевый — перестановка, зелёный — готово."));
|
||||
|
||||
sf::Text section2;
|
||||
section2.setFont(font_);
|
||||
section2.setCharacterSize(42);
|
||||
section2.setScale(0.5f, 0.5f);
|
||||
section2.setFillColor(sf::Color(0, 220, 255));
|
||||
section2.setFillColor(palette.overlaySection);
|
||||
section2.setString(toSfStr(u8"Алгоритмы и сложность"));
|
||||
|
||||
sf::Text body2;
|
||||
body2.setFont(font_);
|
||||
body2.setCharacterSize(32);
|
||||
body2.setScale(0.5f, 0.5f);
|
||||
body2.setFillColor(sf::Color(200, 200, 200));
|
||||
body2.setFillColor(palette.overlayBody);
|
||||
body2.setString(toSfStr(u8"[1] Bubble Sort Время: O(n) / O(n^2) / O(n^2) Память: O(1)\n[2] Selection Sort Время: O(n^2) / O(n^2) / O(n^2) Память: O(1)\n[3] Insertion Sort Время: O(n) / O(n^2) / O(n^2) Память: O(1)\n[4] Merge Sort Время: O(n log n) / O(n log n) / O(n log n) Память: O(n)\n[5] Quick Sort Время: O(n log n) / O(n log n) / O(n^2) Память: O(log n)\n[6] Heap Sort Время: O(n log n) Память: O(1)\n[7] Shell Sort Время: O(n log^2 n) Память: O(1)\n[8] Radix Sort Время: O(n*k) Память: O(n + k)"));
|
||||
|
||||
sf::Text section3;
|
||||
section3.setFont(font_);
|
||||
section3.setCharacterSize(42);
|
||||
section3.setScale(0.5f, 0.5f);
|
||||
section3.setFillColor(sf::Color(0, 220, 255));
|
||||
section3.setFillColor(palette.overlaySection);
|
||||
section3.setString(toSfStr(u8"Гистограмма (внизу слева)"));
|
||||
|
||||
sf::Text body3;
|
||||
body3.setFont(font_);
|
||||
body3.setCharacterSize(32);
|
||||
body3.setScale(0.5f, 0.5f);
|
||||
body3.setFillColor(sf::Color(200, 200, 200));
|
||||
body3.setFillColor(palette.overlayBody);
|
||||
body3.setString(toSfStr(u8"Показывает количество сравнений на каждом шаге сортировки.\nВысокий пик = много сравнений за один шаг.\nBubble Sort даёт ровную линию, Quick Sort — резкие пики в начале."));
|
||||
|
||||
sf::Text section4;
|
||||
section4.setFont(font_);
|
||||
section4.setCharacterSize(42);
|
||||
section4.setScale(0.5f, 0.5f);
|
||||
section4.setFillColor(sf::Color(0, 220, 255));
|
||||
section4.setFillColor(palette.overlaySection);
|
||||
section4.setString(toSfStr(u8"Карта прогресса (внизу справа)"));
|
||||
|
||||
sf::Text body4;
|
||||
body4.setFont(font_);
|
||||
body4.setCharacterSize(32);
|
||||
body4.setScale(0.5f, 0.5f);
|
||||
body4.setFillColor(sf::Color(200, 200, 200));
|
||||
body4.setFillColor(palette.overlayBody);
|
||||
body4.setString(toSfStr(u8"Миниатюрная копия всего массива в виде сетки цветных квадратиков.\nПозволяет видеть глобальный прогресс сортировки даже при большом массиве.\nЗелёные квадраты = отсортированные элементы."));
|
||||
|
||||
sf::Text footer;
|
||||
footer.setFont(font_);
|
||||
footer.setCharacterSize(30);
|
||||
footer.setScale(0.5f, 0.5f);
|
||||
footer.setFillColor(sf::Color(100, 100, 100));
|
||||
footer.setString(toSfStr(u8"Нажми [I] чтобы закрыть | [H] история | [Q] выход | [Space] старт/пауза | [R] перемешать"));
|
||||
footer.setFillColor(palette.overlayFooter);
|
||||
footer.setString(toSfStr(u8"Нажми [I] чтобы закрыть | [H] история | [Q] выход | [Space] старт/пауза | [R] перемешать | [T] тема"));
|
||||
|
||||
float totalHeight = 0.0f;
|
||||
totalHeight += title.getGlobalBounds().height + 10.0f;
|
||||
@@ -328,6 +348,8 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
return;
|
||||
}
|
||||
|
||||
const ColorPalette& palette = Theme::getInstance().getPalette();
|
||||
|
||||
auto toSfStr = [](const char* utf8) -> sf::String {
|
||||
std::string s(utf8);
|
||||
return sf::String::fromUtf8(s.begin(), s.end());
|
||||
@@ -338,14 +360,14 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
|
||||
sf::RectangleShape overlay(sf::Vector2f(windowWidth, windowHeight));
|
||||
overlay.setPosition(0.0f, 0.0f);
|
||||
overlay.setFillColor(sf::Color(8, 10, 18, 230));
|
||||
overlay.setFillColor(palette.overlayBackground);
|
||||
window.draw(overlay);
|
||||
|
||||
sf::Text title;
|
||||
title.setFont(font_);
|
||||
title.setCharacterSize(80);
|
||||
title.setScale(0.5f, 0.5f);
|
||||
title.setFillColor(sf::Color::White);
|
||||
title.setFillColor(palette.overlayTitle);
|
||||
title.setString(toSfStr(u8"История сортировок [H — закрыть]"));
|
||||
|
||||
const auto& records = history.getRecords();
|
||||
@@ -362,7 +384,7 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
emptyText.setFont(font_);
|
||||
emptyText.setCharacterSize(40);
|
||||
emptyText.setScale(0.5f, 0.5f);
|
||||
emptyText.setFillColor(sf::Color(160, 160, 160));
|
||||
emptyText.setFillColor(palette.overlaySubtitle);
|
||||
emptyText.setString(toSfStr(u8"Нет завершённых сортировок"));
|
||||
|
||||
sf::FloatRect emptyBounds = emptyText.getGlobalBounds();
|
||||
@@ -375,7 +397,7 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
header.setFont(font_);
|
||||
header.setCharacterSize(36);
|
||||
header.setScale(0.5f, 0.5f);
|
||||
header.setFillColor(sf::Color(0, 220, 255));
|
||||
header.setFillColor(palette.historyTableHeader);
|
||||
header.setString(toSfStr(u8"Алгоритм Размер Сравнений Свапов Скорость"));
|
||||
|
||||
float tableX = 100.0f;
|
||||
@@ -385,7 +407,7 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
|
||||
sf::RectangleShape separator(sf::Vector2f(windowWidth - 200.0f, 1.0f));
|
||||
separator.setPosition(tableX, startY);
|
||||
separator.setFillColor(sf::Color(60, 70, 90));
|
||||
separator.setFillColor(palette.separator);
|
||||
window.draw(separator);
|
||||
startY += 10.0f;
|
||||
|
||||
@@ -400,11 +422,11 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
rowBg.setPosition(tableX, startY);
|
||||
|
||||
if (isNewest) {
|
||||
rowBg.setFillColor(sf::Color(30, 60, 90, 150));
|
||||
rowBg.setFillColor(palette.historyNewestHighlight);
|
||||
} else if (displayCount % 2 == 1) {
|
||||
rowBg.setFillColor(sf::Color(15, 18, 25, 100));
|
||||
rowBg.setFillColor(palette.historyRowOdd);
|
||||
} else {
|
||||
rowBg.setFillColor(sf::Color(0, 0, 0, 0));
|
||||
rowBg.setFillColor(palette.historyRowEven);
|
||||
}
|
||||
window.draw(rowBg);
|
||||
|
||||
@@ -419,7 +441,7 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
rowText.setFont(font_);
|
||||
rowText.setCharacterSize(32);
|
||||
rowText.setScale(0.5f, 0.5f);
|
||||
rowText.setFillColor(isNewest ? sf::Color(100, 255, 150) : sf::Color(200, 200, 200));
|
||||
rowText.setFillColor(isNewest ? palette.historyNewestText : palette.overlayBody);
|
||||
rowText.setString(algoBuffer);
|
||||
rowText.setPosition(tableX, startY + 2.0f);
|
||||
window.draw(rowText);
|
||||
@@ -433,11 +455,11 @@ void UI::drawHistoryOverlay(sf::RenderWindow& window, const SortHistory& history
|
||||
speedText.setScale(0.5f, 0.5f);
|
||||
|
||||
if (record.relativeSpeed == 1.0f) {
|
||||
speedText.setFillColor(sf::Color(100, 255, 120));
|
||||
speedText.setFillColor(palette.historySpeedFastest);
|
||||
} else if (record.relativeSpeed >= 2.0f) {
|
||||
speedText.setFillColor(sf::Color(255, 160, 60));
|
||||
speedText.setFillColor(palette.historySpeedSlow);
|
||||
} else {
|
||||
speedText.setFillColor(isNewest ? sf::Color(100, 255, 150) : sf::Color(200, 200, 200));
|
||||
speedText.setFillColor(isNewest ? palette.historyNewestText : palette.overlayBody);
|
||||
}
|
||||
|
||||
speedText.setString(speedBuffer);
|
||||
|
||||
Reference in New Issue
Block a user