From e6222ab46717f36281e874a4350f4ac6118be906 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maty=C3=A1=C5=A1=20Latner?= <matyas.latner@nic.cz>
Date: Tue, 27 Oct 2015 13:36:13 +0100
Subject: [PATCH] #58 Refactored game menu and user menu

---
 .../cz/nic/tablexia/game/GameDefinition.java  |  15 +
 .../cz/nic/tablexia/menu/AbstractMenu.java    |  80 ++---
 core/src/cz/nic/tablexia/menu/IMenuItem.java  |   4 +
 .../tablexia/menu/game/GameMenuItemGroup.java | 169 ++++++++++
 .../cz/nic/tablexia/menu/main/MainMenu.java   | 294 ++----------------
 .../menu/main/MainMenuDefinition.java         |  45 +--
 .../tablexia/menu/main/MainMenuItemGroup.java | 128 ++++++++
 .../main/{ => locale}/LocaleSelectBox.java    |   2 +-
 .../menu/main/{ => user}/UserSelectBox.java   |   7 +-
 .../cz/nic/tablexia/menu/user/UserMenu.java   |  36 ++-
 core/src/cz/nic/tablexia/model/User.java      |  16 +
 11 files changed, 428 insertions(+), 368 deletions(-)
 create mode 100644 core/src/cz/nic/tablexia/menu/game/GameMenuItemGroup.java
 create mode 100644 core/src/cz/nic/tablexia/menu/main/MainMenuItemGroup.java
 rename core/src/cz/nic/tablexia/menu/main/{ => locale}/LocaleSelectBox.java (99%)
 rename core/src/cz/nic/tablexia/menu/main/{ => user}/UserSelectBox.java (97%)

diff --git a/core/src/cz/nic/tablexia/game/GameDefinition.java b/core/src/cz/nic/tablexia/game/GameDefinition.java
index 7156751c1..d01c21811 100644
--- a/core/src/cz/nic/tablexia/game/GameDefinition.java
+++ b/core/src/cz/nic/tablexia/game/GameDefinition.java
@@ -1,5 +1,7 @@
 package cz.nic.tablexia.game;
 
+import com.badlogic.gdx.scenes.scene2d.Group;
+
 import cz.nic.tablexia.Tablexia;
 import cz.nic.tablexia.TablexiaApplication;
 import cz.nic.tablexia.bus.ApplicationBus;
@@ -14,6 +16,7 @@ import cz.nic.tablexia.game.games.shooting_range.tools.ShootingRangeResultResolv
 import cz.nic.tablexia.loader.application.ApplicationTextManager;
 import cz.nic.tablexia.menu.AbstractMenu;
 import cz.nic.tablexia.menu.IMenuItem;
+import cz.nic.tablexia.menu.game.GameMenuItemGroup;
 import cz.nic.tablexia.model.game.Game;
 import cz.nic.tablexia.screen.gamemenu.GameMenuScreen;
 import cz.nic.tablexia.screen.gamemenu.event.ShowGameMenuPageEvent;
@@ -37,6 +40,8 @@ public enum GameDefinition implements ApplicationEvent, IMenuItem {
 		AbstractTablexiaGame.GameResult getGameResult(Game game);
 	}
 
+	private static final Class<GameMenuItemGroup> MENU_ITEM_GROUP_CLASS = GameMenuItemGroup.class;
+
 	private int                                      gameNumber;
 	private String                                   menuTextKey;
 	private String 									 descriptionResource;
@@ -71,6 +76,16 @@ public enum GameDefinition implements ApplicationEvent, IMenuItem {
 		return ApplicationTextManager.getInstance().getResult().get(descriptionResource);
 	}
 
+	@Override
+	public String[] getIcons() {
+		return null;
+	}
+
+	@Override
+	public Class<? extends Group> getItemGroupClass() {
+		return MENU_ITEM_GROUP_CLASS;
+	}
+
 	public Class<? extends AbstractTablexiaGame<?>> getScreenClass() {
 		return screenClass;
 	}
diff --git a/core/src/cz/nic/tablexia/menu/AbstractMenu.java b/core/src/cz/nic/tablexia/menu/AbstractMenu.java
index 44e944ab4..7dd839b6f 100644
--- a/core/src/cz/nic/tablexia/menu/AbstractMenu.java
+++ b/core/src/cz/nic/tablexia/menu/AbstractMenu.java
@@ -13,7 +13,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup;
 import com.badlogic.gdx.scenes.scene2d.ui.Image;
 import com.badlogic.gdx.scenes.scene2d.ui.Stack;
 import com.badlogic.gdx.scenes.scene2d.ui.Table;
-import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
 import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
 import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
 import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
@@ -21,14 +20,15 @@ import com.badlogic.gdx.scenes.scene2d.utils.SpriteDrawable;
 import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
 import com.badlogic.gdx.utils.Align;
 import com.badlogic.gdx.utils.Disposable;
-
-import java.util.List;
+import com.badlogic.gdx.utils.reflect.ClassReflection;
+import com.badlogic.gdx.utils.reflect.ReflectionException;
 
 import cz.nic.tablexia.TablexiaSettings;
 import cz.nic.tablexia.bus.ApplicationBus;
 import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
 import cz.nic.tablexia.loader.application.ApplicationFontManager;
 import cz.nic.tablexia.loader.application.ApplicationSoundManager;
