Class PathBasedMenuBuilder
Example
Suppose you register the following menu items in order:
- /my-group/item-1
- /my-group
- /my-item
- /my-group/item-2
- /my-other-group/single-item
or in code:
builder.item( "/my-group/item-1" ).and()
.item( "/my-group" ).and()
.item( "/my-item" ).and()
.item( "/my-group/item-2" ).and()
.item( "/my-other-group/single-item" ).and()
.item( "/my-group:item-3" ).and()
.build()
When building the Menu
this will result in the following hierarchy:
ROOT
+ /my-group
| + /my-group/item-1
| + /my-group/item-2
+ /my-group:item-3
+ /my-item
+ /my-other-group/single-item
Note that a parent item does not automatically get created based on path separator (the example of /my-other-group/single-item
.
Only if there is another item with an exact path of that before a separator will an item be created. This is also why /my-group:item-3
is still a separate item as : (colon) does not count as a path separator.
By default the top-most item of the menu has no specific path. Setting a path on the root item
can be done using root(String)
, but this will have no impact on the hierarchy being created.
The root path of a Menu
is only relevant in specialized cases where you want to merge the result of a
builder into an already existing Menu
.
Order and sorting
A Menu
item can have an order specified which can be used to sort the Menu
. Sorting a menu is usually done externally,
the PathBasedMenuBuilder
creates a Menu
with the items ordered according to their path value. You can see this in the above example.
You can manually set a Comparator
that should be used for sorting a menu. You can so do per item, in which case the comparator
will be used only for the children of that particular item. Depending on how you register it, it will apply for all sub-trees of a menu item.
If you want to use a different Comparator
for the entire menu, you must register it on the root item:
builder.root( "/root" ).comparator( myComparator, true );
Group items
A single item can also be flagged as a group (this sets the value of Menu.isGroup()
. This property however has nothing to do with
the actual hierarchy being created. It is not because an item is flagged as a group that it will be turned into a parent for other items.
It will automatically serve as a parent if the other items have a path that uses the current item as prefix. The group property is an indication
for how the item should behave in the generated Menu
. The value of Menu.isGroup()
is never set automatically, not even when
an item becomes the parent of others. You should create groups using group(String)
.
From item path to Menu hierarchy
The PathBaseMenuBuilder
has itself no concept of a hierarchy of menu items. It purely works on a map of items identified by their path.
It is only when the actual Menu
is being built that this flat list of items gets turned into a Menu
hierarchy, based on the
presence of path separators (/ - forward slash) and items matching sub-segments of others.
- Since:
- 1.0.0
- Author:
- Arne Vandamme, Marc Vanbrabant
- See Also:
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic final class
Represents a single item builder attached to a parentPathBasedMenuBuilder
. -
Constructor Summary
ModifierConstructorDescriptionPathBasedMenuBuilder
(MenuItemBuilderProcessor itemProcessor) protected
PathBasedMenuBuilder
(PathBasedMenuBuilder parent, MenuItemBuilderProcessor itemProcessor) -
Method Summary
Modifier and TypeMethodDescriptionandThen
(@NonNull Consumer<PathBasedMenuBuilder> consumer) Add an additionalConsumer
for thisPathBasedMenuBuilder
that should be applied right before the actualMenu
is being built.build()
void
Will build into the existing menu and merge the root only if the root has been configured on the builder.void
Builds the result of the builder in the existing instance.changeItemPath
(@NonNull String currentPathPrefix, @NonNull String newPathPrefix) Update the path of all items starting with (or equal to) the given path prefix.changeItemPath
(@NonNull String currentPathPrefix, @NonNull String newPathPrefix, boolean replaceAllItemsWithPrefix) Update the path of all items starting with (or equal to) the given path prefix.protected PathBasedMenuBuilder
Retrieve the item builder for a specific path, where the item should represent a group of items.Retrieve the item builder for a specific path, where the item should represent a group of items.Retrieve the item builder for a specific path.Retrieve the item builder for a specific path.Retrieve the item builder for a specific path.void
Will merge into the existing menu and merge the root only if it has been configured on the builder.void
Merges the result of the builder in the existing instance.optionalItem
(@NonNull String path) Return an item builder for updating an item if it exists.removeItems
(@NonNull String path, boolean removeAllItemsWithPathAsPrefix) Remove the item with the specified path from this menu builder.Get the root item builder.withProcessor
(@NonNull MenuItemBuilderProcessor processor, @NonNull Consumer<PathBasedMenuBuilder> consumer) Perform a set of actions with a different item processor.
-
Constructor Details
-
PathBasedMenuBuilder
public PathBasedMenuBuilder()
-
-
Method Details
-
root
Get the root item builder. By default the root item of the menu has no path, this method also configures a path on the root item.- Parameters:
rootPath
- path of the top most menu- Returns:
- root item builder
-
item
Retrieve the item builder for a specific path. If there is none yet, one will be created.- Parameters:
path
- identifying the item- Returns:
- item builder
-
optionalItem
Return an item builder for updating an item if it exists. This will always return a valid item builder, but nothing will happen if that item did not exist before.- Parameters:
path
- identifying the item- Returns:
- item builder
-
item
Retrieve the item builder for a specific path. If there is none yet, one will be created. This method is a shorter version foritem(path).title(title)
.- Parameters:
path
- identifying the itemtitle
- that should be set on the item- Returns:
- item builder
-
item
Retrieve the item builder for a specific path. If there is none yet, one will be created. This method is a shorter version foritem(path).title(title).url(url)
.- Parameters:
path
- identifying the itemtitle
- that should be set on the itemurl
- that should be set on the item- Returns:
- item builder
-
group
Retrieve the item builder for a specific path, where the item should represent a group of items. If there is no item builder yet, one will be created. If the item builder exists, but is not yet flagged as a group, it will be turned into a group. Note that flagging an item as a group simply sets the appropriate property. It has no effect on the actualMenu
hierarchy being built and the fact that this item might serve as a parent for others. The latter is purely determined by the path splitting when building the menu. This method is a shorter version foritem(path).group(true)
.- Parameters:
path
- identifying the item- Returns:
- item builder
-
group
Retrieve the item builder for a specific path, where the item should represent a group of items. If there is no item builder yet, one will be created. If the item builder exists, but is not yet flagged as a group, it will be turned into a group. Note that flagging an item as a group simply sets the appropriate property. It has no effect on the actualMenu
hierarchy being built and the fact that this item might serve as a parent for others. The latter is purely determined by the path splitting when building the menu. This method is a shorter version foritem(path, title).group(true)
.- Parameters:
path
- identifying the itemtitle
- that should be set on the item- Returns:
- item builder
-
andThen
Add an additionalConsumer
for thisPathBasedMenuBuilder
that should be applied right before the actualMenu
is being built. Use this method sparingly, only when you want to customize the menu builder and wish to be sure that initial configuration has been applied. For example you want to move a group of items but you are not sure up front how many child items it will have as modules could register them at a later stage. Shifting the path changing calls to the separateandThen(Consumer)
consumer can help you in said case. Note that once the consumer has been applied, it will not be re-applied on subsequent builds. It is possible to register additional consumers from within a consumer, but simplicity's sake you probably want to avoid this.- Parameters:
consumer
- to add- Returns:
- current builder
-
removeItems
public PathBasedMenuBuilder removeItems(@NonNull @NonNull String path, boolean removeAllItemsWithPathAsPrefix) Remove the item with the specified path from this menu builder. Optionally also removes all other items having the specified path as prefix.- Parameters:
path
- to removeremoveAllItemsWithPathAsPrefix
- true if other items with that path as prefix should be removed as well- Returns:
- current builder
-
changeItemPath
public PathBasedMenuBuilder changeItemPath(@NonNull @NonNull String currentPathPrefix, @NonNull @NonNull String newPathPrefix) Update the path of all items starting with (or equal to) the given path prefix. The prefix of the current path will be updated to the new path prefix. If you only want to change the single item with exactly that path, usechangeItemPath("currentPrefix", "newPrefix", false)
. Note that, unlikeitem("my item").changePathTo(X)
, this method will not create any items if they do not exist.- Parameters:
currentPathPrefix
- prefix item paths should be starting withnewPathPrefix
- new prefix to use- Returns:
- current menu builder
- Since:
- 3.0.0
- See Also:
-
changeItemPath
public PathBasedMenuBuilder changeItemPath(@NonNull @NonNull String currentPathPrefix, @NonNull @NonNull String newPathPrefix, boolean replaceAllItemsWithPrefix) Update the path of all items starting with (or equal to) the given path prefix. The prefix of the current path will be updated to the new path prefix. If you only want to change the single item starting with exactly that path, usechangeItemPaths("currentPrefix", "newPrefix", false)
. Note that, unlikeitem("my item").changePathTo(X)
, this method will not create any items if they do not exist.- Parameters:
currentPathPrefix
- prefix item paths should be starting withnewPathPrefix
- new prefix to usereplaceAllItemsWithPrefix
- true if all items starting with the currentPathPrefix should be updated, false if only an exact match should update- Returns:
- current menu builder
- Since:
- 3.0.0
-
build
- Returns:
- A newly constructed Menu instance.
-
getParent