[Refactor] Improve window buttons and fix state handling.
This commit is contained in:
		
							parent
							
								
									ea25cb6cc7
								
							
						
					
					
						commit
						0e7f97ca81
					
				@ -70,7 +70,7 @@ void GameState::start_single_player_now(int screen_width, int screen_height) {
 | 
			
		||||
  _init_desktop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameState::handle_event(SDL_Event* event) {
 | 
			
		||||
void GameState::handle_event(SDL_Event* event, int screen_width, int screen_height) {
 | 
			
		||||
  switch(_current_screen) {
 | 
			
		||||
  case Screen::MAIN_MENU:
 | 
			
		||||
    if(_main_menu) {
 | 
			
		||||
@ -82,7 +82,7 @@ void GameState::handle_event(SDL_Event* event) {
 | 
			
		||||
    break;
 | 
			
		||||
  case Screen::DESKTOP:
 | 
			
		||||
    if(_desktop) {
 | 
			
		||||
      _desktop->handle_event(event, _screen_height);
 | 
			
		||||
      _desktop->handle_event(event, screen_width, screen_height);
 | 
			
		||||
    }
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ public:
 | 
			
		||||
 | 
			
		||||
  void init(int screen_width, int screen_height);
 | 
			
		||||
  void start_single_player_now(int screen_width, int screen_height);
 | 
			
		||||
  void handle_event(SDL_Event* event);
 | 
			
		||||
  void handle_event(SDL_Event* event, int screen_width, int screen_height);
 | 
			
		||||
  void update(void);
 | 
			
		||||
  void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
			
		||||
              int screen_height, bool show_cursor);
 | 
			
		||||
 | 
			
		||||
@ -94,7 +94,7 @@ int main(int argc, char** argv) {
 | 
			
		||||
    SDL_Event event;
 | 
			
		||||
    while(SDL_PollEvent(&event)) {
 | 
			
		||||
      if(event.type == SDL_EVENT_QUIT) { running = false; }
 | 
			
		||||
      game_state->handle_event(&event);
 | 
			
		||||
      game_state->handle_event(&event, SCREEN_WIDTH, SCREEN_HEIGHT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    game_state->update();
 | 
			
		||||
 | 
			
		||||
@ -55,7 +55,7 @@ void Desktop::_set_focused_window(UIWindow* window) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Desktop::handle_event(SDL_Event* event, int screen_height) {
 | 
			
		||||
void Desktop::handle_event(SDL_Event* event, int screen_width, int screen_height) {
 | 
			
		||||
  if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
			
		||||
    int mouse_x = event->button.x;
 | 
			
		||||
    int mouse_y = event->button.y;
 | 
			
		||||
@ -95,7 +95,8 @@ void Desktop::handle_event(SDL_Event* event, int screen_height) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if(_focused_window) {
 | 
			
		||||
    _focused_window->handle_event(event);
 | 
			
		||||
    _focused_window->handle_event(event, screen_width, screen_height,
 | 
			
		||||
                                  _taskbar->get_height());
 | 
			
		||||
    Terminal* content = _focused_window->get_content();
 | 
			
		||||
    if(content && (event->type == SDL_EVENT_TEXT_INPUT || event->type == SDL_EVENT_KEY_DOWN)) {
 | 
			
		||||
      content->handle_input(event);
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ public:
 | 
			
		||||
  ~Desktop(void);
 | 
			
		||||
 | 
			
		||||
  void add_window(std::unique_ptr<UIWindow> window);
 | 
			
		||||
  void handle_event(SDL_Event* event, int screen_height);
 | 
			
		||||
  void handle_event(SDL_Event* event, int screen_width, int screen_height);
 | 
			
		||||
  void update(void);
 | 
			
		||||
  void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height,
 | 
			
		||||
              bool show_cursor);
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,12 @@ UIWindow::UIWindow(const char* title, int x, int y, int width, int height) :
 | 
			
		||||
    _should_close(false),
 | 
			
		||||
    _state(WindowState::NORMAL),
 | 
			
		||||
    _is_resizing(false),
 | 
			
		||||
    _resize_margin(10) {}
 | 
			
		||||
    _resize_margin(10) {
 | 
			
		||||
  /* Init title bar buttons. */
 | 
			
		||||
  _title_bar_buttons.push_back({WindowButtonAction::CLOSE,    {0.8f, 0.2f, 0.2f}});
 | 
			
		||||
  _title_bar_buttons.push_back({WindowButtonAction::MAXIMIZE, {0.2f, 0.8f, 0.2f}});
 | 
			
		||||
  _title_bar_buttons.push_back({WindowButtonAction::MINIMIZE, {0.8f, 0.8f, 0.2f}});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UIWindow::~UIWindow(void) {}
 | 
			
		||||
 | 
			
		||||
@ -74,8 +79,6 @@ void UIWindow::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
			
		||||
  const Color title_bar_color         = { 0.15f, 0.15f, 0.2f  };
 | 
			
		||||
  const Color focused_title_bar_color = { 0.3f,  0.3f,  0.4f  };
 | 
			
		||||
  const Color title_text_color        = { 0.9f,  0.9f,  0.9f  };
 | 
			
		||||
  const Color close_button_color      = { 0.8f,  0.2f,  0.2f  };
 | 
			
		||||
  const Color minimize_button_color   = { 0.8f,  0.8f,  0.2f  };
 | 
			
		||||
  const Color resize_handle_color     = { 0.9f,  0.9f,  0.9f  };
 | 
			
		||||
 | 
			
		||||
  /* Convert top-left coords to bottom-left for OpenGL. */
 | 
			
		||||
@ -97,14 +100,15 @@ void UIWindow::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
			
		||||
  txt_renderer->render_text(_title.c_str(), _x+5, y_gl+_height-title_bar_height+8,
 | 
			
		||||
                            1.0f, title_text_color);
 | 
			
		||||
 | 
			
		||||
  /* Draw close button. */
 | 
			
		||||
  shape_renderer->draw_rect(_x + _width - 25, y_gl + _height - title_bar_height + 5, 
 | 
			
		||||
                            20, 20, close_button_color);
 | 
			
		||||
 | 
			
		||||
  /* Draw minimize button. */
 | 
			
		||||
  shape_renderer->draw_rect(_x + _width - 50, 
 | 
			
		||||
                            y_gl + _height - title_bar_height + 5, 20, 20, 
 | 
			
		||||
                            minimize_button_color);
 | 
			
		||||
  /* Draw title bar buttons. */
 | 
			
		||||
  int button_size = 20;
 | 
			
		||||
  int button_margin = 5;
 | 
			
		||||
  int x_offset = _x + _width - button_size - button_margin;
 | 
			
		||||
  for(const auto& button : _title_bar_buttons) {
 | 
			
		||||
    shape_renderer->draw_rect(x_offset, y_gl + _height - title_bar_height + button_margin,
 | 
			
		||||
                              button_size, button_size, button.color);
 | 
			
		||||
    x_offset -= (button_size + button_margin);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Draw Resize handle. */
 | 
			
		||||
  int corner_x = _x + _width;
 | 
			
		||||
@ -119,36 +123,55 @@ void UIWindow::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWindow::handle_event(SDL_Event* event) {
 | 
			
		||||
void UIWindow::handle_event(SDL_Event* event, int screen_width,
 | 
			
		||||
                            int screen_height, int taskbar_height) {
 | 
			
		||||
  int title_bar_height = 30;
 | 
			
		||||
 | 
			
		||||
  if(event->type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
 | 
			
		||||
    int mouse_x = event->button.x;
 | 
			
		||||
    int mouse_y = event->button.y;
 | 
			
		||||
 | 
			
		||||
    /* Check for close button click. */
 | 
			
		||||
    int close_button_x = _x + _width - 25;
 | 
			
		||||
    int close_button_y = _y + 5;
 | 
			
		||||
    if(mouse_x >= close_button_x && mouse_x <= close_button_x + 20 &&
 | 
			
		||||
       mouse_y >= close_button_y && mouse_y <= close_button_y + 20) {
 | 
			
		||||
      _should_close = true;
 | 
			
		||||
      return; /* Stop processing this event. */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check for minimize button click. */
 | 
			
		||||
    int minimize_button_x = _x + _width - 50;
 | 
			
		||||
    int minimize_button_y = _y + 5;
 | 
			
		||||
    if(mouse_x >= minimize_button_x && mouse_x <= minimize_button_x + 20 &&
 | 
			
		||||
       mouse_y >= minimize_button_y && mouse_y <= minimize_button_y + 20) {
 | 
			
		||||
      minimize();
 | 
			
		||||
      return; /* Stop processing this event. */
 | 
			
		||||
    /* Check for title bar button clicks. */
 | 
			
		||||
    int button_size = 20;
 | 
			
		||||
    int button_margin = 5;
 | 
			
		||||
    int x_offset = _x + _width - button_size - button_margin;
 | 
			
		||||
    for(const auto& button : _title_bar_buttons) {
 | 
			
		||||
      if(mouse_x >= x_offset && mouse_x <= x_offset + button_size &&
 | 
			
		||||
         mouse_y >= _y + button_margin && mouse_y <= _y + button_margin + button_size) {
 | 
			
		||||
        switch(button.action) {
 | 
			
		||||
        case WindowButtonAction::CLOSE:
 | 
			
		||||
          _should_close = true;
 | 
			
		||||
          break;
 | 
			
		||||
        case WindowButtonAction::MAXIMIZE:
 | 
			
		||||
          if(_state == WindowState::MAXIMIZED) {
 | 
			
		||||
            _x          = _pre_maximize_rect.x;
 | 
			
		||||
            _y          = _pre_maximize_rect.y;
 | 
			
		||||
            _width      = _pre_maximize_rect.w;
 | 
			
		||||
            _height     = _pre_maximize_rect.h;
 | 
			
		||||
            _state      = WindowState::NORMAL;
 | 
			
		||||
          } else {
 | 
			
		||||
            _pre_maximize_rect = { _x, _y, _width, _height };
 | 
			
		||||
            _x = 0; _y = taskbar_height;
 | 
			
		||||
            _width = screen_width; _height = screen_height - taskbar_height;
 | 
			
		||||
            _state = WindowState::MAXIMIZED;
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case WindowButtonAction::MINIMIZE:
 | 
			
		||||
          minimize();
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        return; /* Button clicked, no need to process further. */
 | 
			
		||||
      }
 | 
			
		||||
      x_offset -= (button_size + button_margin);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Check for resize handle click (bottom-right corner). */
 | 
			
		||||
    if(is_mouse_over_resize_handle(mouse_x, mouse_y)) {
 | 
			
		||||
    if(is_mouse_over_resize_handle(mouse_x, mouse_y) &&
 | 
			
		||||
       _state != WindowState::MAXIMIZED) {
 | 
			
		||||
      _is_resizing = true;
 | 
			
		||||
    } else if(mouse_x >= _x && mouse_x <= _x + _width &&
 | 
			
		||||
       mouse_y >= _y && mouse_y <= _y + title_bar_height) {
 | 
			
		||||
       mouse_y >= _y && mouse_y <= _y + title_bar_height &&
 | 
			
		||||
       _state != WindowState::MAXIMIZED) {
 | 
			
		||||
      /* Is click within title bar? */
 | 
			
		||||
      _is_dragging = true;
 | 
			
		||||
      _drag_offset_x = mouse_x - _x;
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,17 @@ enum class WindowState {
 | 
			
		||||
  MAXIMIZED
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class WindowButtonAction {
 | 
			
		||||
  CLOSE,
 | 
			
		||||
  MAXIMIZE,
 | 
			
		||||
  MINIMIZE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct TitleBarButton {
 | 
			
		||||
  WindowButtonAction action;
 | 
			
		||||
  Color color;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class UIWindow {
 | 
			
		||||
public:
 | 
			
		||||
  UIWindow(const char* title, int x, int y, int width, int height);
 | 
			
		||||
@ -20,7 +31,8 @@ public:
 | 
			
		||||
 | 
			
		||||
  void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height,
 | 
			
		||||
              bool show_cursor);
 | 
			
		||||
  void handle_event(SDL_Event* event);
 | 
			
		||||
  void handle_event(SDL_Event* event, int screen_width, int screen_height,
 | 
			
		||||
                    int taskbar_height);
 | 
			
		||||
  void minimize(void);
 | 
			
		||||
  void restore(void);
 | 
			
		||||
  bool is_minimized(void) const;
 | 
			
		||||
@ -42,6 +54,7 @@ private:
 | 
			
		||||
  bool _is_hovered; /* Send scroll events even if not focused. */
 | 
			
		||||
  bool _should_close;
 | 
			
		||||
 | 
			
		||||
  std::vector<TitleBarButton> _title_bar_buttons;
 | 
			
		||||
  WindowState _state;
 | 
			
		||||
 | 
			
		||||
  bool _is_dragging;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user