From 7c572e5e14ba7801c5e888dec79951e51a120b6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Horv=C3=A1th=20Kata?= <horka23@cortex.itk.ppke.hu>
Date: Sat, 10 May 2025 23:40:26 +0200
Subject: [PATCH] menu+bemeneti mezok a jatekosok neveinek

---
 app.hpp        |   2 +-
 button.cpp     |   2 +-
 gamelogic.cpp  |  12 +----
 main.cpp       | 144 +++++++++++++++++++++++++++++++++++++++----------
 statictext.cpp |  89 ++++++++++++++++++++++++++++++
 statictext.hpp |  19 +++++++
 textbox.cpp    | 111 ++++++++++++++++++++++++++++++++++++++
 textbox.hpp    |  29 ++++++++++
 textedit.cpp   |  28 ++++++++++
 textedit.hpp   |  16 ++++++
 10 files changed, 410 insertions(+), 42 deletions(-)
 create mode 100644 statictext.cpp
 create mode 100644 statictext.hpp
 create mode 100644 textbox.cpp
 create mode 100644 textbox.hpp
 create mode 100644 textedit.cpp
 create mode 100644 textedit.hpp

diff --git a/app.hpp b/app.hpp
index 4081938..3d960ea 100644
--- a/app.hpp
+++ b/app.hpp
@@ -19,7 +19,7 @@ public:
     virtual ~App();
 
     void registerWidget(Widget* widget);
-    void event_loop();
+    virtual void event_loop();
     virtual void action(const std::string& id) = 0;
 
     // Add these to avoid incomplete type issues
diff --git a/button.cpp b/button.cpp
index bf04277..83c7b2f 100644
--- a/button.cpp
+++ b/button.cpp
@@ -20,7 +20,7 @@ void Button::draw(){
     }
 
     int text_x=_x+(_size_x-gout.twidth(_text))/2;
-    int text_y =_y+(_size_y-gout.cascent()-gout.cdescent())/2+gout.cascent();
+    int text_y =_y+(_size_y-gout.cascent()-gout.cdescent())/2;
     gout << move_to(text_x, text_y) << color(0,0,0) << text(_text);
 
 }
diff --git a/gamelogic.cpp b/gamelogic.cpp
index 834f423..071808a 100644
--- a/gamelogic.cpp
+++ b/gamelogic.cpp
@@ -16,17 +16,7 @@ void GameLogic::reset() {
     _winner=EMPTY;
     _last_move_row=-1;
     _last_move_col=-1;
-    /*int _board[GameLogic::ROWS][GameLogic::COLS];
-    for (int i = 0; i < GameLogic::ROWS; ++i) {
-        for (int j = 0; j < GameLogic::COLS; ++j) {
-            _board[i][j] = GameLogic::EMPTY;
-        }
-    }
-    _current_player = PLAYER1;
-    gameover = false;
-    _winner = EMPTY;
-    _last_move_row = -1;
-    _last_move_col = -1;*/
+
 
 }
 
diff --git a/main.cpp b/main.cpp
index 9170ce0..d1a4e39 100644
--- a/main.cpp
+++ b/main.cpp
@@ -3,6 +3,7 @@
 #include "gamelogic.hpp"
 #include "cell.hpp"
 #include "button.hpp"
+#include "textbox.hpp"
 
 #include <vector>
 #include <iostream>
