Solved GUI with multiple pages

Discussion in 'Spigot Plugin Development' started by Nort721, Jun 5, 2018.

  1. so, I am working on a plugin of Town voting, you have a towny server and every time that a player creates a town it will automatically add the town to the voting GUI, the plugin is creating a file for every town where it saves all the data about every town.
    the GUI looks like this:
    pic.PNG


    but I have one problem I want the user to be able to add an infinite amount of towns so I want to make a paging system to the GUI so every time the plugin loads the towns from the files to the town array list and then when creating the GUI it will create the number of pages that needed.
    also will need to create buttons to navigate between pages

    here is the GUI creating code:
    Code (Text):

        public static void openVotingGui(Player p) {
            Inventory inv = Bukkit.createInventory(null, ConfigManager.lines * 9, "TownVote");
            ItemStack book = null;
            int count = 0;
            for (Town t : TownVote.towns) {
                book = new ItemStack(Material.valueOf(ConfigManager.TownMaterial));
                ItemMeta meta = book.getItemMeta();
                meta.setDisplayName(ChatColor.GOLD + t.name);
                ArrayList<String> lore = new ArrayList<String>();
                lore.add(ChatColor.GRAY + "Votes: " + t.votes);
                meta.setLore(lore);
                book.setItemMeta(meta);
                inv.setItem(count, book);
                count++;
            }
            p.openInventory(inv);
        }
     
    I don't like spoon feeding but I will like to get from you good people some ideas of how I can do this
     
    #1 Nort721, Jun 5, 2018
    Last edited: Jun 5, 2018
  2. You already have a collection of towns, let's call that "list".
    Let's say you also have an integer variable that is called "page", which is initialized with the value 0.
    The inventory size is 54. The last line won't be used, as I place the control elements there in this example.

    For any page, that is greater or equal than 0, loop this logic:
    You get an index, that starts at 0, and is incremented every iteration.
    If the index + page*45 (45 because 54-1*9, as the last line is unused) is greater than or equal to the size of your list, end the loop.
    From list, get what is at (index + page*45), and place it in inventory slot index.

    This will get you pages with 45 items per page. Adapt to your needs. You will most likely also need some items to control the page variable. Page should never be lower than 0 or greater than (size of list / 45) - 1.
     
    • Winner Winner x 2
  3. thanks for the help but I am a bit confused how do I run for every page if I haven't created the pages yet do you mean that I need to create an ArrayList of inventories and then open them from the page variable like use it as an index? :unsure: but then how exactly I sort the items in every inventory?
     
  4. The pages are virtual, they are a mathematical construct, there is no object or something like that (but you could create that of course, but this is kept simple)

    So basically you can have any List (also an ArrayList, but that does not matter), that stores your towns. You only have a single inventory.
    To sort the items, you can sort the List like this:
    Code (Java):
    List<Town> sortedTowns = list.stream().sorted().collect(Collectors.toList());
    Then you just loop over that list, with said index and apply said maths to create the ItemStacks for every n-th element on every m-th page.
     
  5. you shouldnt be making the inventory every time someone runs it, just make it when the server enables and edit it so u can get the most updated information on how mnay towns / etc
     
  6. IF might work to your advantage here. It has support for paginated GUIs which you can use easily. There are tutorials on how to use it on the wiki, but I'll just give a small example on your use case if you're planning on using it.
    Code (Java):
    //create a gui
    Gui gui = new Gui(this, 6, ChatColor.GRAY + "TownVote");

    //crteate a pane with pages
    PaginatedPane paginatedPane = new PaginatedPane(new GuiLocation(0, 0), 9, 5);

    for (int page = 0; page < /*amount of pages*/; page++) {
      //create a pane which holds the items for every page
      OutlinePane outlinePane = new OutlinePane(new GuiLocation(0, 0), 9, 5);
     
      //add all the items to the pane
      for (int i = 0; i < /*max items for this page, probably 45*/; i++)
        outlinePane.addItem(new GuiItem(new ItemStack(Material.BOOK), event -> /*what to do if someone clicks on this town*/))

      //add the outline pane to the paginated pane
      paginatedPane.addPane(page, outlinePane);
    }

    //add the paginated pane to the gui
    gui.addPane(paginatedPane);

    //show the gui to the player
    gui.show(player);
    This would be the base structure for what you'd be doing, you'd only have to create buttons to navigate between the pages yourself.

    If you don't want to use this, follow the advice petomka gave you: check which page the user wants and then fill the inventory with those items and show it to them.
     
    • Like Like x 1
  7. Don't mean to sound overly self-promoting, but my own API works great for making paginated inventories
     
  8. thanks everyone for your suggestions i will try them when i will have time and will tell you how it go
     
  9. thanks everyone problem solved :)