diff --git a/application.cpp b/application.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a0e6a90a4951474563e29c55ecf367ba152530bf
--- /dev/null
+++ b/application.cpp
@@ -0,0 +1,42 @@
+#include "application.hpp"
+#include "graphics.hpp"
+#include "widget.hpp"
+using namespace genv;
+
+Application::Application()
+{
+    gout.open(900,900);
+}
+
+void Application::event_loop()
+{
+    event ev;
+    int focus = -1;
+    while(gin >> ev )
+    {
+        if (ev.type == ev_mouse && ev.button==btn_left)
+        {
+            for (size_t i=0; i<widgets.size(); i++)
+            {
+                if (widgets[i]->isover(ev.pos_x, ev.pos_y))
+                {
+                    focus = i;
+                }
+            }
+        }
+        if (focus!=-1)
+        {
+            widgets[focus]->handle(ev);
+        }
+        for (Widget * w : widgets)
+        {
+            w->draw();
+        }
+        gout << refresh;
+    }
+}
+
+void Application::registerWidget(Widget* w)
+{
+    widgets.push_back(w);
+}
diff --git a/application.hpp b/application.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..82c04f05dea3bae7db1e36f3ce1ba951fa0787c6
--- /dev/null
+++ b/application.hpp
@@ -0,0 +1,23 @@
+#ifndef APPLICATION_HPP
+#define APPLICATION_HPP
+#include "vector"
+#include <iostream>
+
+
+class Widget;
+
+class Application
+{
+public:
+    Application();
+
+    virtual void event_loop();
+    virtual void registerWidget(Widget*);
+
+    virtual void action(std::string) = 0;
+
+protected:
+    std::vector<Widget*> widgets;
+};
+
+#endif
diff --git a/listbox.cpp b/listbox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0141044f1e43ee764fe8a31a887168e509cdba6f
--- /dev/null
+++ b/listbox.cpp
@@ -0,0 +1,119 @@
+#include "listbox.hpp"
+#include "widget.hpp"
+#include "graphics.hpp"
+using namespace genv;
+using namespace std;
+
+ListBox::ListBox(Application* parent,int x, int y, int sizex, int sizey, vector<string> s) : Widget(parent,x,y,sizex,sizey), _s(s), _scroll(0), displaynum(0), _selected(-1)
+{
+
+}
+
+
+void ListBox::draw()
+{
+    gout.load_font("LiberationSans-Regular.ttf",20);
+    int height = gout.cascent()+gout.cdescent()+2;
+    int displaynum = _sizey/height;
+
+    if(displaynum > _s.size())
+    {
+        displaynum = _s.size();
+
+
+    }
+    _sizey = displaynum * height;
+
+    int ypos = 0;
+
+    gout << move_to(_x, _y) << color(200,200,200) << box (_sizex+2, displaynum*height);
+
+    for (int i = _scroll; i < _scroll + displaynum and i < _s.size(); ++i)
+    {
+
+        if(i != _selected){
+            {
+                gout << move_to(_x+1, _y+ypos) << color(0,0,0) << box (_sizex, height) << move_to(_x+2, _y+ypos) << color(255,255,255) << text(_s[i]) << move_to(_x, _y+ypos)
+                     <<  color(200,200,200) << line(_sizex, 0);
+            }
+
+        }
+        if(i == _selected){
+            {
+                gout << move_to(_x+1, _y+ypos) << color(0,0,0) << box (_sizex, height) << move_to(_x+2, _y+ypos) << color(255,0,255) << text(_s[i]) << move_to(_x, _y+ypos)
+                     <<  color(200,200,200) << line(_sizex, 0);
+            }
+            //ypos += height;
+        }
+        ypos += height;
+
+
+    }
+    gout << move_to(_x, _y + ypos) << color(200,200,200) << line(_sizex, 0) << refresh;
+
+
+
+
+
+
+}
+
+
+
+void ListBox::handle(event ev)
+{
+
+
+    gout.load_font("LiberationSans-Regular.ttf",20);
+    int height = gout.cascent()+gout.cdescent()+2;
+    int displaynum = _sizey/height;
+    int max_scroll = _s.size()-displaynum;
+    if(ev.type == ev_mouse)
+    {
+        if(isover(ev.pos_x, ev.pos_y) and (ev.button == btn_wheeldown or ev.button == btn_middle))
+        {
+            if(_scroll < max_scroll)
+            {
+                _scroll++;
+            }
+        }
+        if(isover(ev.pos_x, ev.pos_y) and (ev.button == btn_wheelup or ev.button == btn_right))
+        {
+            if (_scroll > 0)
+            {
+                _scroll--;
+            }
+        }
+
+        for (int i = 0; i < displaynum; ++i)
+        {
+            if(i == 0)
+            {
+                if(ev.pos_x > _x and ev.pos_x < _x + _sizex and ev.pos_y < height+_y and ev.pos_y > _y and ev.button == btn_left )
+                {
+                    _selected = i + _scroll;
+                }
+            }
+            if(i > 0){
+                if(ev.pos_x > _x and ev.pos_x < _x + _sizex and ev.pos_y < _y+i*2*height and ev.pos_y > _y+i*height and ev.button == btn_left )
+                {
+                    _selected = i + _scroll;
+                }
+            }
+        }
+        if(!isover(ev.pos_x,ev.pos_y) and ev.button == btn_left)
+        {
+            _selected = -1;
+        }
+    }
+}
+bool ListBox::isover(int ms_x, int ms_y)
+{
+    return (ms_x >= _x) and (ms_x <= _x + _sizex) and (ms_y >= _y) and (ms_y <= _y + _sizey);
+}
+string ListBox::getter()
+{
+    return _s[_selected];
+}
+
+
diff --git a/listbox.hpp b/listbox.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..26b2e72eb61e0e19eb73c4d67635ffcd9c8f2056
--- /dev/null
+++ b/listbox.hpp
@@ -0,0 +1,26 @@
+#ifndef LISTBOX_HPP
+#define LISTBOX_HPP
+#include "graphics.hpp"
+#include "widget.hpp"
+
+class ListBox : public Widget
+{
+protected:
+
+    std::vector<std::string> _s;
+    int _scroll, displaynum;
+
+    int _selected;
+
+
+public:
+    ListBox(Application*,int, int, int,int, std::vector<std::string>);
+
+    void draw() override;
+    void handle(genv::event) override;
+    bool isover(int mouse_x,int mouse_y) override;
+    std::string getter() override;
+
+};
+
+#endif // LISTBOX_HPP
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..40aad3738ef158db6150498bfd0c48313ed57f16
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,13 @@
+#include "graphics.hpp"
+using namespace genv;
+
+
+int main()
+{
+    gout.open(400,400);
+    gout <<text("hello world")<< refresh;
+    event ev;
+    while(gin >> ev) {
+    }
+    return 0;
+}
diff --git a/spinbox.cpp b/spinbox.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3d6417b91455a6d0ca3a6a5f817e4549574b0f22
--- /dev/null
+++ b/spinbox.cpp
@@ -0,0 +1,123 @@
+#include "spinbox.hpp"
+#include "graphics.hpp"
+#include "widget.hpp"
+
+
+using namespace genv;
+using namespace std;
+
+int mouse_x = 0;
+int mouse_y = 0;
+
+SpinBox::SpinBox(Application* parent,int x, int y, int sizey, int min, int max) : Widget(parent,x,y,sizey*3,sizey), _min(min), _max(max), _isselected(0)
+{
+    _num = (_min + _max)/2;
+}
+
+void SpinBox::draw()
+{
+    gout.load_font("LiberationSans-Regular",20);
+
+    gout << move_to (_x,_y)  << color(255,255,255) << box(_sizex,_sizey);
+
+    gout << move_to(_x + 1, _y + 1) << color(0,0,0) << box(_sizey - 2, _sizey -2);
+
+    gout << move_to(_x + _sizey + 1, _y + 1) << color(0,0,0) << box(_sizey - 2, _sizey -2);
+
+    gout << move_to(_x +2*_sizey + 1, _y + 1) << color(0,0,0) << box(_sizey - 2, _sizey -2);
+
+    gout << move_to(_x + _sizey / 2, _y + _sizey / 2 + _sizey / 6)
+         << color(255, 0, 0)
+         << line_to(_x + _sizey / 2 + _sizey / 6, _y + _sizey / 2 - _sizey / 6)
+         << line_to(_x + _sizey / 2 - _sizey / 6, _y + _sizey / 2 - _sizey / 6)
+         << line_to(_x + _sizey / 2, _y + _sizey / 2 + _sizey / 6);
+
+    int text_width = gout.twidth(to_string(_num));
+
+    int text_height = gout.cascent() + gout.cdescent();
+
+    gout << move_to(_x + (_sizex - text_width) / 2, _y + (_sizey - text_height) / 2 + gout.cascent())
+         << color(255, 255, 255)
+         << text(to_string(_num));
+    gout << move_to(_x + _sizex - _sizey / 2, _y + _sizey / 2 - _sizey / 6)
+         << color(0, 255, 0)
+         << line_to(_x + _sizex - _sizey / 2 + _sizey / 6, _y + _sizey / 2 + _sizey / 6)
+         << line_to(_x + _sizex - _sizey / 2 - _sizey / 6, _y + _sizey / 2 + _sizey / 6)
+         << line_to(_x + _sizex - _sizey / 2, _y + _sizey / 2 - _sizey / 6);
+}
+
+bool SpinBox::isover(int ms_x, int ms_y)
+{
+    return (ms_x >= _x) and (ms_x <= _x + _sizex) and (ms_y >= _y) and (ms_y <= _y + _sizey);
+}
+
+
+
+
+
+
+
+string SpinBox::getter()
+{
+    return to_string(_num);
+}
+
+
+void SpinBox::handle(event ev)
+{
+    if(ev.type == ev_mouse)
+    {
+
+        if(ev.button == btn_left)
+        {
+            if(isover(ev.pos_x,ev.pos_y))
+            {
+                _isselected = true;
+            }
+            else
+            {
+                _isselected = false;
+            }
+        }
+
+        if(_isselected)
+        {
+            if(isover(ev.pos_x, ev.pos_y) and ev.pos_x < _x + _sizex/3 and ev.button == btn_left and _num >= _min)
+            {
+                _num -= 1;
+
+
+            }
+
+            if(isover(ev.pos_x, ev.pos_y) and ev.pos_x > _x + 2*_sizex/3 and ev.button == btn_left and _num <= _max)
+            {
+                _num += 1;
+
+            }
+        }
+
+    }
+    else if(ev.type == ev_key)
+    {
+        if(_isselected)
+        {
+
+            if( ev.keycode == key_pgdn and _num >= _min + 10)
+            {
+                _num -= 10;
+            }
+            else if(ev.keycode == key_pgup and _num <= _max - 10)
+            {
+                _num += 10;
+            }
+            else if( ev.keycode == key_down and _num >= _min + 1 )
+            {
+                _num -= 1;
+            }
+            else if(ev.keycode == key_up and _num <= _max -1)
+            {
+                _num += 1;
+            }
+        }
+    }
+}
diff --git a/spinbox.hpp b/spinbox.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7fed94086b2bcb528eb554ca1b10c1449c7471d5
--- /dev/null
+++ b/spinbox.hpp
@@ -0,0 +1,25 @@
+#ifndef SPINBOX_HPP
+#define SPINBOX_HPP
+#include "graphics.hpp"
+#include "widget.hpp"
+
+class SpinBox : public Widget
+{
+protected:
+    int _min, _max, _num;
+    bool _isselected;
+
+public:
+    SpinBox(Application* ,int, int, int,int, int);
+
+    void draw() override;
+    void handle(genv::event) override;
+    bool isover(int mouse_x,int mouse_y) override;
+    std::string getter() override;
+
+
+
+
+};
+
+#endif // SPINBOX_HPP
diff --git a/widget.cpp b/widget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..79bce8eebc4409390e9fb4aac5484f4cd362af04
--- /dev/null
+++ b/widget.cpp
@@ -0,0 +1,10 @@
+#include "widget.hpp"
+#include "application.hpp"
+#include "graphics.hpp"
+using namespace genv;
+
+Widget::Widget(Application * parent,int x, int y, int sizex, int sizey) : _x(x), _y(y), _sizex(sizex), _sizey(sizey), _parent(parent)
+
+{
+    _parent->registerWidget(this);
+}
diff --git a/widget.hpp b/widget.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d61c2cd05ab23fdb79bd68c6c25c43d5a2989680
--- /dev/null
+++ b/widget.hpp
@@ -0,0 +1,22 @@
+#ifndef WIDGET_HPP
+#define WIDGET_HPP
+#include "application.hpp"
+#include "graphics.hpp"
+
+
+
+class Widget {
+protected:
+    int _x, _y, _sizex, _sizey;
+    Application * _parent;
+
+public:
+    Widget(Application * parent, int x, int y, int sizex, int sizey);
+    virtual void draw() = 0;
+    virtual void handle(genv::event ev) = 0;
+    virtual bool isover(int ms_x, int ms_y) = 0;
+    virtual std::string getter() = 0;
+
+};
+
+#endif // WIDGET_HPP