+import cz.nic.tablexia.util.Log;
 import cz.nic.tablexia.util.ui.TablexiaNoBlendingImage;
 
 /**
@@ -38,8 +38,6 @@ import cz.nic.tablexia.util.ui.TablexiaNoBlendingImage;
  */
 public abstract class AbstractMenu extends Stack implements Disposable {
 
-    private static final int    MENU_ITEMS_ALIGN = Align.left;
-
     protected enum MenuControlType {
 
         MANUAL      (ApplicationAtlasManager.MAINMENU_BORDER_SWITCH,    true,   false),
@@ -118,7 +116,8 @@ public abstract class AbstractMenu extends Stack implements Disposable {
     private static final int                    OPEN_MENU_BUTTON_HEIGHT = 75;
     private static final int                    OPEN_MENU_BUTTON_TOP_OFFSET = 60;
 
-    private VerticalGroup       menuItemsLayout;
+    protected VerticalGroup       menuItemsLayout;
+    private final Container<Group> layoutContainer;
     private TextButtonStyle     menuButtonStyle;
     private float               menuHidePositionX;
     private float               menuClosePositionX;
@@ -146,7 +145,7 @@ public abstract class AbstractMenu extends Stack implements Disposable {
 
         // menu layout
         menuItemsLayout = new VerticalGroup();
-        Container<Group> layoutContainer = new Container<Group>();
+        layoutContainer = new Container<Group>();
         layoutContainer.setDebug(true, false);
         layoutContainer.setActor(createMenuLayout(menuItemsLayout));
         layoutContainer.align(Align.left);
@@ -230,67 +229,25 @@ public abstract class AbstractMenu extends Stack implements Disposable {
 
 //////////////////////////// MENU ITEMS
 
-    protected abstract List<? extends IMenuItem> getMenuItems();
-
     public void initMenuItems() {
-        menuItemsLayout.clear();
-        menuItemsLayout.align(MENU_ITEMS_ALIGN);
-        menuItemsLayout.fill();
-
-        for (final IMenuItem menuItem : getMenuItems()) {
-            Group menuItemContainer = createMenuItem(menuItem);
-            menuItemContainer.addListener(new ClickListener() {
-                @Override
-                public void clicked(InputEvent event, float x, float y) {
-                    doMenuAction(menuItem.getMenuAction(), true, true);
-                    performMenuAction(menuItem);
-                }
-            });
-            menuItemsLayout.addActor(menuItemContainer);
-            IMenuItem[] subMenu = menuItem.getSubmenu();
-            if (subMenu != null) {
-                for (final IMenuItem submenuItem : subMenu) {
-                    Group submenuItemContainer = createSubMenuItem(submenuItem);
-                    submenuItemContainer.addListener(new ClickListener() {
-                        @Override
-                        public void clicked(InputEvent event, float x, float y) {
-                            doMenuAction(submenuItem.getMenuAction(), true, true);
-                            performMenuAction(submenuItem);
-                        }
-                    });
-                    menuItemsLayout.addActor(submenuItemContainer);
-                }
-            }
-        }
+        initMenuItems(layoutContainer);
     }
 
-    protected Group createMenuItem(final IMenuItem menuItem) {
-        return createDefaultMenuItem(menuItem);
-    }
-
-    protected Group createSubMenuItem(final IMenuItem menuItem) {
-        return createDefaultMenuItem(menuItem);
-    }
-
-    private Group createDefaultMenuItem(final IMenuItem menuItem) {
-        TextButton menuButton = new TextButton(menuItem.getTitle(), menuButtonStyle);
-        menuButton.addListener(new ClickListener() {
-
-            @Override
-            public void clicked(InputEvent event, float x, float y) {
-                doMenuAction(menuItem.getMenuAction(), true, true);
-                performMenuAction(menuItem);
-            }
-
-        });
-
-        return menuButton;
-    }
+    protected abstract void initMenuItems(Container<Group> layoutContainer);
 
     protected void performMenuAction(final IMenuItem menuItem) {
         menuItem.performAction();
     }
 
+    protected Group getGroupForMenuItem(IMenuItem menuItem) {
+        try {
+            return (Group) ClassReflection.getConstructor(menuItem.getItemGroupClass(), IMenuItem.class).newInstance(menuItem);
+        } catch (ReflectionException e) {
+            Log.err(getClass(), "Cannot instantiate menu item group class: " + menuItem.getItemGroupClass(), e);
+        }
+        return null;
+    }
+
 
 //////////////////////////// MENU MOVEMENT
 
@@ -415,7 +372,8 @@ public abstract class AbstractMenu extends Stack implements Disposable {
         }
     }
 
-    void doMenuAction(MenuAction menuAction, boolean animated, boolean force) {
+    // TODO check
+    public void doMenuAction(MenuAction menuAction, boolean animated, boolean force) {
         if (menuAction != null) {
             menuAction.doAction(this, animated, force);
         }
diff --git a/core/src/cz/nic/tablexia/menu/IMenuItem.java b/core/src/cz/nic/tablexia/menu/IMenuItem.java
index 3901fbeb4..b82be6734 100644
--- a/core/src/cz/nic/tablexia/menu/IMenuItem.java
+++ b/core/src/cz/nic/tablexia/menu/IMenuItem.java
@@ -1,11 +1,15 @@
 package cz.nic.tablexia.menu;
 
+import com.badlogic.gdx.scenes.scene2d.Group;
+
 public interface IMenuItem {
 	
 	String 		getTitle();
 	String 		getDescription();
 	void 		performAction();
+	Class<? extends Group> getItemGroupClass();
 	AbstractMenu.MenuAction getMenuAction();
 	IMenuItem[] getSubmenu();
+	String[] getIcons();
 	
 }
diff --git a/core/src/cz/nic/tablexia/menu/game/GameMenuItemGroup.java b/core/src/cz/nic/tablexia/menu/game/GameMenuItemGroup.java
new file mode 100644
index 000000000..f4edf45ba
--- /dev/null
+++ b/core/src/cz/nic/tablexia/menu/game/GameMenuItemGroup.java
@@ -0,0 +1,169 @@
+package cz.nic.tablexia.menu.game;
+
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.Touchable;
+import com.badlogic.gdx.scenes.scene2d.ui.Cell;
+import com.badlogic.gdx.scenes.scene2d.ui.Container;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable;
+import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
+import com.badlogic.gdx.utils.Align;
+
+import net.engio.mbassy.listener.Handler;
+
+import cz.nic.tablexia.TablexiaApplication;
+import cz.nic.tablexia.bus.ApplicationBus;
+import cz.nic.tablexia.game.AbstractTablexiaGame;
+import cz.nic.tablexia.game.GameDefinition;
+import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
+import cz.nic.tablexia.loader.application.ApplicationFontManager;
+import cz.nic.tablexia.menu.IMenuItem;
+import cz.nic.tablexia.screen.gamemenu.GameMenuScreen;
+import cz.nic.tablexia.screen.gamemenu.pages.GameMenuPage;
+
+/**
+ * Created by Matyáš Latner.
+ */
+public class GameMenuItemGroup extends Container<Table> {
+
+    private static final Color  HIGHLITED_COLOR             = new Color(0.780f, 0.698f, 0.600f, 1);
+
+    private static final String TITLE_FONT_TYPE             = ApplicationFontManager.APPLICATION_DEFAULT_FONT_BOLD;
+    private static final Color  TITLE_FONT_COLOR            = new Color(0.325f, 0.278f, 0.255f, 1);
+    private static final float  TITLE_FONT_SCALE            = 0.9f;
+
+    private static final String DESCRIPTION_FONT_TYPE       = ApplicationFontManager.APPLICATION_DEFAULT_FONT_REGULAR;
+    private static final Color  DESCRIPTION_FONT_COLOR      = new Color(0.325f, 0.278f, 0.255f, 1);
+    private static final float  DESCRIPTION_FONT_SCALE      = 0.6f;
+
+    private static final float  LABELS_PADDING_LEFT         = 15f;
+    private static final float  LABELS_PADDING_DEFAULT      = 5f;
+    private static final Color  HIGHLITER_COLOR             = new Color(0.647f, 0.22f, 0.22f, 1);
+    private static final float  ARROW_PADING_RIGHT          = 15f;
+    private static final float  LAYOUT_PADDING              = 2f;
+    private static final float  CONTAINER_BOTTOM_PADDING    = 4f;
+    private static final float  LEFT_PADDING                = 5f;
+
+    private final Table             layoutContainer;
+    private final Image             arrowIcon;
+    private final Image             restartIcon;
+    private final Cell<Image> iconCell;
+    private final Image             highliter;
+    private NinePatchDrawable background;
+    private TextureRegionDrawable   highlitedBackground;
+
+    private Class<? extends AbstractTablexiaGame> abstractTablexiaGameClass;
+    private GameMenuScreen.GameMenuPageDefinition gameMenuPageDefinition;
+
+    public GameMenuItemGroup(IMenuItem menuItem) {
+        this.abstractTablexiaGameClass = ((GameDefinition)menuItem).getScreenClass();
+        this.gameMenuPageDefinition = GameMenuScreen.GameMenuPageDefinition.getGameMenuPageForGameDefinition(GameDefinition.getGameDefinitionForClass(abstractTablexiaGameClass));
+
+        padLeft(LEFT_PADDING);
+        layoutContainer = new Table();
+        layoutContainer.pad(LAYOUT_PADDING);
+        layoutContainer.setTouchable(Touchable.enabled);
+        layoutContainer.addListener(new ClickListener() {
+
+            @Override
+            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
+                setPressed();
+                return super.touchDown(event, x, y, pointer, button);
+            }
+
+            @Override
+            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
+                setUnpressed();
+                super.touchUp(event, x, y, pointer, button);
+            }
+        });
+
+        background          = new NinePatchDrawable(ApplicationAtlasManager.getInstance().getPatch(ApplicationAtlasManager.MAINMENU_CHILDITEM_BACKGROUND));
+        highlitedBackground = new TextureRegionDrawable(ApplicationAtlasManager.getInstance().getColorTextureRegion(HIGHLITED_COLOR));
+
+        fill(true, false);
+        setActor(layoutContainer);
+        padBottom(CONTAINER_BOTTOM_PADDING);
+
+        // highliter
+        highliter = new Image(ApplicationAtlasManager.getInstance().getColorTexture(HIGHLITER_COLOR));
+        layoutContainer.add(highliter);
+
+        // texts
+        Label titleLabel = new Label(menuItem.getTitle(), new Label.LabelStyle(ApplicationFontManager.getInstance().getFont(TITLE_FONT_TYPE), TITLE_FONT_COLOR));
+        titleLabel.setFontScale(TITLE_FONT_SCALE);
+        Label descritopnLabel = new Label(menuItem.getDescription(), new Label.LabelStyle(ApplicationFontManager.getInstance().getFont(DESCRIPTION_FONT_TYPE), DESCRIPTION_FONT_COLOR));
+        descritopnLabel.setFontScale(DESCRIPTION_FONT_SCALE);
+        Table labelsContainer = new Table();
+        labelsContainer.add(titleLabel).align(Align.left);
+        labelsContainer.row();
+        labelsContainer.add(descritopnLabel).align(Align.left);
+        labelsContainer.pad(LABELS_PADDING_DEFAULT, LABELS_PADDING_LEFT, LABELS_PADDING_DEFAULT, LABELS_PADDING_DEFAULT);
+        layoutContainer.add(labelsContainer);
+
+        // arrow
+        arrowIcon = new Image(ApplicationAtlasManager.getInstance().getTextureRegion(ApplicationAtlasManager.MAINMENU_CHILDITEM_ARROW, false));
+        restartIcon = new Image(ApplicationAtlasManager.getInstance().getTextureRegion(ApplicationAtlasManager.MAINMENU_CHILDITEM_RESTART, false));
+        iconCell = layoutContainer.add();
+        iconCell.expandX().align(Align.right).padRight(ARROW_PADING_RIGHT);
+        changeIconToArrow();
+
+        // highliter size
+        highliter.getDrawable().setMinWidth(5);
+        highliter.getDrawable().setMinHeight(layoutContainer.getMinHeight());
+        unhighlite();
+
+        setUnpressed();
+        ApplicationBus.getInstance().subscribe(this);
+    }
+
+    private void highlite() {
+        highliter.setVisible(true);
+    }
+
+    private void unhighlite() {
+        highliter.setVisible(false);
+    }
+
+    private void changeIconToArrow() {
+        restartIcon.remove();
+        iconCell.setActor(arrowIcon);
+    }
+
+    private void changeIconToRestart() {
+        arrowIcon.remove();
+        iconCell.setActor(restartIcon);
+    }
+
+    private void setUnpressed() {
+        layoutContainer.setBackground(background);
+    }
+
+    private void setPressed() {
+        layoutContainer.setBackground(highlitedBackground);
+    }
+
+    @Handler
+    public void onScreenChangedEvent(TablexiaApplication.ScreenChangedEvent screenChangedEvent) {
+        if (screenChangedEvent.getScreenClass() == abstractTablexiaGameClass) {
+            highlite();
+            changeIconToRestart();
+        } else {
+            unhighlite();
+            changeIconToArrow();
+        }
+    }
+
+    @Handler
+    public void onGameMenuPageScrollEvent(GameMenuPage.GameMenuPageScrolledEvent gameMenuPageScrolledEvent) {
+        if (gameMenuPageScrolledEvent.getGameMenuPageDefinition() == gameMenuPageDefinition) {
+            highlite();
+        } else {
+            unhighlite();
+        }
+    }
+}
diff --git a/core/src/cz/nic/tablexia/menu/main/MainMenu.java b/core/src/cz/nic/tablexia/menu/main/MainMenu.java
index ae46883f2..186dfb4ec 100644
--- a/core/src/cz/nic/tablexia/menu/main/MainMenu.java
+++ b/core/src/cz/nic/tablexia/menu/main/MainMenu.java
@@ -4,35 +4,18 @@ import com.badlogic.gdx.graphics.Color;
 import com.badlogic.gdx.graphics.g2d.BitmapFont;
 import com.badlogic.gdx.scenes.scene2d.Group;
 import com.badlogic.gdx.scenes.scene2d.InputEvent;
-import com.badlogic.gdx.scenes.scene2d.Touchable;
-import com.badlogic.gdx.scenes.scene2d.ui.Cell;
 import com.badlogic.gdx.scenes.scene2d.ui.Container;
-import com.badlogic.gdx.scenes.scene2d.ui.Image;
 import com.badlogic.gdx.scenes.scene2d.ui.Label;
 import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
-import com.badlogic.gdx.scenes.scene2d.ui.Stack;
 import com.badlogic.gdx.scenes.scene2d.ui.Table;
 import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
 import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
-import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable;
-import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
 import com.badlogic.gdx.utils.Align;
 
-import net.engio.mbassy.listener.Handler;
-
-import java.util.List;
-
-import cz.nic.tablexia.TablexiaApplication;
 import cz.nic.tablexia.TablexiaSettings;
-import cz.nic.tablexia.bus.ApplicationBus;
-import cz.nic.tablexia.game.AbstractTablexiaGame;
-import cz.nic.tablexia.game.GameDefinition;
-import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
 import cz.nic.tablexia.loader.application.ApplicationFontManager;
 import cz.nic.tablexia.menu.AbstractMenu;
 import cz.nic.tablexia.menu.IMenuItem;
-import cz.nic.tablexia.screen.gamemenu.GameMenuScreen;
-import cz.nic.tablexia.screen.gamemenu.pages.GameMenuPage;
 
 /**
  * MainMenu container
@@ -53,242 +36,6 @@ public class MainMenu extends AbstractMenu {
     private static final float      APP_NAME_TEXT_PADDING_LEFT      = 10f;
     private static final float      APP_NAME_WIDTH_RATIO            = 3f/5;
 
-    private static final Color      HIGHLITED_COLOR         = new Color(0.780f, 0.698f, 0.600f, 1);
-    private static final Color      DIVIDER_COLOR           = new Color(0.780f, 0.698f, 0.600f, 1);
-    private static final int        DIVIDER_WIDTH           = 205;
-
-    private static class MenuItemGroup extends Container<Table> {
-
-        private static final String MENU_ITEM_FONT_TYPE     = ApplicationFontManager.APPLICATION_DEFAULT_FONT_BOLD;
-        private static final Color  MENU_ITEM_FONT_COLOR    = new Color(0.325f, 0.278f, 0.255f, 1);
-        private static final int    ICON_RIGHT_SPACE        = 15;
-        private static final float  ICON_SCALE              = 0.8f;
-
-        private final Image                 iconUnpressedImage;
-        private final Image                 iconPressedImage;
-        private final TextureRegionDrawable highlitedBackground;
-
-        public MenuItemGroup(String iconUnpressed, String iconPressed, String title) {
-            Table layoutTable = new Table();
-            layoutTable.setFillParent(true);
-            setActor(layoutTable);
-            addListener(new ClickListener() {
-
-                @Override
-                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
-                    setPressed();
-                    return super.touchDown(event, x, y, pointer, button);
-                }
-
-                @Override
-                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
-                    setUnpressed();
-                    super.touchUp(event, x, y, pointer, button);
-                }
-            });
-            setTouchable(Touchable.enabled);
-            setUnpressed();
-
-            // highliter
-            highlitedBackground = new TextureRegionDrawable(ApplicationAtlasManager.getInstance().getColorTextureRegion(HIGHLITED_COLOR));
-
-            // icons
-            Stack iconStack = new Stack();
-            layoutTable.add(iconStack);
-            iconPressedImage = createIcon(iconPressed, iconStack);
-            iconUnpressedImage = createIcon(iconUnpressed, iconStack);
-
-            // title
-            if (title != null) {
-                Label label = new Label(title, new Label.LabelStyle(ApplicationFontManager.getInstance().getFont(MENU_ITEM_FONT_TYPE), MENU_ITEM_FONT_COLOR));
-                layoutTable.add(label).expandX().align(Align.left).padLeft(ICON_RIGHT_SPACE);
-            }
-            layoutTable.row();
-
-            // divider
-            Image divider = new Image(ApplicationAtlasManager.getInstance().getColorTexture(DIVIDER_COLOR));
-            divider.getDrawable().setMinWidth(DIVIDER_WIDTH);
-            layoutTable.add();
-            layoutTable.add(divider);
-        }
-
-        @Override
-        protected void setParent(Group parent) {
-            super.setParent(parent);
-            minWidth(parent.getWidth());
-        }
-
-        private Image createIcon(String iconName, Stack iconStack) {
-            Image icon = null;
-            if (iconName != null) {
-                icon = new Image(ApplicationAtlasManager.getInstance().getTextureRegion(iconName));
-                icon.setOrigin(Align.center);
-                icon.setScale(ICON_SCALE);
-                iconStack.add(icon);
-            }
-
-            return icon;
-        }
-
-        public void setUnpressed() {
-            setBackground(null);
-            if (iconUnpressedImage != null) {
-                iconUnpressedImage.setVisible(true);
-            }
-            if (iconPressedImage != null) {
-                iconPressedImage.setVisible(false);
-            }
-        }
-
-        public void setPressed() {
-            setBackground(highlitedBackground);
-            if (iconUnpressedImage != null) {
-                iconUnpressedImage.setVisible(false);
-            }
-            if (iconPressedImage != null) {
-                iconPressedImage.setVisible(true);
-            }
-        }
-    }
-
-    private static class SubMenuItemGroup extends Container<Table> {
-
-        private static final String TITLE_FONT_TYPE             = ApplicationFontManager.APPLICATION_DEFAULT_FONT_BOLD;
-        private static final Color  TITLE_FONT_COLOR            = new Color(0.325f, 0.278f, 0.255f, 1);
-        private static final float  TITLE_FONT_SCALE            = 0.9f;
-
-        private static final String DESCRIPTION_FONT_TYPE       = ApplicationFontManager.APPLICATION_DEFAULT_FONT_REGULAR;
-        private static final Color  DESCRIPTION_FONT_COLOR      = new Color(0.325f, 0.278f, 0.255f, 1);
-        private static final float  DESCRIPTION_FONT_SCALE      = 0.6f;
-
-        private static final float  LABELS_PADDING_LEFT         = 15f;
-        private static final float  LABELS_PADDING_DEFAULT      = 5f;
-        private static final Color  HIGHLITER_COLOR             = new Color(0.647f, 0.22f, 0.22f, 1);
-        private static final float  ARROW_PADING_RIGHT          = 15f;
-        private static final float  LAYOUT_PADDING              = 2f;
-        private static final float  CONTAINER_BOTTOM_PADDING    = 4f;
-        private static final float  LEFT_PADDING                = 5f;
-
-        private final Table             layoutContainer;
-        private final Image             arrowIcon;
-        private final Image             restartIcon;
-        private final Cell<Image>       iconCell;
-        private final Image             highliter;
-        private NinePatchDrawable       background;
-        private TextureRegionDrawable   highlitedBackground;
-
-        private Class<? extends AbstractTablexiaGame> abstractTablexiaGameClass;
-        private GameMenuScreen.GameMenuPageDefinition gameMenuPageDefinition;
-
-        public SubMenuItemGroup(String title, String description, Class<? extends AbstractTablexiaGame> abstractTablexiaGameClass) {
-            this.abstractTablexiaGameClass = abstractTablexiaGameClass;
-            this.gameMenuPageDefinition = GameMenuScreen.GameMenuPageDefinition.getGameMenuPageForGameDefinition(GameDefinition.getGameDefinitionForClass(abstractTablexiaGameClass));
-
-            padLeft(LEFT_PADDING);
-            layoutContainer = new Table();
-            layoutContainer.pad(LAYOUT_PADDING);
-            layoutContainer.setTouchable(Touchable.enabled);
-            layoutContainer.addListener(new ClickListener() {
-
-                @Override
-                public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
-                    setPressed();
-                    return super.touchDown(event, x, y, pointer, button);
-                }
-
-                @Override
-                public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
-                    setUnpressed();
-                    super.touchUp(event, x, y, pointer, button);
-                }
-            });
-
-            background          = new NinePatchDrawable(ApplicationAtlasManager.getInstance().getPatch(ApplicationAtlasManager.MAINMENU_CHILDITEM_BACKGROUND));
-            highlitedBackground = new TextureRegionDrawable(ApplicationAtlasManager.getInstance().getColorTextureRegion(HIGHLITED_COLOR));
-
-            fill(true, false);
-            setActor(layoutContainer);
-            padBottom(CONTAINER_BOTTOM_PADDING);
-
-            // highliter
-            highliter = new Image(ApplicationAtlasManager.getInstance().getColorTexture(HIGHLITER_COLOR));
-            layoutContainer.add(highliter);
-
-            // texts
-            Label titleLabel = new Label(title, new Label.LabelStyle(ApplicationFontManager.getInstance().getFont(TITLE_FONT_TYPE), TITLE_FONT_COLOR));
-            titleLabel.setFontScale(TITLE_FONT_SCALE);
-            Label descritopnLabel = new Label(description, new Label.LabelStyle(ApplicationFontManager.getInstance().getFont(DESCRIPTION_FONT_TYPE), DESCRIPTION_FONT_COLOR));
-            descritopnLabel.setFontScale(DESCRIPTION_FONT_SCALE);
-            Table labelsContainer = new Table();
-            labelsContainer.add(titleLabel).align(Align.left);
-            labelsContainer.row();
-            labelsContainer.add(descritopnLabel).align(Align.left);
-            labelsContainer.pad(LABELS_PADDING_DEFAULT, LABELS_PADDING_LEFT, LABELS_PADDING_DEFAULT, LABELS_PADDING_DEFAULT);
-            layoutContainer.add(labelsContainer);
-
-            // arrow
-            arrowIcon = new Image(ApplicationAtlasManager.getInstance().getTextureRegion(ApplicationAtlasManager.MAINMENU_CHILDITEM_ARROW, false));
-            restartIcon = new Image(ApplicationAtlasManager.getInstance().getTextureRegion(ApplicationAtlasManager.MAINMENU_CHILDITEM_RESTART, false));
-            iconCell = layoutContainer.add();
-            iconCell.expandX().align(Align.right).padRight(ARROW_PADING_RIGHT);
-            changeIconToArrow();
-
-            // highliter size
-            highliter.getDrawable().setMinWidth(5);
-            highliter.getDrawable().setMinHeight(layoutContainer.getMinHeight());
-            unhighlite();
-
-            setUnpressed();
-            ApplicationBus.getInstance().subscribe(this);
-        }
-
-        private void highlite() {
-            highliter.setVisible(true);
-        }
-
-        private void unhighlite() {
-            highliter.setVisible(false);
-        }
-
-        private void changeIconToArrow() {
-            restartIcon.remove();
-            iconCell.setActor(arrowIcon);
-        }
-
-        private void changeIconToRestart() {
-            arrowIcon.remove();
-            iconCell.setActor(restartIcon);
-        }
-
-        private void setUnpressed() {
-            layoutContainer.setBackground(background);
-        }
-
-        private void setPressed() {
-            layoutContainer.setBackground(highlitedBackground);
-        }
-
-        @Handler
-        public void onScreenChangedEvent(TablexiaApplication.ScreenChangedEvent screenChangedEvent) {
-            if (screenChangedEvent.getScreenClass() == abstractTablexiaGameClass) {
-                highlite();
-                changeIconToRestart();
-            } else {
-                unhighlite();
-                changeIconToArrow();
-            }
-        }
-
-        @Handler
-        public void onGameMenuPageScrollEvent(GameMenuPage.GameMenuPageScrolledEvent gameMenuPageScrolledEvent) {
-            if (gameMenuPageScrolledEvent.getGameMenuPageDefinition() == gameMenuPageDefinition) {
-                highlite();
-            } else {
-                unhighlite();
-            }
-        }
-    }
-
     public MainMenu(Float width, Float height) {
         super(width, height);
     }
@@ -325,15 +72,35 @@ public class MainMenu extends AbstractMenu {
     }
 
     @Override
-    protected Group createMenuItem(IMenuItem menuItem) {
-        MainMenuDefinition mainMenuDefinition = (MainMenuDefinition) menuItem;
-        return new MenuItemGroup(mainMenuDefinition.getIconUnpressed(), mainMenuDefinition.getIconPressed(), menuItem.getTitle());
-    }
+    public void initMenuItems(Container<Group> layoutContainer) {
+        menuItemsLayout.clear();
+        menuItemsLayout.fill();
 
-    @Override
-    protected Group createSubMenuItem(IMenuItem menuItem) {
-        GameDefinition gameDefinition = ((GameDefinition) menuItem);
-        return new SubMenuItemGroup(gameDefinition.getTitle(), gameDefinition.getDescription(), gameDefinition.getScreenClass());
+        for (final IMenuItem mainMenuDefinition : MainMenuDefinition.getItemsForMenu()) {
+            Group menuItemContainer = getGroupForMenuItem(mainMenuDefinition);
+            menuItemContainer.addListener(new ClickListener() {
+                @Override
+                public void clicked(InputEvent event, float x, float y) {
+                    doMenuAction(mainMenuDefinition.getMenuAction(), true, true);
+                    performMenuAction(mainMenuDefinition);
+                }
+            });
+            menuItemsLayout.addActor(menuItemContainer);
+            IMenuItem[] subMenu = mainMenuDefinition.getSubmenu();
+            if (subMenu != null) {
+                for (final IMenuItem submenuItem : subMenu) {
+                    Group submenuItemContainer = getGroupForMenuItem(submenuItem);
+                    submenuItemContainer.addListener(new ClickListener() {
+                        @Override
+                        public void clicked(InputEvent event, float x, float y) {
+                            doMenuAction(submenuItem.getMenuAction(), true, true);
+                            performMenuAction(submenuItem);
+                        }
+                    });
+                    menuItemsLayout.addActor(submenuItemContainer);
+                }
+            }
+        }
     }
 
     @Override
@@ -346,9 +113,4 @@ public class MainMenu extends AbstractMenu {
         return MenuControlType.MANUAL;
     }
 
-    @Override
-    protected List<? extends IMenuItem> getMenuItems() {
-        return MainMenuDefinition.getItemsForMenu();
-    }
-
 }
diff --git a/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java b/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java
index bb133282d..c726609cd 100644
--- a/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java
+++ b/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java
@@ -1,5 +1,7 @@
 package cz.nic.tablexia.menu.main;
 
+import com.badlogic.gdx.scenes.scene2d.Group;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -22,12 +24,12 @@ import cz.nic.tablexia.screen.viewport.ViewportDebugScreen;
 
 public enum MainMenuDefinition implements IMenuItem {
 
-	GAMES				(false, ApplicationAtlasManager.MAINMENU_ICON_GAMES_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_GAMES_PRESSED, "mainmenu_games", GameDefinition.values(), null, null), // TODO open menu event
-	HALL_OF_FAME		(false, ApplicationAtlasManager.MAINMENU_ICON_HALLOFFAME_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_HALLOFFAME_PRESSED, "mainmenu_halloffame", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(HallOfFameScreen.class,     TablexiaApplication.ScreenTransaction.FADE)),
-	STATISTICS			(false, ApplicationAtlasManager.MAINMENU_ICON_STATISTICS_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_STATISTICS_PRESSED, "mainmenu_statistics", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(StatisticsScreen.class,     TablexiaApplication.ScreenTransaction.FADE)),
-	ENCYCLOPEDIA		(false, ApplicationAtlasManager.MAINMENU_ICON_ENCYCLOPEDIA_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_ENCYCLOPEDIA_PRESSED, "mainmenu_encyclopedia", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(EncyclopediaScreen.class,   TablexiaApplication.ScreenTransaction.FADE)),
-	ABOUT_APPLICATION	(false, ApplicationAtlasManager.MAINMENU_ICON_ABOUT_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_ABOUT_PRESSED, "mainmenu_about", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(AboutScreen.class,          TablexiaApplication.ScreenTransaction.FADE)),
-	LOGOUT				(false, ApplicationAtlasManager.MAINMENU_ICON_LOGOUT_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_LOGOUT_PRESSED, "mainmenu_logout", null, AbstractMenu.MenuAction.HIDE,  null) {
+	GAMES				(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_GAMES_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_GAMES_PRESSED}, "mainmenu_games", GameDefinition.values(), null, null), // TODO open menu event
+	HALL_OF_FAME		(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_HALLOFFAME_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_HALLOFFAME_PRESSED}, "mainmenu_halloffame", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(HallOfFameScreen.class,     TablexiaApplication.ScreenTransaction.FADE)),
+	STATISTICS			(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_STATISTICS_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_STATISTICS_PRESSED}, "mainmenu_statistics", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(StatisticsScreen.class,     TablexiaApplication.ScreenTransaction.FADE)),
+	ENCYCLOPEDIA		(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_ENCYCLOPEDIA_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_ENCYCLOPEDIA_PRESSED}, "mainmenu_encyclopedia", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(EncyclopediaScreen.class,   TablexiaApplication.ScreenTransaction.FADE)),
+	ABOUT_APPLICATION	(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_ABOUT_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_ABOUT_PRESSED}, "mainmenu_about", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(AboutScreen.class,          TablexiaApplication.ScreenTransaction.FADE)),
+	LOGOUT				(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_LOGOUT_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_LOGOUT_PRESSED}, "mainmenu_logout", null, AbstractMenu.MenuAction.HIDE,  null) {
 
 		@Override
 		public void performAction() {
@@ -35,20 +37,20 @@ public enum MainMenuDefinition implements IMenuItem {
 			ApplicationBus.getInstance().post(new Tablexia.ChangeScreenEvent(TablexiaSettings.LOADER_SCREEN, TablexiaApplication.ScreenTransaction.FADE)).asynchronously();
 		}
 	},
-    SCREEN_DEBUG    	(true, ApplicationAtlasManager.MAINMENU_ICON_ABOUT_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_ABOUT_PRESSED, "mainmenu_screendebug", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(ViewportDebugScreen.class, TablexiaApplication.ScreenTransaction.FADE));
+    SCREEN_DEBUG    	(true, new String[]{ApplicationAtlasManager.MAINMENU_ICON_ABOUT_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_ABOUT_PRESSED}, "mainmenu_screendebug", null, AbstractMenu.MenuAction.CLOSE, new Tablexia.ChangeScreenEvent(ViewportDebugScreen.class, TablexiaApplication.ScreenTransaction.FADE));
+
+	private static final Class<MainMenuItemGroup> MENU_ITEM_GROUP_CLASS = MainMenuItemGroup.class;
 
-    private boolean debug;
-	private String iconUnpressed;
-	private String iconPressed;
+	private boolean debug;
+	private String[] icons;
 	private String menuTextKey;
 	private IMenuItem[] submenu;
 	private AbstractMenu.MenuAction menuAction;
 	private ApplicationEvent action;
 
-	MainMenuDefinition(boolean debug, String iconUnpressed, String iconPressed, String nameResource, IMenuItem[] submenu, AbstractMenu.MenuAction menuAction, ApplicationEvent action) {
+	MainMenuDefinition(boolean debug, String[] icons, String nameResource, IMenuItem[] submenu, AbstractMenu.MenuAction menuAction, ApplicationEvent action) {
         this.debug = debug;
-		this.iconUnpressed = iconUnpressed;
-		this.iconPressed = iconPressed;
+		this.icons = icons;
 		this.menuTextKey = nameResource;
 		this.submenu = submenu;
 		this.menuAction = menuAction;
@@ -70,16 +72,17 @@ public enum MainMenuDefinition implements IMenuItem {
 	}
 
 	@Override
-	public void performAction() {
-		ApplicationBus.getInstance().publishAsync(this.getAction());
+	public Class<? extends Group> getItemGroupClass() {
+		return MENU_ITEM_GROUP_CLASS;
 	}
 
-	public String getIconUnpressed() {
-		return iconUnpressed;
+	@Override
+	public void performAction() {
+		ApplicationBus.getInstance().publishAsync(this.getAction());
 	}
 
-	public String getIconPressed() {
-		return iconPressed;
+	public String[] getIcons() {
+		return icons;
 	}
 
 	public IMenuItem[] getSubmenu() {
@@ -91,8 +94,8 @@ public enum MainMenuDefinition implements IMenuItem {
 		return menuAction;
 	}
 
-    public static List<IMenuItem> getItemsForMenu() {
-        List<IMenuItem> mainMenu = new ArrayList<IMenuItem>();
+    public static List<MainMenuDefinition> getItemsForMenu() {
+        List<MainMenuDefinition> mainMenu = new ArrayList<MainMenuDefinition>();
         for (MainMenuDefinition mainMenuDefinition : MainMenuDefinition.values()) {
             if (TablexiaSettings.getInstance().isDebug() || !mainMenuDefinition.debug) {
                 mainMenu.add(mainMenuDefinition);
diff --git a/core/src/cz/nic/tablexia/menu/main/MainMenuItemGroup.java b/core/src/cz/nic/tablexia/menu/main/MainMenuItemGroup.java
new file mode 100644
index 000000000..0aa14ac68
--- /dev/null
+++ b/core/src/cz/nic/tablexia/menu/main/MainMenuItemGroup.java
@@ -0,0 +1,128 @@
+package cz.nic.tablexia.menu.main;
+
+import com.badlogic.gdx.graphics.Color;
+import com.badlogic.gdx.scenes.scene2d.Group;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
+import com.badlogic.gdx.scenes.scene2d.Touchable;
+import com.badlogic.gdx.scenes.scene2d.ui.Container;
+import com.badlogic.gdx.scenes.scene2d.ui.Image;
+import com.badlogic.gdx.scenes.scene2d.ui.Label;
+import com.badlogic.gdx.scenes.scene2d.ui.Stack;
+import com.badlogic.gdx.scenes.scene2d.ui.Table;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
+import com.badlogic.gdx.utils.Align;
+
+import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
+import cz.nic.tablexia.loader.application.ApplicationFontManager;
+import cz.nic.tablexia.menu.IMenuItem;
+
+/**
+ * Created by Matyáš Latner.
+ */
+public class MainMenuItemGroup extends Container<Table> {
+
+    private static final Color      HIGHLITED_COLOR         = new Color(0.780f, 0.698f, 0.600f, 1);
+    private static final Color      DIVIDER_COLOR           = new Color(0.780f, 0.698f, 0.600f, 1);
+    private static final int        DIVIDER_WIDTH           = 205;
+
+    private static final String     MENU_ITEM_FONT_TYPE     = ApplicationFontManager.APPLICATION_DEFAULT_FONT_BOLD;
+    private static final Color      MENU_ITEM_FONT_COLOR    = new Color(0.325f, 0.278f, 0.255f, 1);
+    private static final int        ICON_RIGHT_SPACE        = 15;
+    private static final float      ICON_SCALE              = 0.8f;
+
+    private Image iconUnpressedImage;
+    private Image iconPressedImage;
+
+    private final TextureRegionDrawable highlitedBackground;
+
+    public MainMenuItemGroup(IMenuItem menuItem) {
+        Table layoutTable = new Table();
+        layoutTable.setFillParent(true);
+        setActor(layoutTable);
+        addListener(new ClickListener() {
+
+            @Override
+            public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
+                setPressed();
+                return super.touchDown(event, x, y, pointer, button);
+            }
+
+            @Override
+            public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
+                setUnpressed();
+                super.touchUp(event, x, y, pointer, button);
+            }
+        });
+        setTouchable(Touchable.enabled);
+
+        // highliter
+        highlitedBackground = new TextureRegionDrawable(ApplicationAtlasManager.getInstance().getColorTextureRegion(HIGHLITED_COLOR));
+
+        // icons
+        Stack iconStack = new Stack();
+        layoutTable.add(iconStack);
+        String[] menuItemIcons = menuItem.getIcons();
+        if (menuItemIcons != null) {
+            if (menuItemIcons.length > 0) {
+                iconUnpressedImage = createIcon(menuItemIcons[0], iconStack);
+            }
+            if (menuItemIcons.length > 1) {
+                iconPressedImage = createIcon(menuItemIcons[1], iconStack);
+            }
+        }
+        setUnpressed();
+
+        // title
+        String menuItemTitle = menuItem.getTitle();
+        if (menuItemTitle != null) {
+            Label label = new Label(menuItemTitle, new Label.LabelStyle(ApplicationFontManager.getInstance().getFont(MENU_ITEM_FONT_TYPE), MENU_ITEM_FONT_COLOR));
+            layoutTable.add(label).expandX().align(Align.left).padLeft(ICON_RIGHT_SPACE);
+        }
+        layoutTable.row();
+
+        // divider
+        Image divider = new Image(ApplicationAtlasManager.getInstance().getColorTexture(DIVIDER_COLOR));
+        divider.getDrawable().setMinWidth(DIVIDER_WIDTH);
+        layoutTable.add();
+        layoutTable.add(divider);
+    }
+
+    @Override
+    protected void setParent(Group parent) {
+        super.setParent(parent);
+        minWidth(parent.getWidth());
+    }
+
+    private Image createIcon(String iconName, Stack iconStack) {
+        Image icon = null;
+        if (iconName != null) {
+            icon = new Image(ApplicationAtlasManager.getInstance().getTextureRegion(iconName));
+            icon.setOrigin(Align.center);
+            icon.setScale(ICON_SCALE);
+            iconStack.add(icon);
+        }
+
+        return icon;
+    }
+
+    public void setUnpressed() {
+        setBackground(null);
+        if (iconUnpressedImage != null) {
+            iconUnpressedImage.setVisible(true);
+        }
+        if (iconPressedImage != null) {
+            iconPressedImage.setVisible(false);
+        }
+    }
+
+    public void setPressed() {
+        setBackground(highlitedBackground);
+        if (iconUnpressedImage != null) {
+            iconUnpressedImage.setVisible(false);
+        }
+        if (iconPressedImage != null) {
+            iconPressedImage.setVisible(true);
+        }
+    }
+}
diff --git a/core/src/cz/nic/tablexia/menu/main/LocaleSelectBox.java b/core/src/cz/nic/tablexia/menu/main/locale/LocaleSelectBox.java
similarity index 99%
rename from core/src/cz/nic/tablexia/menu/main/LocaleSelectBox.java
rename to core/src/cz/nic/tablexia/menu/main/locale/LocaleSelectBox.java
index a9b4fe4a7..92d8f9eda 100644
--- a/core/src/cz/nic/tablexia/menu/main/LocaleSelectBox.java
+++ b/core/src/cz/nic/tablexia/menu/main/locale/LocaleSelectBox.java
@@ -1,4 +1,4 @@
-package cz.nic.tablexia.menu.main;
+package cz.nic.tablexia.menu.main.locale;
 
 import com.badlogic.gdx.graphics.Color;
 import com.badlogic.gdx.graphics.g2d.Batch;
diff --git a/core/src/cz/nic/tablexia/menu/main/UserSelectBox.java b/core/src/cz/nic/tablexia/menu/main/user/UserSelectBox.java
similarity index 97%
rename from core/src/cz/nic/tablexia/menu/main/UserSelectBox.java
rename to core/src/cz/nic/tablexia/menu/main/user/UserSelectBox.java
index ac91ea503..3f6501c39 100644
--- a/core/src/cz/nic/tablexia/menu/main/UserSelectBox.java
+++ b/core/src/cz/nic/tablexia/menu/main/user/UserSelectBox.java
@@ -1,4 +1,4 @@
-package cz.nic.tablexia.menu.main;
+package cz.nic.tablexia.menu.main.user;
 
 import com.badlogic.gdx.graphics.Color;
 import com.badlogic.gdx.graphics.g2d.Batch;
@@ -23,6 +23,7 @@ import cz.nic.tablexia.bus.ApplicationBus;
 import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
 import cz.nic.tablexia.loader.application.ApplicationFontManager;
 import cz.nic.tablexia.loader.application.ApplicationTextManager;
+import cz.nic.tablexia.menu.IMenuItem;
 import cz.nic.tablexia.model.User;
 import cz.nic.tablexia.screen.createuser.PanoramaScreen;
 import cz.nic.tablexia.util.ui.AbstractTablexiaSelectBox;
@@ -64,8 +65,8 @@ public class UserSelectBox extends AbstractTablexiaSelectBox<UserSelectBox.IUser
         private final TextureRegionDrawable image;
         private final User                  user;
 
-        public UserItem(User user) {
-            this.user = user;
+        public UserItem(IMenuItem menuItem) {
+            this.user = (User) menuItem;
 
             background = ApplicationAtlasManager.getInstance().getPatch(ApplicationAtlasManager.USERMENU_MENUITEM_BACKGROUND);
             font = ApplicationFontManager.getInstance().getDefaultApplicationRegularFont();
diff --git a/core/src/cz/nic/tablexia/menu/user/UserMenu.java b/core/src/cz/nic/tablexia/menu/user/UserMenu.java
index 46a848512..2fc83b6d4 100644
--- a/core/src/cz/nic/tablexia/menu/user/UserMenu.java
+++ b/core/src/cz/nic/tablexia/menu/user/UserMenu.java
@@ -1,19 +1,18 @@
 package cz.nic.tablexia.menu.user;
 
 import com.badlogic.gdx.scenes.scene2d.Group;
+import com.badlogic.gdx.scenes.scene2d.InputEvent;
 import com.badlogic.gdx.scenes.scene2d.ui.Container;
 import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
 import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
+import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
+import com.badlogic.gdx.utils.Align;
 
 import net.engio.mbassy.listener.Handler;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import cz.nic.tablexia.bus.ApplicationBus;
 import cz.nic.tablexia.menu.AbstractMenu;
 import cz.nic.tablexia.menu.IMenuItem;
-import cz.nic.tablexia.menu.main.UserSelectBox;
 import cz.nic.tablexia.model.User;
 
 /**
@@ -60,18 +59,23 @@ public class UserMenu extends AbstractMenu {
     }
 
     @Override
-    protected List<? extends IMenuItem> getMenuItems() {
-        List<IMenuItem> userMenuItems = new ArrayList<IMenuItem>();
-        userMenuItems.addAll(User.selectActiveUsers());
-        return userMenuItems;
-    }
-
-    @Override
-    protected Group createMenuItem(IMenuItem menuItem) {
-        UserSelectBox.UserItem userItem = new UserSelectBox.UserItem((User) menuItem);
-        userItem.setSize(getBackground().getWidth(), 100);
-        setDebug(true, true);
-        return userItem;
+    public void initMenuItems(Container<Group> layoutContainer) {
+        menuItemsLayout.clear();
+        menuItemsLayout.align(Align.left);
+        menuItemsLayout.fill();
+
+        for (final IMenuItem menuItem : User.selectActiveUsers()) {
+            Group userItemGroup = getGroupForMenuItem(menuItem);
+            userItemGroup.setSize(getBackground().getWidth(), 100);
+            userItemGroup.addListener(new ClickListener() {
+                @Override
+                public void clicked(InputEvent event, float x, float y) {
+                    doMenuAction(menuItem.getMenuAction(), true, true);
+                    performMenuAction(menuItem);
+                }
+            });
+            menuItemsLayout.addActor(userItemGroup);
+        }
     }
 
     @Handler
diff --git a/core/src/cz/nic/tablexia/model/User.java b/core/src/cz/nic/tablexia/model/User.java
index 6b10477f2..8015c8917 100644
--- a/core/src/cz/nic/tablexia/model/User.java
+++ b/core/src/cz/nic/tablexia/model/User.java
@@ -1,5 +1,7 @@
 package cz.nic.tablexia.model;
 
+import com.badlogic.gdx.scenes.scene2d.Group;
+
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -11,6 +13,7 @@ import cz.nic.tablexia.TablexiaStorage;
 import cz.nic.tablexia.bus.ApplicationBus;
 import cz.nic.tablexia.game.GameDefinition;
 import cz.nic.tablexia.game.difficulty.GameDifficulty;
+import cz.nic.tablexia.menu.main.user.UserSelectBox;
 import cz.nic.tablexia.menu.user.UserMenu;
 import cz.nic.tablexia.model.game.Game;
 import cz.nic.tablexia.util.Log;
@@ -20,6 +23,8 @@ import cz.nic.tablexia.util.Log;
  */
 public class User extends UserMenu.UserMenuItem {
 
+    private static final Class<UserSelectBox.UserItem> USER_ITEM_CLASS = UserSelectBox.UserItem.class;
+
     public enum Gender {
         FEMALE(0),
         MALE(1);
@@ -115,6 +120,17 @@ public class User extends UserMenu.UserMenuItem {
         return null;
     }
 
+    @Override
+    public String[] getIcons() {
+        // TODO return user avatar
+        return null;
+    }
+
+    @Override
+    public Class<? extends Group> getItemGroupClass() {
+        return USER_ITEM_CLASS;
+    }
+
     @Override
     public void performAction() {
         TablexiaSettings.getInstance().setSelectedUser(this);
-- 
GitLab