From 51fd5b31bb16471136967abc1a37e6cefc4c2fce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maty=C3=A1=C5=A1=20Latner?= <matyas.latner@nic.cz>
Date: Thu, 29 Oct 2015 14:19:35 +0100
Subject: [PATCH] #58 Ability to open and close submenus

---
 .../bus/event/SubMenuControlEvent.java        | 46 ++++++++++++++++
 core/src/cz/nic/tablexia/menu/IMenuItem.java  |  2 +-
 .../cz/nic/tablexia/menu/main/MainMenu.java   | 52 ++++++++++++++++---
 .../menu/main/MainMenuDefinition.java         |  9 +++-
 4 files changed, 100 insertions(+), 9 deletions(-)
 create mode 100644 core/src/cz/nic/tablexia/bus/event/SubMenuControlEvent.java

diff --git a/core/src/cz/nic/tablexia/bus/event/SubMenuControlEvent.java b/core/src/cz/nic/tablexia/bus/event/SubMenuControlEvent.java
new file mode 100644
index 000000000..de2911f39
--- /dev/null
+++ b/core/src/cz/nic/tablexia/bus/event/SubMenuControlEvent.java
@@ -0,0 +1,46 @@
+package cz.nic.tablexia.bus.event;
+
+import cz.nic.tablexia.bus.ApplicationBus;
+import cz.nic.tablexia.menu.AbstractMenu;
+import cz.nic.tablexia.menu.IMenuItem;
+
+public class SubMenuControlEvent implements ApplicationBus.ApplicationEvent {
+
+    public enum SubMenuAction {
+        OPEN    (false),
+        CLOSE   (true),
+        TOGGLE  (null);
+
+        private Boolean isOpen;
+
+        SubMenuAction(Boolean isOpen) {
+            this.isOpen = isOpen;
+        }
+
+        public boolean isOpen(boolean isMenuOpenNow) {
+            return isOpen != null ? isOpen : !isMenuOpenNow;
+        }
+    }
+
+    private Class<? extends AbstractMenu>   menu;
+    private IMenuItem                       menuItem;
+    private SubMenuAction subMenuAction;
+
+    public SubMenuControlEvent(Class<? extends AbstractMenu> menu, IMenuItem menuItem, SubMenuAction subMenuAction) {
+        this.menu           = menu;
+        this.menuItem       = menuItem;
+        this.subMenuAction = subMenuAction;
+    }
+
+    public Class<? extends AbstractMenu> getMenu() {
+        return menu;
+    }
+
+    public IMenuItem getMenuItem() {
+        return menuItem;
+    }
+
+    public SubMenuAction getSubMenuAction() {
+        return subMenuAction;
+    }
+}
diff --git a/core/src/cz/nic/tablexia/menu/IMenuItem.java b/core/src/cz/nic/tablexia/menu/IMenuItem.java
index b82be6734..152a2e768 100644
--- a/core/src/cz/nic/tablexia/menu/IMenuItem.java
+++ b/core/src/cz/nic/tablexia/menu/IMenuItem.java
@@ -3,7 +3,7 @@ package cz.nic.tablexia.menu;
 import com.badlogic.gdx.scenes.scene2d.Group;
 
 public interface IMenuItem {
-	
+
 	String 		getTitle();
 	String 		getDescription();
 	void 		performAction();
diff --git a/core/src/cz/nic/tablexia/menu/main/MainMenu.java b/core/src/cz/nic/tablexia/menu/main/MainMenu.java
index 5e9605dce..ee6074e63 100644
--- a/core/src/cz/nic/tablexia/menu/main/MainMenu.java
+++ b/core/src/cz/nic/tablexia/menu/main/MainMenu.java
@@ -12,7 +12,14 @@ 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.HashMap;
+import java.util.Map;
+
 import cz.nic.tablexia.TablexiaSettings;
+import cz.nic.tablexia.bus.ApplicationBus;
+import cz.nic.tablexia.bus.event.SubMenuControlEvent;
 import cz.nic.tablexia.loader.application.ApplicationFontManager;
 import cz.nic.tablexia.menu.AbstractMenu;
 import cz.nic.tablexia.menu.IMenuItem;
@@ -33,7 +40,7 @@ public class MainMenu extends AbstractMenu {
     private static final float      SCROLLBAR_PADDING_BOTTOM        = 10f;
     private static final float      SCROLLBAR_PADDING_TOP           = 10f;
     private static final int        SELECTBOX_USER_HEIGHT           = 70;
-    private static final int        SELECTBOX_LOCALE_HEIGHT         = 30;
+    private static final int        SELECTBOX_LOCALE_HEIGHT         = 40;
     private static final float      SELECTBOX_LOCALE_TEXT_SCALE     = 0.65f;
     private static final float      SELECTBOX_LOCALE_WIDTH_RATIO    = 2f/5;
     private static final int        APP_NAME_TEXT_ALIGN             = Align.left;
@@ -41,8 +48,12 @@ 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 Map<IMenuItem, Group>   subMenus = new HashMap<IMenuItem, Group>();
+    private VerticalGroup           menuItemsLayout;
+
     public MainMenu(Float width, Float height) {
         super(width, height);
+        ApplicationBus.getInstance().subscribe(this);
     }
 
     @Override
@@ -57,22 +68,23 @@ public class MainMenu extends AbstractMenu {
 
     @Override
     public void initMenuItems(Container<Group> layoutContainer) {
-        VerticalGroup menuItemsLayout = new VerticalGroup();
+        subMenus.clear();
+        menuItemsLayout = new VerticalGroup();
         menuItemsLayout.fill();
 
         Table layoutTable = new Table();
+        layoutTable.setFillParent(true);
         layoutTable.pad(MAINMENU_PADDING);
         BitmapFont font = ApplicationFontManager.getInstance().getDefaultApplicationRegularFont();
 
         // User SelectBox
-        layoutTable.add(new UserSelectBox(SELECTBOX_USER_HEIGHT)).expand().fill();
+        layoutTable.add(new UserSelectBox(SELECTBOX_USER_HEIGHT)).fillX();
         layoutTable.row();
 
         // Menu ScrollPane
         ScrollPane scrollPane = new ScrollPane(menuItemsLayout);
         scrollPane.setScrollingDisabled(true, false);
-        layoutTable.add(scrollPane).expand().fill().padBottom(SCROLLBAR_PADDING_BOTTOM).padTop(SCROLLBAR_PADDING_TOP);
-        layoutTable.setFillParent(true);
+        layoutTable.add(scrollPane).fill().padBottom(SCROLLBAR_PADDING_BOTTOM).padTop(SCROLLBAR_PADDING_TOP).expandY();
         layoutTable.row();
 
         // Locale SelectBox and App name
@@ -84,7 +96,7 @@ public class MainMenu extends AbstractMenu {
         appName.setFontScale(APP_NAME_TEXT_SCALE);
         appName.setWrap(true);
         footerTable.add(appName).width(footerContentWidth * APP_NAME_WIDTH_RATIO).padLeft(APP_NAME_TEXT_PADDING_LEFT);
-        layoutTable.add(footerTable).expand().fill();
+        layoutTable.add(footerTable).fillX();
 
 
         for (final IMenuItem mainMenuDefinition : MainMenuDefinition.getItemsForMenu()) {
@@ -99,6 +111,10 @@ public class MainMenu extends AbstractMenu {
             menuItemsLayout.addActor(menuItemContainer);
             IMenuItem[] subMenu = mainMenuDefinition.getSubmenu();
             if (subMenu != null) {
+                VerticalGroup subMenuLayout = new VerticalGroup();
+                subMenus.put(mainMenuDefinition, subMenuLayout);
+                menuItemsLayout.addActor(subMenuLayout);
+                subMenuLayout.fill();
                 for (final IMenuItem submenuItem : subMenu) {
                     Group submenuItemContainer = getGroupForMenuItem(submenuItem);
                     submenuItemContainer.addListener(new ClickListener() {
@@ -108,11 +124,33 @@ public class MainMenu extends AbstractMenu {
                             performMenuAction(submenuItem);
                         }
                     });
-                    menuItemsLayout.addActor(submenuItemContainer);
+                    subMenuLayout.addActor(submenuItemContainer);
                 }
             }
         }
 
+        layoutContainer.align(Align.bottom);
         layoutContainer.setActor(layoutTable);
     }
+
+    @Override
+    public void dispose() {
+        super.dispose();
+        ApplicationBus.getInstance().unsubscribe(this);
+    }
+
+
+//////////////////////////// SUBMENU CONTROL EVENT HANDLING
+
+    @Handler
+    public void onSubMenuControlEvent(SubMenuControlEvent subMenuControlEvent) {
+        Group subMenu = subMenus.get(subMenuControlEvent.getMenuItem());
+        if (subMenu != null) {
+            if (subMenuControlEvent.getSubMenuAction().isOpen(subMenu.hasParent()) && !subMenu.hasParent()) {
+                menuItemsLayout.addActorAt(((MainMenuDefinition) subMenuControlEvent.getMenuItem()).ordinal() + 1, subMenu);
+            } else {
+                subMenu.remove();
+            }
+        }
+    }
 }
diff --git a/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java b/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java
index 13b2e3207..f119c6619 100644
--- a/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java
+++ b/core/src/cz/nic/tablexia/menu/main/MainMenuDefinition.java
@@ -10,6 +10,7 @@ import cz.nic.tablexia.TablexiaApplication;
 import cz.nic.tablexia.TablexiaSettings;
 import cz.nic.tablexia.bus.ApplicationBus;
 import cz.nic.tablexia.bus.ApplicationBus.ApplicationEvent;
+import cz.nic.tablexia.bus.event.SubMenuControlEvent;
 import cz.nic.tablexia.loader.application.ApplicationAtlasManager;
 import cz.nic.tablexia.loader.application.ApplicationTextManager;
 import cz.nic.tablexia.menu.AbstractMenu;
@@ -24,7 +25,13 @@ import cz.nic.tablexia.screen.viewport.ViewportDebugScreen;
 
 public enum MainMenuDefinition implements IMenuItem {
 
-	GAMES				(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_GAMES_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_GAMES_PRESSED}, "mainmenu_games", GameMenuDefinition.values(), null, null), // TODO open menu event
+	GAMES				(false, new String[]{ApplicationAtlasManager.MAINMENU_ICON_GAMES_UNPRESSED, ApplicationAtlasManager.MAINMENU_ICON_GAMES_PRESSED}, "mainmenu_games", GameMenuDefinition.values(), null, null) {
+
+		@Override
+		public void performAction() {
+			ApplicationBus.getInstance().post(new SubMenuControlEvent(MainMenu.class, this, SubMenuControlEvent.SubMenuAction.TOGGLE)).asynchronously();
+		}
+	},
 	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)),
-- 
GitLab