diff --git a/examples/floating_window/floating_window.c b/examples/floating_window/floating_window.c new file mode 100644 index 0000000..b6b7058 --- /dev/null +++ b/examples/floating_window/floating_window.c @@ -0,0 +1,146 @@ +#include "raylib.h" + +#define RAYGUI_IMPLEMENTATION +#include "../../raygui.h" + +#include "../../styles/dark/style_dark.h" + +static Vector2 window_position = { 10, 10 }; +static Vector2 window_size = { 200, 400 }; +static bool minimized = false; +static bool moving = false; +static bool resizing = false; +static Vector2 scroll; + +static Vector2 window2_position = { 250, 10 }; +static Vector2 window2_size = { 200, 400 }; +static bool minimized2 = false; +static bool moving2 = false; +static bool resizing2 = false; +static Vector2 scroll2; + +void GuiWindowFloating(Vector2 *position, Vector2 *size, bool *minimized, bool *moving, bool *resizing, void (*draw_content)(Vector2, Vector2), Vector2 content_size, Vector2 *scroll, const char* title) { + #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT) + #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24 + #endif + + #if !defined(RAYGUI_WINDOW_CLOSEBUTTON_SIZE) + #define RAYGUI_WINDOW_CLOSEBUTTON_SIZE 18 + #endif + + int close_title_size_delta_half = (RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_WINDOW_CLOSEBUTTON_SIZE) / 2; + + // window movement and resize input and collision check + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && !*moving && !*resizing) { + Vector2 mouse_position = GetMousePosition(); + + Rectangle title_collision_rect = { position->x, position->y, size->x - (RAYGUI_WINDOW_CLOSEBUTTON_SIZE + close_title_size_delta_half), RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + Rectangle resize_collision_rect = { position->x + size->x - 20, position->y + size->y - 20, 20, 20 }; + + if(CheckCollisionPointRec(mouse_position, title_collision_rect)) { + *moving = true; + } else if(!*minimized && CheckCollisionPointRec(mouse_position, resize_collision_rect)) { + *resizing = true; + } + } + + // window movement and resize update + if(*moving) { + Vector2 mouse_delta = GetMouseDelta(); + position->x += mouse_delta.x; + position->y += mouse_delta.y; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) { + *moving = false; + + // clamp window position keep it inside the application area + if(position->x < 0) position->x = 0; + else if(position->x > GetScreenWidth() - size->x) position->x = GetScreenWidth() - size->x; + if(position->y < 0) position->y = 0; + else if(position->y > GetScreenHeight()) position->y = GetScreenHeight() - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT; + } + + } else if(*resizing) { + Vector2 mouse_delta = GetMouseDelta(); + size->x += mouse_delta.x; + size->y += mouse_delta.y; + + // clamp window size to an arbitrary minimum value and the window size as the maximum + if(size->x < 100) size->x = 100; + else if(size->x > GetScreenWidth()) size->x = GetScreenWidth(); + if(size->y < 100) size->y = 100; + else if(size->y > GetScreenHeight()) size->y = GetScreenHeight(); + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) { + *resizing = false; + } + } + + // window and content drawing with scissor and scroll area + if(*minimized) { + GuiStatusBar((Rectangle){ position->x, position->y, size->x, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }, title); + + if (GuiButton((Rectangle){ position->x + size->x - RAYGUI_WINDOW_CLOSEBUTTON_SIZE - close_title_size_delta_half, + position->y + close_title_size_delta_half, + RAYGUI_WINDOW_CLOSEBUTTON_SIZE, + RAYGUI_WINDOW_CLOSEBUTTON_SIZE }, + "#120#")) { + *minimized = false; + } + + } else { + *minimized = GuiWindowBox((Rectangle) { position->x, position->y, size->x, size->y }, title); + + // scissor and draw content within a scroll panel + if(draw_content != NULL) { + Rectangle scissor = { 0 }; + GuiScrollPanel((Rectangle) { position->x, position->y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, size->x, size->y - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }, + NULL, + (Rectangle) { position->x, position->y, content_size.x, content_size.y }, + scroll, + &scissor); + + bool require_scissor = size->x < content_size.x || size->y < content_size.y; + + if(require_scissor) { + BeginScissorMode(scissor.x, scissor.y, scissor.width, scissor.height); + } + + draw_content(*position, *scroll); + + if(require_scissor) { + EndScissorMode(); + } + } + + // draw the resize button/icon + GuiDrawIcon(71, position->x + size->x - 20, position->y + size->y - 20, 1, WHITE); + } +} + +static void DrawContent(Vector2 position, Vector2 scroll) { + GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 50 + scroll.y, 100, 25 }, "Button 1"); + GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 100 + scroll.y, 100, 25 }, "Button 2"); + GuiButton((Rectangle) { position.x + 20 + scroll.x, position.y + 150 + scroll.y, 100, 25 }, "Button 3"); + GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 200 + scroll.y, 250, 25 }, "A Label"); + GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 250 + scroll.y, 250, 25 }, "Another Label"); + GuiLabel((Rectangle) { position.x + 20 + scroll.x, position.y + 300 + scroll.y, 250, 25 }, "Yet Another Label"); +} + +int main(void) { + InitWindow(960, 560, "raygui - floating window example"); + SetTargetFPS(60); + GuiLoadStyleDark(); + + while(!WindowShouldClose()) { + BeginDrawing(); + ClearBackground(DARKGREEN); + GuiWindowFloating(&window_position, &window_size, &minimized, &moving, &resizing, &DrawContent, (Vector2) { 140, 320 }, &scroll, "Movable & Scalable Window"); + GuiWindowFloating(&window2_position, &window2_size, &minimized2, &moving2, &resizing2, &DrawContent, (Vector2) { 140, 320 }, &scroll2, "Another window"); + EndDrawing(); + } + + CloseWindow(); + + return 0; +} \ No newline at end of file