@@ -12,12 +13,82 @@ using namespace genv;
 
 class Amoba: public App{
 private:
-    GameLogic _game;
-    vector<vector<Cell*>> _cells;
-    vector<Widget*> _widgets;
+    enum Mode {MENU, GAME};
+    Mode current_mode;
+    std::string player1_name, player2_name;
+
+    Textbox* name1_input;
+    Textbox* name2_input;
     Button* start_button;
-    Button* restart_button;
+    std::vector<Widget*> menu_widgets;
+
+
+    std::vector<std::vector<Cell*>> _cells;
+    std::vector<Widget*> game_widgets;
+    GameLogic _game;
     bool game_started;
+    Button* restart_button;
+
+
+
+
+    void createMenu() {
+        name1_input = new Textbox(this, 190, 300, 200, 40);
+        menu_widgets.push_back(name1_input);
+        registerWidget(name1_input);
+
+        name2_input = new Textbox(this, 410, 300, 200, 40);
+        menu_widgets.push_back(name2_input);
+        registerWidget(name2_input);
+
+        start_button = new Button(this, 350, 360, 100, 40, "START");
+        menu_widgets.push_back(start_button);
+        registerWidget(start_button);
+        }
+
+
+
+    void handleMenu(){
+        if(start_button->isSelected() && !name1_input->getText().empty()){
+            player1_name=name1_input->getText();
+            player2_name=name2_input->getText();
+            current_mode=GAME;
+            start_button->setSelected(false);
+            game_started=true;
+        }
+        else{
+            start_button->setSelected(false);
+        }
+
+    }
+
+
+
+
+
+    void handleMouseEvent(const genv::event& ev){
+        _focused_widget = nullptr;
+        std::vector<Widget*>* active_widgets;
+
+        if (current_mode==MENU){
+            active_widgets=&menu_widgets;
+        } else {
+            active_widgets=&game_widgets;
+        }
+
+        for (Widget* w:*active_widgets){
+            if (w->is_selected(ev.pos_x, ev.pos_y)){
+                _focused_widget=w;
+                break;
+            }
+        }
+
+        if (_focused_widget) {
+            _focused_widget->handle_event(ev);
+    }
+}
+
+
 
 
 
@@ -48,6 +119,7 @@ private:
                                    }
                       });
                 rowcells.push_back(cell);
+                game_widgets.push_back(cell);
             }
             _cells.push_back(rowcells);
 
@@ -61,22 +133,13 @@ private:
 
         const int button_width=100;
         const int button_height=40;
-
-
-
-        start_button=new Button(this, _width-3*button_width+10, 50, button_width, button_height, "START");
-        _widgets.push_back(start_button);
         restart_button=new Button(this, _width-4*button_width, 50, button_width, button_height, "RESTART");
+        game_widgets.push_back(restart_button);
         _widgets.push_back(restart_button);
 
     }
 
 
