#include"mx_system_bar.hpp" #include"window.hpp" #include"dimension.hpp" #include"mx_window.hpp" namespace mx { SystemBar::SystemBar(mxApp &app) { dimensions = nullptr; font = TTF_OpenFont(getPath(app.system_font).c_str(), 14); if (!font) { mx::system_err << "Error opening font: " << getPath(app.system_font) << "\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } objects.push_back(std::make_unique<MenuBar>(app)); menu = dynamic_cast<MenuBar *>(objects[0].get()); if(!menu) { mx::system_err << "MasterX System: Bad cast..\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } menu->menuOpen = false; animationComplete = false; yPos = 0; prev_dim = 0; cur_dim = 0; } SystemBar::~SystemBar() { if(font != nullptr) TTF_CloseFont(font); } void SystemBar::addMinimizedWindow(Window *window) { DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get()); if(con != nullptr) { con->mini_win.push_back(window); mx::system_out << "MasterX System: Minimized Window.\n"; } else { mx::system_err << "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 + 30, menu_y + yOffset, text_width, text_height}; SDL_Rect icoRect = {menu_x + 5, menu_y +yOffset, 16 ,16 }; SDL_RenderCopy(app.ren, textTexture, nullptr, &textRect); SDL_RenderCopy(app.ren, win->icon == nullptr ? app.icon : win->icon, nullptr, &icoRect); 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) { int button_height = 0; int bar_height = 0; if (dimensions != nullptr && animationComplete == true) { int activeIndex = 0; bool tcursor = false; int button_width = 150; int button_spacing = 10; int arrow_width = 15; int available_width = app.width - (arrow_width * 2) - (button_spacing * 2); int max_buttons = available_width / (button_width + button_spacing); for (size_t j = bar_offset; j < bar_offset+max_buttons && 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; } button_width = 150; button_height = text_height + 20; 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 + 30, button_y + (button_height - text_height) / 2, text_width, text_height}; SDL_RenderCopy(app.ren, textTexture, nullptr, &textRect); SDL_DestroyTexture(textTexture); textRect.x -= 24; textRect.y -= 2; textRect.w = 20; textRect.h = 20; SDL_RenderCopy(app.ren, dim->icon == nullptr ? app.icon : dim->icon, nullptr, &textRect); 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 (activeIndex > 0) { int arrow_width = 15; int arrow_height = 30; int arrow_y = app.height - bar_height + (bar_height - arrow_height) / 2; int left_arrow_x = 10 + activeIndex * (button_width + 10); drawArrow(app.ren, left_arrow_x, arrow_y, arrow_width, arrow_height, "left"); int right_arrow_x = left_arrow_x + arrow_width + 10; drawArrow(app.ren, right_arrow_x, arrow_y, arrow_width, arrow_height, "right"); } if(tcursor == true) { cursor_shown = true; } } } void SystemBar::drawArrow(SDL_Renderer* ren, int x, int y, int width, int height, const std::string& direction) { SDL_Color gradStart = {192, 192, 192, 255}; SDL_Color gradEnd = {128, 128, 128, 255}; for (int py = y; py < y + height; ++py) { float factor = static_cast<float>(py - y) / height; SDL_Color color = { static_cast<Uint8>(gradStart.r+(factor * (gradEnd.r - gradStart.r))), static_cast<Uint8>(gradStart.g+(factor * (gradEnd.g - gradStart.g))), static_cast<Uint8>(gradStart.b+(factor * (gradEnd.b - gradStart.b))), 255 }; SDL_SetRenderDrawColor(ren, color.r, color.g, color.b, color.a); if (direction == "left") { SDL_RenderDrawLine(ren, x + width, py, x + (py - y) / 2, py); } else if (direction == "right") { SDL_RenderDrawLine(ren, x, py, x + width - (py - y) / 2, py); } } SDL_SetRenderDrawColor(ren, 255, 255, 255, 255); SDL_Rect arrowRect = {x, y, width, height}; SDL_RenderDrawRect(ren, &arrowRect); if(direction == "left") arrowRectLeft = arrowRect; else arrowRectRight = arrowRect; } void SystemBar::setCurrentDimension(int dim) { if(dim != cur_dim) { DimensionContainer *old, *setv; old = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get()); if(!old) { mx::system_err << "MasterX System: Bad cast..\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } setv = dynamic_cast<DimensionContainer *>(dimensions->operator[](dim).get()); if(!setv) { mx::system_err << "MasterX System: Bad cast..\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } prev_dim = cur_dim; cur_dim = dim; if (setv) { setv->setActive(true); setv->setVisible(true); mx::system_out << "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; static Uint32 lastTime = SDL_GetTicks(); if (!animationComplete) { Uint32 currentTime = SDL_GetTicks(); Uint32 deltaTime = currentTime - lastTime; float speed = 0.8f; yPos += speed * deltaTime; if (yPos >= targetYPos) { yPos = targetYPos; animationComplete = true; DimensionContainer *con = dynamic_cast<DimensionContainer *>(dimensions->operator[](cur_dim).get()); if(!con) { mx::system_err << "MasterX System: Bad cast..\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } con->setVisible(true); } lastTime = currentTime; } SDL_Color gradBarStart = {240, 240, 240, 255}; SDL_Color gradBarEnd = {200, 200, 200, 255}; SDL_Rect barRect = {0, animationComplete == true ? app.height- barHeight : 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, animationComplete == true ? app.height - barHeight : 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) { if(e.type == SDL_MOUSEBUTTONDOWN && e.button.button == SDL_BUTTON_LEFT) { SDL_Point p = {e.button.x, e.button.y}; if(SDL_PointInRect(&p, &arrowRectLeft)) { if(bar_offset > 0) { bar_offset--; } return true; } if(SDL_PointInRect(&p, &arrowRectRight)) { int button_width = 150; int button_spacing = 10; int arrow_width = 15; int available_width = app.width - (arrow_width * 2) - (button_spacing * 2); int max_buttons = available_width / (button_width + button_spacing); if ((bar_offset + max_buttons) < activeDimensionsStack.size()) { bar_offset++; } return true; } } 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]); mx::system_out << "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) { mx::system_err << "MasterX System: Bad cast..\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } 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) { mx::system_err << "MasterX System: Bad cast..\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } 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; return true; } 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(!dim) { mx::system_err << "MasterX System: Bad cast..\n"; mx::system_err.flush(); exit(EXIT_FAILURE); } 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: loadDimension(4); break; case 5: { loadDimension(5); } break; case 7: loadDimension(2); break; case 6: loadDimension(6); break; case 8: mx::system_out << "MasterX System: Shutdown signal sent...\n"; app.shutdown(); break; default: mx::system_out << "No valid action\n"; break; } } MenuBar::MenuBar(mxApp &app) { menuOpen = false; currentY = app.height; targetY = app.height / 2; font = TTF_OpenFont(getPath(app.system_font).c_str(), 14); if (!font) { mx::system_err << "Error opening font: " << getPath(app.system_font) << "\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 = 1280 / 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", "MasterPiece", "Asteroids", "Tetris", "About", "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_Rect menuItem8 = {menuX, menuY + 10 + 7 * (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; } else if(SDL_PointInRect(&cursor_pos,&menuItem8)) { return 8; } 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; } }