← index
cplusplus2x.Examples/C++20/MasterX/src/mx_system_bar.cpp
Source: cplusplus2x.Examples/C++20/MasterX/src/mx_system_bar.cpp
#include "mx_system_bar.hpp"

#include "dimension.hpp"

#include "mx_window.hpp"

#include "window.hpp"


namespace mx {

    SystemBar::SystemBar(mxApp &app) {
        dimensions = nullptr;
        font = TTF_OpenFont(getPath("fonts/arial.ttf").c_str(), 14);
        if (!font) {
            std::cerr << "Error opening font: " << getPath("fonts/arial.ttf") << "\n";
            exit(EXIT_FAILURE);
        }
        objects.push_back(std::make_unique<MenuBar>(app));
        menu = dynamic_cast<MenuBar *>(objects[0].get());
        menu->menuOpen = false;
        animationComplete = false;
        yPos = 0;
        prev_dim = 0;
        cur_dim = 0;
    }

    SystemBar::~SystemBar() {
    }

    void SystemBar::addMinimizedWindow(Window *window) {
        DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get());
        if (con != nullptr) {
            con->mini_win.push_back(window);
            std::cout << "MasterX System: Minimized Window.\n";
        } else {
            std::cerr << "MasterX System: Error: Wrong Type\n";
        }
    }

    void SystemBar::restoreWindow(Window *window) {
        if (window->minimized) {
            window->isMinimizing = false;
            window->restoreTargetX = window->originalX;
            window->restoreTargetY = window->originalY;
            window->restoreTargetW = window->originalWidth;
            window->restoreTargetH = window->originalHeight;
            window->restoreAnimationStep = 10;
            window->isRestoring = true;
            window->minimize(false);
            DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get());
            if (con != nullptr) {
                auto w = std::find(con->mini_win.begin(), con->mini_win.end(), window);
                if (w != con->mini_win.end()) {
                    con->mini_win.erase(w);
                }
            }
        }
    }

    void SystemBar::drawMinimizedMenu(mxApp &app, int button_x, int button_y, int button_width) {
        if (!showMinimizedMenu) {
            return;
        }

        DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get());
        if (!con)
            return;

        SDL_Color white = {0xBD, 0, 0, 255};
        SDL_Color darkGray = {160, 160, 160, 255};
        SDL_Color lightGray = {240, 240, 240, 255};
        SDL_Color gradStart = {255, 255, 255, 255};
        SDL_Color gradEnd = {180, 180, 180, 255};

        int menu_width = 150;
        int menu_height = 20 + static_cast<int>(con->mini_win.size()) * 30;

        int menu_x = button_x + (button_width - menu_width) / 2;
        int menu_y = button_y - menu_height - 5;

        for (int y = 0; y < menu_height; ++y) {
            float factor = static_cast<float>(y) / menu_height;
            SDL_Color color;
            color.r = gradStart.r + static_cast<Uint8>(factor * (gradEnd.r - gradStart.r));
            color.g = gradStart.g + static_cast<Uint8>(factor * (gradEnd.g - gradStart.g));
            color.b = gradStart.b + static_cast<Uint8>(factor * (gradEnd.b - gradStart.b));
            color.a = 255;

            SDL_SetRenderDrawColor(app.ren, color.r, color.g, color.b, color.a);
            SDL_RenderDrawLine(app.ren, menu_x, menu_y + y, menu_x + menu_width, menu_y + y);
        }

        SDL_SetRenderDrawColor(app.ren, lightGray.r, lightGray.g, lightGray.b, 255);
        SDL_RenderDrawLine(app.ren, menu_x, menu_y, menu_x + menu_width, menu_y);  // Top border

        SDL_RenderDrawLine(app.ren, menu_x, menu_y, menu_x, menu_y + menu_height); // Left border


        SDL_SetRenderDrawColor(app.ren, darkGray.r, darkGray.g, darkGray.b, 255);
        SDL_RenderDrawLine(app.ren, menu_x, menu_y + menu_height, menu_x + menu_width, menu_y + menu_height); // Bottom border

        SDL_RenderDrawLine(app.ren, menu_x + menu_width, menu_y, menu_x + menu_width, menu_y + menu_height);  // Right border


        int yOffset = 20;
        for (size_t i = 0; i < con->mini_win.size(); ++i) {
            Window *win = con->mini_win[i];
            if (menuHover == true && hoverIndex == static_cast<int>(i))
                TTF_SetFontStyle(font, TTF_STYLE_UNDERLINE);
            SDL_Surface *textSurface = TTF_RenderText_Blended(font, win->title.c_str(), white);
            TTF_SetFontStyle(font, TTF_STYLE_NORMAL);
            SDL_Texture *textTexture = SDL_CreateTextureFromSurface(app.ren, textSurface);
            int text_width = textSurface->w;
            int text_height = textSurface->h;
            SDL_FreeSurface(textSurface);
            SDL_Rect textRect = {menu_x + 10, menu_y + yOffset, text_width, text_height};
            SDL_RenderCopy(app.ren, textTexture, nullptr, &textRect);
            SDL_DestroyTexture(textTexture);
            yOffset += 30;
        }
    }

    void SystemBar::setDimensions(std::vector<std::unique_ptr<Screen>> *dim) {
        dimensions = dim;
    }

    void SystemBar::activateDimension(int dim) {
        auto it = std::find(activeDimensionsStack.begin(), activeDimensionsStack.end(), dim);
        ;
        if (it != activeDimensionsStack.end()) {
            activeDimensionsStack.erase(it);
        }
        activeDimensionsStack.push_back(dim);
    }

    void SystemBar::deactivateDimension(int dim) {
        auto it = std::find(activeDimensionsStack.begin(), activeDimensionsStack.end(), dim);
        if (it != activeDimensionsStack.end()) {
            activeDimensionsStack.erase(it);
        }
    }

    void SystemBar::drawDimensions(mxApp &app) {
        if (dimensions != nullptr && animationComplete == true) {
            int activeIndex = 0;
            bool tcursor = false;
            for (size_t j = 0; j < activeDimensionsStack.size(); ++j) {
                int i = activeDimensionsStack[j];
                DimensionContainer *dim = dynamic_cast<DimensionContainer *>(dimensions->operator[](i).get());

                if (dim != nullptr && dim->isActive()) {

                    const std::string &name = dim->name;
                    SDL_Color white = {255, 255, 255, 255};
                    SDL_Surface *textSurface = TTF_RenderText_Blended(font, name.c_str(), white);
                    if (textSurface == nullptr) {
                        continue;
                    }

                    SDL_Texture *textTexture = SDL_CreateTextureFromSurface(app.ren, textSurface);
                    int text_width = textSurface->w;
                    int text_height = textSurface->h;
                    SDL_FreeSurface(textSurface);
                    if (textTexture == nullptr) {
                        continue;
                    }

                    int button_width = 150;
                    int button_height = text_height + 20;
                    int bar_height = 50;
                    int button_y = (bar_height - button_height) / 2 + app.height - bar_height;

                    int button_x = 10 + activeIndex * (button_width + 10);
                    activeIndex++;

                    SDL_Color gradStart, gradEnd;

                    if (static_cast<int>(i) == cur_dim) {
                        gradStart = {0, 0, 255, 255};
                        gradEnd = {0, 0, 139, 255};
                    } else {
                        gradStart = {192, 192, 192, 255};
                        gradEnd = {128, 128, 128, 255};
                    }

                    SDL_Rect buttonRect = {button_x, button_y, button_width, button_height};

                    for (int y = buttonRect.y; y < buttonRect.y + buttonRect.h; ++y) {
                        float factor = static_cast<float>(y - buttonRect.y) / buttonRect.h;
                        SDL_Color color;
                        color.r = gradStart.r + static_cast<Uint8>(factor * (gradEnd.r - gradStart.r));
                        color.g = gradStart.g + static_cast<Uint8>(factor * (gradEnd.g - gradStart.g));
                        color.b = gradStart.b + static_cast<Uint8>(factor * (gradEnd.b - gradStart.b));
                        color.a = 255;

                        SDL_SetRenderDrawColor(app.ren, color.r, color.g, color.b, color.a);
                        SDL_RenderDrawLine(app.ren, buttonRect.x, y, buttonRect.x + buttonRect.w, y);
                    }

                    SDL_SetRenderDrawColor(app.ren, 255, 255, 255, 255);
                    SDL_RenderDrawRect(app.ren, &buttonRect);

                    SDL_Rect textRect = {button_x + 10, button_y + (button_height - text_height) / 2, text_width, text_height};
                    SDL_RenderCopy(app.ren, textTexture, nullptr, &textRect);
                    SDL_DestroyTexture(textTexture);

                    if (i == cur_dim && dim->mini_win.size() > 0 && showMinimizedMenu) {
                        drawMinimizedMenu(app, button_x, button_y, button_width);
                    }

                    if (dim->name != "Dashboard") {
                        int square_size = 20;
                        int square_x = button_x + button_width - square_size - 5;
                        int square_y = button_y + (button_height - square_size) / 2;

                        SDL_SetRenderDrawColor(app.ren, 200, 200, 200, 255);
                        SDL_Rect closeButtonRect = {square_x, square_y, square_size, square_size};
                        if (dim->hoveringX) {
                            SDL_SetRenderDrawColor(app.ren, 0xBD, 0, 0, 255);
                            tcursor = true;
                        }
                        SDL_RenderFillRect(app.ren, &closeButtonRect);

                        SDL_SetRenderDrawColor(app.ren, 255, 255, 255, 255);
                        SDL_RenderDrawRect(app.ren, &closeButtonRect);

                        SDL_Color black = {0, 0, 0, 255};
                        SDL_Surface *xSurface = TTF_RenderText_Blended(font, "X", black);
                        if (xSurface != nullptr) {
                            SDL_Texture *xTexture = SDL_CreateTextureFromSurface(app.ren, xSurface);
                            int x_width = xSurface->w;
                            int x_height = xSurface->h;
                            SDL_FreeSurface(xSurface);

                            SDL_Rect xRect = {square_x + (square_size - x_width) / 2, square_y + (square_size - x_height) / 2, x_width, x_height};
                            SDL_RenderCopy(app.ren, xTexture, nullptr, &xRect);
                            SDL_DestroyTexture(xTexture);
                        }
                    }
                }
            }
            if (tcursor == true) {
                cursor_shown = true;
            }
        }
    }
    void SystemBar::setCurrentDimension(int dim) {
        if (dim != cur_dim) {
            DimensionContainer *old, *setv;
            old = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get());
            setv = dynamic_cast<DimensionContainer *>(dimensions->operator[](dim).get());
            prev_dim = cur_dim;
            cur_dim = dim;
            if (setv) {
                setv->setActive(true);
                setv->setVisible(true);
                std::cout << "MasterX System: Switching from: " << old->name << " to " << setv->name << "\n";
                setv->startTransition(old ? old->wallpaper : nullptr);
            }
        }
    }

    int SystemBar::getCurrentDimension() const {
        return cur_dim;
    }

    void SystemBar::draw(mxApp &app) {
        int barHeight = 50;
        int windowWidth = app.width;
        int windowHeight = app.height;
        int targetYPos = windowHeight - barHeight;
        int startButtonSize = 100;
        if (!animationComplete) {
            yPos += 5;
            if (yPos >= targetYPos) {
                yPos = targetYPos;
                animationComplete = true;
                DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get());
                con->setVisible(true);
            }
        }

        SDL_Color gradBarStart = {240, 240, 240, 255};
        SDL_Color gradBarEnd = {200, 200, 200, 255};
        SDL_Rect barRect = {0, yPos, windowWidth, barHeight};
        for (int y = 0; y < barHeight; ++y) {
            float factor = static_cast<float>(y) / barHeight;
            SDL_Color color;
            color.r = gradBarStart.r + static_cast<Uint8>(factor * (gradBarEnd.r - gradBarStart.r));
            color.g = gradBarStart.g + static_cast<Uint8>(factor * (gradBarEnd.g - gradBarStart.g));
            color.b = gradBarStart.b + static_cast<Uint8>(factor * (gradBarEnd.b - gradBarStart.b));
            color.a = 255;

            SDL_SetRenderDrawColor(app.ren, color.r, color.g, color.b, color.a);
            SDL_RenderDrawLine(app.ren, barRect.x, barRect.y + y, barRect.x + barRect.w, barRect.y + y);
        }

        SDL_Color lightBevel = {255, 255, 255, 255};
        SDL_Color darkBevel = {128, 128, 128, 255};

        SDL_SetRenderDrawColor(app.ren, lightBevel.r, lightBevel.g, lightBevel.b, lightBevel.a);
        SDL_RenderDrawLine(app.ren, barRect.x, barRect.y, barRect.x + barRect.w, barRect.y);
        SDL_RenderDrawLine(app.ren, barRect.x, barRect.y, barRect.x, barRect.y + barRect.h);

        SDL_SetRenderDrawColor(app.ren, darkBevel.r, darkBevel.g, darkBevel.b, darkBevel.a);
        SDL_RenderDrawLine(app.ren, barRect.x, barRect.y + barRect.h - 1, barRect.x + barRect.w - 1, barRect.y + barRect.h - 1);
        SDL_RenderDrawLine(app.ren, barRect.x + barRect.w - 1, barRect.y, barRect.x + barRect.w - 1, barRect.y + barRect.h - 1);

        SDL_Color buttonColor = {169, 169, 169, 255};
        SDL_Color textColor = {0, 0, 0, 255};

        if (isHovering) {
            buttonColor = {0, 0, 139, 255};
            textColor = {255, 255, 255, 255};
            cursor_shown = true;
        }
        SDL_Rect startButton = {windowWidth - startButtonSize, yPos, startButtonSize, barHeight};

        if (isHovering) {
            SDL_Color gradStart = {0, 0, 255, 255};
            SDL_Color gradEnd = {0, 0, 139, 255};

            for (int y = 0; y < startButton.h; ++y) {

                float factor = static_cast<float>(y) / startButton.h;
                SDL_Color color;
                color.r = gradStart.r + static_cast<Uint8>(factor * (gradEnd.r - gradStart.r));
                color.g = gradStart.g + static_cast<Uint8>(factor * (gradEnd.g - gradStart.g));
                color.b = gradStart.b + static_cast<Uint8>(factor * (gradEnd.b - gradStart.b));
                color.a = 255;

                SDL_SetRenderDrawColor(app.ren, color.r, color.g, color.b, color.a);
                SDL_RenderDrawLine(app.ren, startButton.x, startButton.y + y, startButton.x + startButton.w, startButton.y + y);
            }
        } else {
            SDL_Color gradStart = {192, 192, 192, 255};
            SDL_Color gradEnd = {128, 128, 128, 255};

            for (int y = 0; y < startButton.h; ++y) {
                float factor = static_cast<float>(y) / startButton.h;
                SDL_Color color;
                color.r = gradStart.r + static_cast<Uint8>(factor * (gradEnd.r - gradStart.r));
                color.g = gradStart.g + static_cast<Uint8>(factor * (gradEnd.g - gradStart.g));
                color.b = gradStart.b + static_cast<Uint8>(factor * (gradEnd.b - gradStart.b));
                color.a = 255;

                SDL_SetRenderDrawColor(app.ren, color.r, color.g, color.b, color.a);
                SDL_RenderDrawLine(app.ren, startButton.x, startButton.y + y, startButton.x + startButton.w, startButton.y + y);
            }
        }

        SDL_SetRenderDrawColor(app.ren, 255, 255, 255, 255);
        SDL_RenderDrawLine(app.ren, startButton.x, startButton.y, startButton.x + startButton.w - 1, startButton.y);
        SDL_RenderDrawLine(app.ren, startButton.x, startButton.y, startButton.x, startButton.y + startButton.h - 1);

        SDL_SetRenderDrawColor(app.ren, 128, 128, 128, 255);
        SDL_RenderDrawLine(app.ren, startButton.x, startButton.y + startButton.h - 1, startButton.x + startButton.w - 1, startButton.y + startButton.h - 1);
        SDL_RenderDrawLine(app.ren, startButton.x + startButton.w - 1, startButton.y, startButton.x + startButton.w - 1, startButton.y + startButton.h - 1);

        SDL_Surface *textSurface = TTF_RenderText_Blended(font, "Launch", textColor);
        SDL_Texture *textTexture = SDL_CreateTextureFromSurface(app.ren, textSurface);

        int textWidth = textSurface->w;
        int textHeight = textSurface->h;
        SDL_FreeSurface(textSurface);

        SDL_Rect textRect = {
            startButton.x + (startButton.w - textWidth) / 2,
            startButton.y + (startButton.h - textHeight) / 2,
            textWidth,
            textHeight};

        SDL_RenderCopy(app.ren, textTexture, nullptr, &textRect);
        SDL_DestroyTexture(textTexture);

        drawDimensions(app);
        SDL_SetRenderTarget(app.ren, nullptr);

        for (auto &i : objects) {
            i->draw(app);
        }

        if (menuHover) {
            cursor_shown = true;
        }
    }

    bool SystemBar::empty() const {
        return activeDimensionsStack.empty();
    }

    bool SystemBar::event(mxApp &app, SDL_Event &e) {

        DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get());
        if (!con) {
            return false;
        }

        int dpos = 0;

        for (auto &i : activeDimensionsStack) {
            if (i == cur_dim)
                break;
            dpos++;
        }

        int button_width = 150;
        int button_y = app.height - 50;
        int button_x = 10 + dpos * (button_width + 10);
        int menu_width = 150;
        int menu_height = 20 + static_cast<int>(con->mini_win.size()) * 30;
        int menu_x = button_x + (button_width - menu_width) / 2;
        int menu_y = button_y - menu_height - 5;
        bool chover = false;
        hoverIndex = -1;

        if (showMinimizedMenu && e.type == SDL_MOUSEMOTION) {
            int mouseX = e.motion.x;
            int mouseY = e.motion.y;
            SDL_Rect menuRect = {menu_x, menu_y, menu_width, menu_height};
            SDL_Point rc = {mouseX, mouseY};
            if (SDL_PointInRect(&rc, &menuRect)) {
                int yOffset = 20;
                for (size_t i = 0; i < con->mini_win.size(); ++i) {
                    SDL_Rect textRect = {menu_x + 10, menu_y + yOffset, 180, 20};
                    if (SDL_PointInRect(&rc, &textRect)) {
                        chover = true;
                        hoverIndex = static_cast<int>(i);
                        break;
                    }
                    yOffset += 30;
                }
            }
        }

        menuHover = chover;

        if (showMinimizedMenu && e.type == SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT) {
            int mouseX = e.button.x;
            int mouseY = e.button.y;
            SDL_Rect menuRect = {menu_x, menu_y, menu_width, menu_height};
            SDL_Point rc = {mouseX, mouseY};
            if (SDL_PointInRect(&rc, &menuRect)) {
                int yOffset = 20;
                for (size_t i = 0; i < con->mini_win.size(); ++i) {
                    SDL_Rect textRect = {menu_x + 10, menu_y + yOffset, 180, 20};
                    if (SDL_PointInRect(&rc, &textRect)) {
                        restoreWindow(con->mini_win[i]);
                        std::cout << "MasterX System: Restored Window\n";
                        showMinimizedMenu = false;
                        return true;
                    }
                    yOffset += 30;
                }
            } else {
                showMinimizedMenu = false;
            }
        }

        if (e.type == SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_RIGHT) {
            int mouseX = e.button.x;
            int mouseY = e.button.y;

            int button_width = 150;
            int button_height = 30;
            int button_y = app.height - 50;

            for (int j = 0; j < static_cast<int>(activeDimensionsStack.size()); ++j) {
                int button_x = 10 + j * (button_width + 10);
                SDL_Rect buttonRect = {button_x, button_y, button_width, button_height};
                SDL_Point mousePoint = {mouseX, mouseY};

                if (SDL_PointInRect(&mousePoint, &buttonRect)) {
                    if (holdingDimension) {
                        Uint32 holdTime = SDL_GetTicks() - holdStartTime;
                        if (holdTime > 500) {
                            showMinimizedMenu = true;
                            holdingDimension = false;
                        }
                    } else {
                        showMinimizedMenu = !showMinimizedMenu;
                    }
                    break;
                }
            }
        }

        if (e.type == SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT) {
            int mouseX = e.button.x;
            int mouseY = e.button.y;
            bool clickedOutside = true;

            int button_width = 150;
            int button_height = 30;
            int button_y = app.height - 50;

            for (int j = 0; j < static_cast<int>(activeDimensionsStack.size()); ++j) {
                int button_x = 10 + j * (button_width + 10);
                SDL_Rect buttonRect = {button_x, button_y, button_width, button_height};
                SDL_Point mousePoint = {mouseX, mouseY};

                if (SDL_PointInRect(&mousePoint, &buttonRect)) {
                    clickedOutside = false;
                    break;
                }
            }

            SDL_Point mousePoint = {mouseX, mouseY};
            SDL_Rect menuRect = {menu_x, menu_y, menu_width, menu_height};
            if (SDL_PointInRect(&mousePoint, &menuRect)) {
                clickedOutside = false;
            }

            if (clickedOutside) {
                showMinimizedMenu = false;
            }
        }

        if (e.type == SDL_MOUSEMOTION) {

            int mouseX = e.motion.x;
            int mouseY = e.motion.y;
            int barHeight = 50;
            int button_height = 30;
            int button_y = app.height - barHeight;
            int button_width = 150;
            int square_size = 20;
            int activeIndex = 0;

            if (dimensions != nullptr) {
                for (size_t j = 0; j < activeDimensionsStack.size(); ++j) {
                    int i = activeDimensionsStack[j];
                    DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](i).get());
                    if (con->isActive()) {
                        int button_x = 10 + activeIndex * (button_width + 10);
                        activeIndex++;
                        SDL_Rect closeButtonRect = {button_x + button_width - square_size - 5, button_y + (button_height - square_size) / 2, square_size, square_size};
                        SDL_Point cur_point{mouseX, mouseY};
                        if (con->name != "Dashboard" && SDL_PointInRect(&cur_point, &closeButtonRect)) {
                            con->hoveringX = true;
                        } else {
                            con->hoveringX = false;
                        }
                    }
                }
            }
        }

        if (e.type == SDL_MOUSEMOTION) {
            int mouseX = e.motion.x;
            int mouseY = e.motion.y;
            int barHeight = 50;
            int startButtonSize = 100;
            int windowWidth = app.width;
            int targetYPos = app.height - barHeight;

            SDL_Rect startButtonRect = {windowWidth - startButtonSize, targetYPos, startButtonSize, barHeight};

            if (mouseX >= startButtonRect.x && mouseX <= (startButtonRect.x + startButtonRect.w) &&
                mouseY >= startButtonRect.y && mouseY <= (startButtonRect.y + startButtonRect.h)) {
                isHovering = true;
            } else {
                isHovering = false;
            }
        } else if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_LEAVE) {
            isHovering = false;
            menuHover = false;
            return true;
        }

        if (e.type == SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT) {
            if (holdingDimension) {
                Uint32 holdTime = SDL_GetTicks() - holdStartTime;

                if (holdTime > 500) {
                    showMinimizedMenu = true;
                }

                holdingDimension = false;
                return true;
            }
        }

        if (e.type == SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT) {
            int mouseX = e.button.x;
            int mouseY = e.button.y;
            int barHeight = 50;
            int startButtonSize = 100;
            int windowWidth = app.width;
            int targetYPos = app.height - barHeight;

            SDL_Rect startButtonRect = {windowWidth - startButtonSize, targetYPos, startButtonSize, barHeight};
            SDL_Point mousePos = {mouseX, mouseY};
            if (SDL_PointInRect(&mousePos, &startButtonRect)) {
                menu->menuOpen = !menu->menuOpen;
                menu->animating = true;
                if (menu->menuOpen) {
                    menu->currentY = targetYPos - barHeight;
                    menu->targetY = targetYPos - (app.height / 2);
                } else {
                    menu->currentY = targetYPos - (app.height / 2);
                    menu->targetY = targetYPos - barHeight;
                }
                return true;
            }

            if (dimensions != nullptr) {
                int button_width = 150;
                int button_height = 30;
                int button_y = app.height - barHeight;
                int activeIndex = 0;
                for (size_t j = 0; j < activeDimensionsStack.size(); ++j) {
                    int i = activeDimensionsStack[j];
                    DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](i).get());
                    if (con->isActive()) {
                        int button_x = 10 + activeIndex * (button_width + 10);
                        activeIndex++;
                        int square_size = 20;
                        SDL_Rect closeButtonRect = {button_x + button_width - square_size - 5, button_y + (button_height - square_size) / 2, square_size, square_size};
                        SDL_Point cur_point = {mouseX, mouseY};
                        if (con->name != "Dashboard" && SDL_PointInRect(&cur_point, &closeButtonRect)) {
                            con->setActive(false);
                            if (i == cur_dim) {
                                deactivateDimension(i);
                                prev_dim = 0;
                                setCurrentDimension(0);
                            } else {
                                deactivateDimension(i);
                            }
                            return true;
                        } else {
                            SDL_Rect buttonRect = {button_x, button_y, button_width, button_height};
                            if (mouseX >= buttonRect.x && mouseX <= (buttonRect.x + buttonRect.w) &&
                                mouseY >= buttonRect.y && mouseY <= (buttonRect.y + buttonRect.h)) {
                                if (getCurrentDimension() != i) {
                                    setCurrentDimension(i);
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            int action = menu->itemClicked(app, mouseX, mouseY);
            if (action != -1) {
                performAction(app, action);
                menu->menuOpen = false;
                menu->animating = true;
                menu->targetY = app.height;
            } else if (menu->menuOpen) {
                int menuX = app.width - (app.width / 6) - 20;
                int menuY = menu->currentY;
                int menuWidth = app.width / 6;
                int menuHeight = app.height / 2;

                SDL_Rect menuRect = {menuX, menuY, menuWidth, menuHeight};

                if (mouseX >= menuRect.x && mouseX <= (menuRect.x + menuRect.w) &&
                    mouseY >= menuRect.y && mouseY <= (menuRect.y + menuRect.h)) {
                    return false;
                }
                menu->menuOpen = false;
                menu->animating = true;
                menu->targetY = app.height;
                return true;
            }
        }

        for (auto &i : objects) {
            if (i->event(app, e))
                return true;
        }

        return false;
    }

    void SystemBar::loadDimension(int id) {
        DimensionContainer *dim = dynamic_cast<DimensionContainer *>(dimensions->operator[](id).get());
        if (std::find(activeDimensionsStack.begin(), activeDimensionsStack.end(), id) == activeDimensionsStack.end()) {
            dim->setActive(true);
            setCurrentDimension(id);
            activateDimension(id);
        } else {
            dim->setActive(true);
            setCurrentDimension(id);
        }
    }

    void SystemBar::performAction(mxApp &app, int action) {
        switch (action) {
        case 1: {
            loadDimension(1);
        } break;
        case 2: {
            loadDimension(3);
        } break;
        case 3: {
            loadDimension(0);

        } break;
        case 4:
            std::cout << "Find clicked\n";
            break;
        case 5: {
            loadDimension(2);
        } break;
        case 6:
            std::cout << "Run clicked\n";
            break;
        case 7:
            std::cout << "MasterX System: Shutdown signal sent...\n";
            app.shutdown();
            break;
        default:
            std::cout << "No valid action\n";
            break;
        }
    }

    MenuBar::MenuBar(mxApp &app) {
        menuOpen = false;
        currentY = app.height;
        targetY = app.height / 2;
        font = TTF_OpenFont(getPath("fonts/arial.ttf").c_str(), 14);
        if (!font) {
            std::cerr << "Error opening font: " << getPath("fonts/arial.ttf") << "\n";
            exit(EXIT_FAILURE);
        }
        white = {255, 255, 255, 255};
        itemTexture = nullptr;
        itemSurface = nullptr;
        animating = false;
    }

    MenuBar::~MenuBar() {
        // TTF_CloseFont(font);

    }

    void MenuBar::draw(mxApp &app) {
        if (!menuOpen && !animating) {
            return;
        }

        if (animating) {
            if (menuOpen) {
                currentY -= 30;
                if (currentY <= targetY) {
                    currentY = targetY;
                    animating = false;
                }
            } else {
                currentY += 30;
                if (currentY >= targetY) {
                    currentY = targetY;
                    animating = false;
                }
            }
        }

        int menuWidth = app.width / 6;
        int menuHeight = app.height / 2;
        int menuX = app.width - menuWidth - 20;

        SDL_SetRenderTarget(app.ren, app.tex);

        SDL_Color hoverColor = {0, 0, 128, 255};
        SDL_SetRenderDrawColor(app.ren, hoverColor.r, hoverColor.g, hoverColor.b, hoverColor.a);
        SDL_Rect rightSideRect = {menuX + menuWidth, currentY, 20, menuHeight};
        SDL_RenderFillRect(app.ren, &rightSideRect);

        int gradientHeight = menuHeight;
        for (int i = 0; i < gradientHeight; i++) {
            int grayValue = 192 - (64 * i / gradientHeight);
            SDL_SetRenderDrawColor(app.ren, grayValue, grayValue, grayValue, 255);
            SDL_RenderDrawLine(app.ren, menuX, currentY + i, menuX + menuWidth, currentY + i);
        }

        SDL_SetRenderDrawColor(app.ren, 128, 128, 128, 255);
        SDL_Rect menuRect = {menuX, currentY, menuWidth, menuHeight};
        SDL_RenderDrawRect(app.ren, &menuRect);

        SDL_Color black = {0, 0, 0, 255};
        SDL_Color white = {255, 255, 255, 255};

        const char *items[] = {"Welcome", "Terminal", "Settings", "Find", "About", "Run", "Shutdown"};
        int numItems = sizeof(items) / sizeof(items[0]);
        int itemHeight = 30;
        SDL_Rect itemRect;

        bool tcursor = false;

        for (int i = 0; i < numItems; i++) {
            itemRect = {menuX + 10, currentY + 10 + i * (itemHeight + 5), menuWidth - 20, itemHeight};

            int mouseX, mouseY;
            SDL_GetMouseState(&mouseX, &mouseY);
            SDL_Point cursor_pos = {mouseX, mouseY};
            bool isHovering = SDL_PointInRect(&cursor_pos, &itemRect);

            if (isHovering) {
                SDL_SetRenderDrawColor(app.ren, hoverColor.r, hoverColor.g, hoverColor.b, hoverColor.a);
                SDL_RenderFillRect(app.ren, &itemRect);
                tcursor = true;
            } else {
                SDL_SetRenderDrawColor(app.ren, 192, 192, 192, 255);
                SDL_RenderFillRect(app.ren, &itemRect);
            }

            SDL_SetRenderDrawColor(app.ren, 128, 128, 128, 255);
            SDL_RenderDrawRect(app.ren, &itemRect);

            SDL_Color textColor = isHovering ? white : black;
            SDL_Surface *textSurface = TTF_RenderText_Blended(font, items[i], textColor);
            SDL_Texture *textTexture = SDL_CreateTextureFromSurface(app.ren, textSurface);
            int textWidth = textSurface->w;
            int textHeight = textSurface->h;
            SDL_FreeSurface(textSurface);

            SDL_Rect textRect = {itemRect.x + (itemRect.w - textWidth) / 2, itemRect.y + (itemRect.h - textHeight) / 2, textWidth, textHeight};
            SDL_RenderCopy(app.ren, textTexture, nullptr, &textRect);
            SDL_DestroyTexture(textTexture);
        }

        if (tcursor == true) {
            cursor_shown = true;
        }

        SDL_SetRenderTarget(app.ren, nullptr);
    }
    int MenuBar::itemClicked(mxApp &app, int x, int y) {
        int menuX = app.width - (app.width / 6) - 20;
        int menuY = currentY;
        int itemHeight = 30;
        int menuWidth = app.width / 6;

        SDL_Rect menuItem1 = {menuX, menuY + 10, menuWidth, itemHeight};
        SDL_Rect menuItem2 = {menuX, menuY + 10 + (itemHeight + 5), menuWidth, itemHeight};
        SDL_Rect menuItem3 = {menuX, menuY + 10 + 2 * (itemHeight + 5), menuWidth, itemHeight};
        SDL_Rect menuItem4 = {menuX, menuY + 10 + 3 * (itemHeight + 5), menuWidth, itemHeight};
        SDL_Rect menuItem5 = {menuX, menuY + 10 + 4 * (itemHeight + 5), menuWidth, itemHeight};
        SDL_Rect menuItem6 = {menuX, menuY + 10 + 5 * (itemHeight + 5), menuWidth, itemHeight};
        SDL_Rect menuItem7 = {menuX, menuY + 10 + 6 * (itemHeight + 5), menuWidth, itemHeight};

        SDL_Point cursor_pos = {x, y};

        if (SDL_PointInRect(&cursor_pos, &menuItem1)) {
            return 1;
        } else if (SDL_PointInRect(&cursor_pos, &menuItem2)) {
            return 2;
        } else if (SDL_PointInRect(&cursor_pos, &menuItem3)) {
            return 3;
        } else if (SDL_PointInRect(&cursor_pos, &menuItem4)) {
            return 4;
        } else if (SDL_PointInRect(&cursor_pos, &menuItem5)) {
            return 5;
        } else if (SDL_PointInRect(&cursor_pos, &menuItem6)) {
            return 6;
        } else if (SDL_PointInRect(&cursor_pos, &menuItem7)) {
            return 7;
        }
        return -1;
    }

    bool MenuBar::event(mxApp &app, SDL_Event &e) {

        if (e.type == SDL_WINDOWEVENT) {
            if (e.window.event == SDL_WINDOWEVENT_LEAVE) {
                this->animating = false;
                this->menuOpen = true;
                return false;
            }
        }

        return false;
    }

} // namespace mx