-
-
-
-
-
     void handleColumnclick(int col){
         if(game_started && !_game.GameOver()){
             if(_game.makeMove(col)){
@@ -91,17 +154,16 @@ private:
     }
 
 
-
     void checkButtons(){
-        if(start_button && start_button->isSelected()){
+        /*if(start_button && start_button->isSelected()){
             game_started=true;
             start_button->setSelected(false);
-        }
+        }*/
 
 
         if(restart_button && restart_button->isSelected()){
             _game.reset();
-            game_started=false;
+            game_started=true;
             //generateCells();
             updateBoard();
             restart_button->setSelected(false);
@@ -135,7 +197,8 @@ private:
 
 public:
 
-    Amoba(int w, int h): App(w, h), game_started(false){
+    Amoba(int w, int h): App(w, h), game_started(false), current_mode(MENU){
+        createMenu();
         generateCells();
         createButtons();
         updateBoard();
@@ -143,19 +206,22 @@ public:
 
     ~Amoba(){
 
-        for(int i=0; i<_cells.size(); i++){
-            for(int j=0; j<_cells[i].size(); j++){
-                delete _cells[i][j];
-            }
-
+        for (Widget* widget : menu_widgets) {
+            delete widget;
+    }
+        for (Widget* widget : game_widgets) {
+            delete widget;
+    }
+        for (std::vector<Cell*>& row : _cells) {
+            for (Cell* cell : row) {
+                delete cell;
         }
+    }
         _cells.clear();
-        delete start_button;
-        delete restart_button;
 
     }
 
-     void action(const std::string& id) override {
+    void action(const std::string& id) override {
         if (id == "enter" || id == "space") {
             _game.reset();
             updateBoard();
@@ -164,7 +230,7 @@ public:
 
 
 
-    void event_loop(){
+    void event_loop() override{
         gout.open(_width, _height);
         gin.timer(20);
         event ev;
@@ -172,7 +238,14 @@ public:
         while(gin>>ev){
             if(ev.type==ev_mouse){
                 handleMouseEvent(ev);
-                checkButtons();
+                if(current_mode==MENU){
+                    handleMenu();
+                }
+                else if(current_mode==GAME){
+                    checkButtons();
+                }
+
+             //   checkButtons();
             }
             else if(ev.type==ev_key){
                 if(_focused_widget){
@@ -186,6 +259,19 @@ public:
 
     }
 
+    void drawAllWidgets() {
+        if(current_mode==MENU){
+            for(Widget* widget:menu_widgets){
+                widget->draw();
+            }
+        }
+        else if(current_mode==GAME){
+            for(Widget* widget : game_widgets){
+                widget->draw();
+            }
+        }
+    gout << genv::refresh;
+    }
 
 
 };
diff --git a/statictext.cpp b/statictext.cpp
new file mode 100644
index 0000000..2ada044
--- /dev/null
+++ b/statictext.cpp
@@ -0,0 +1,89 @@
+#include "statictext.hpp"
+#include "graphics.hpp"
+using namespace genv;
+
+StaticText::StaticText(int x, int y, int sx, int sy, const std::string& s)
+    : Widget(x, y, sx, sy), _text(s), _cursor_pos(0), _show_cursor(false), _editable(false) {}
+
+void StaticText::draw() {
+    gout << move_to(_x, _y) << color(255, 255, 255) << box(_size_x, _size_y);
+    gout.load_font("LiberationMono-Regular.ttf", 15);
+
+    gout << move_to(_x+2 + 2, _y+10) << color(0, 0, 0);
+
+    std::string visible_text = _text;
+    int text_width = gout.twidth(visible_text);
+
+    while (text_width > _size_x - 4 && !visible_text.empty()) {
+        visible_text.pop_back();
+        text_width = gout.twidth(visible_text);
+    }
+
+    gout << text(visible_text);
+
+
+    if (_editable && _show_cursor) {
+        std::string before_cursor = _text.substr(0, _cursor_pos);
+        int cursor_x = _x + 2 + gout.twidth(before_cursor);
+
+
+        if (cursor_x < _x + _size_x - 2) {
+            gout << move_to(cursor_x+2, _y + _size_y/4) << color(0, 0, 0)
+                 << line(0, gout.cascent() + gout.cdescent());
+        }
+    }
+}
+
+void StaticText::handle(event ev) {
+    if (ev.type == ev_mouse && ev.button == btn_left) {
+
+        _editable = is_selected(ev.pos_x, ev.pos_y);
+        _show_cursor = _editable;
+
+        if (_editable) {
+
+            int click_x = ev.pos_x - _x - 2;
+            std::string temp;
+            _cursor_pos = 0;
+
+            for (size_t i = 0; i < _text.length(); i++) {
+                temp += _text[i];
+                if (gout.twidth(temp) > click_x) {
+                    break;
+                }
+                _cursor_pos = i + 1;
+            }
+        }
+    }
+
+    if (!_editable) return;
+
+    if (ev.type == ev_key) {
+        _show_cursor = true;
+
+        if (ev.keycode == key_left && _cursor_pos > 0) {
+            _cursor_pos--;
+        } else if (ev.keycode == key_right && _cursor_pos < _text.length()) {
+            _cursor_pos++;
+        } else if (ev.keycode == key_backspace && _cursor_pos > 0) {
+            _text.erase(_cursor_pos - 1, 1);
+            _cursor_pos--;
+        } else if (ev.keycode == key_delete && _cursor_pos < _text.length()) {
+            _text.erase(_cursor_pos, 1);
+        } else if (ev.keycode >= 32 && ev.keycode < 256) {
+            std::string temp_text = _text;
+            temp_text.insert(_cursor_pos, 1, ev.keycode);
+            if (gout.twidth(temp_text) <= _size_x - 4) {
+                _text.insert(_cursor_pos, 1, ev.keycode);
+                _cursor_pos++;
+            }
+        } else if (ev.keyutf8 != "") {
+            std::string temp_text = _text;
+            temp_text.insert(_cursor_pos, ev.keyutf8);
+            if (gout.twidth(temp_text) <= _size_x - 4) {
+                _text.insert(_cursor_pos, ev.keyutf8);
+                _cursor_pos += ev.keyutf8.length();
+            }
+        }
+    }
+}
diff --git a/statictext.hpp b/statictext.hpp
new file mode 100644
index 0000000..db2cb3f
--- /dev/null
+++ b/statictext.hpp
@@ -0,0 +1,19 @@
+#ifndef STATICTEXT_HPP
+#define STATICTEXT_HPP
+
+#include "widgets.hpp"
+#include <string>
+
+class StaticText : public Widget {
+protected:
+    std::string _text;
+    size_t _cursor_pos;
+    bool _show_cursor;
+    bool _editable;
+public:
+    StaticText(int x, int y, int sx, int sy, const std::string& s);
+    virtual void draw() override;
+    virtual void handle(genv::event ev) override;
+};
+
+#endif
diff --git a/textbox.cpp b/textbox.cpp
new file mode 100644
index 0000000..c52adf6
--- /dev/null
+++ b/textbox.cpp
@@ -0,0 +1,111 @@
+#include "textbox.hpp"
+#include "graphics.hpp"
+
+using namespace genv;
+
+Textbox::Textbox(App* parent, int x, int y, int sx, int sy): Widget(parent, x, y, sx, sy), _text(""), _cursor_pos(0), _show_cursor(false), _editable(false){}
+
+
+void Textbox::draw(){
+    gout << move_to(_x, _y) << color(50, 50, 50) << box(_size_x, _size_y);
+    gout.load_font("LiberationSans-Regular.ttf", 15);
+
+    gout << move_to(_x+2 + 2, _y+15) << color(255, 255, 255);
+
+
+
+    std::string visible_text = _text;
+    int text_width = gout.twidth(visible_text);
+
+    while (text_width > _size_x - 4 && !visible_text.empty()) {
+        visible_text.pop_back();
+        text_width = gout.twidth(visible_text);
+    }
+
+    gout << text(visible_text);
+
+
+    if (_editable && _show_cursor) {
+        std::string before_cursor = _text.substr(0, _cursor_pos);
+        int cursor_x = _x + 2 + gout.twidth(before_cursor);
+
+
+        if (cursor_x < _x + _size_x - 2) {
+            gout << move_to(cursor_x+2, _y + _size_y/4) << color(0, 0, 0)
+                 << line(0, gout.cascent() + gout.cdescent());
+        }
+    }
+
+
+
+    /*gout << move_to(_x, _y) << color(220, 220, 220) << box(_size_x, _size_y);
+
+    if (_active){
+        gout << move_to(_x, _y) << color(200, 200, 200) << line(_size_x, 0)
+             << line(0, _size_y) << line(-_size_x, 0) << line(0, -_size_y);
+             */
+    }
+
+    //gout << move_to(_x+5, _y+_size_y/2+gout.cascent()/2) << color(255, 255, 255) << text(_text);
+
+
+
+void Textbox::handle_event(event ev){
+    if (ev.type==ev_mouse && ev.button==btn_left) {
+        _editable=is_selected(ev.pos_x, ev.pos_y);
+        _show_cursor=_editable;
+    }
+    if (!_editable) {return;}
+    if (_editable){
+
+        int click_x=ev.pos_x-_x - 2;
+        std::string temp;
+        _cursor_pos=0;
+
+        for (int i=0; i<_text.length(); i++){
+            temp+=_text[i];
+            if (gout.twidth(temp)>click_x){
+                break;
+            }
+            _cursor_pos=i+1;
+        }
+    }
+
+
+
+
+    if (ev.type==ev_key){
+        _show_cursor=true;
+
+        if (ev.keycode==key_left && _cursor_pos>0){
+            _cursor_pos--;
+        }
+        else if (ev.keycode==key_right && _cursor_pos<_text.length()){
+            _cursor_pos++;
+        }
+        else if (ev.keycode==key_backspace &&_cursor_pos>0){
+            _text.erase(_cursor_pos - 1, 1);
+            _cursor_pos--;
+        }
+        else if (ev.keycode==key_delete && _cursor_pos<_text.length()){
+            _text.erase(_cursor_pos, 1);
+
+        }
+        else if (ev.keycode>=32 && ev.keycode<256){
+            std::string temp_text=_text;
+            temp_text.insert(_cursor_pos, 1, ev.keycode);
+            if (gout.twidth(temp_text)<=_size_x-4){
+                _text.insert(_cursor_pos, 1, ev.keycode);
+                _cursor_pos++;
+            }
+        } else if (ev.keyutf8!=""){
+            std::string temp_text=_text;
+            temp_text.insert(_cursor_pos, ev.keyutf8);
+            if (gout.twidth(temp_text)<=_size_x-4) {
+                _text.insert(_cursor_pos, ev.keyutf8);
+                _cursor_pos+=ev.keyutf8.length();
+                _cursor_pos++;
+            }
+        }
+    }
+}
diff --git a/textbox.hpp b/textbox.hpp
new file mode 100644
index 0000000..4a82d3f
--- /dev/null
+++ b/textbox.hpp
@@ -0,0 +1,29 @@
+#ifndef TEXTBOX_HPP_INCLUDED
+#define TEXTBOX_HPP_INCLUDED
+
+
+#include "graphics.hpp"
+#include "widgets.hpp"
+#include "app.hpp"
+#include <string>
+
+
+class Textbox: public Widget{
+private:
+    std::string _text;
+    size_t _cursor_pos;
+    bool _show_cursor;
+    bool _editable;
+
+public:
+    Textbox(App* parent, int x, int y, int sx, int sy);
+    void draw() override;
+    void handle_event(genv::event ev) override;
+
+    std::string getText() const {return _text;}
+    void setText(std::string newtext){_text=newtext;}
+
+};
+
+
+#endif // TEXTBOX_HPP_INCLUDED
diff --git a/textedit.cpp b/textedit.cpp
new file mode 100644
index 0000000..e9ef1af
--- /dev/null
+++ b/textedit.cpp
@@ -0,0 +1,28 @@
+#include "textedit.hpp"
+
+TextEdit::TextEdit(int x, int y, int sx, int sy, std::string s)
+    : Widget(x,y,sx,sy), _text(s)
+{}
+
+using namespace genv;
+
+void TextEdit::draw()
+{
+    gout.load_font("LiberationMono-BoldItalic.ttf", 20);
+    gout <<move_to(_x, _y) << color(255,255,255) << box(_size_x, _size_y) << color(0, 0, 0) << move_to(_x+5, _y+5) << text(_text);
+}
+
+void TextEdit::handle(event ev)
+{
+    if(ev.type == ev_key)
+    {
+        if(ev.keycode==key_backspace)
+        {
+            _text=_text.substr(0,_text.size()-1);
+        }
+        else
+        {
+            _text+=ev.keyutf8;
+        }
+    }
+}
diff --git a/textedit.hpp b/textedit.hpp
new file mode 100644
index 0000000..cd1ad64
--- /dev/null
+++ b/textedit.hpp
@@ -0,0 +1,16 @@
+#ifndef TEXTEDIT_HPP
+#define TEXTEDIT_HPP
+
+#include "widgets.hpp"
+
+class TextEdit : public Widget
+{
+protected:
+    std::string _text;
+public:
+    TextEdit(int, int, int, int, std::string);
+    virtual void draw() override;
+    virtual void handle(genv::event) override;
+};
+
+#endif // TEXTEDIT_HPP
-- 
GitLab