Skip to content

Method: lambda$new$0(UserActionProvider)

1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * SteelBlue: DCI User Interfaces
5: * http://tidalwave.it/projects/steelblue
6: *
7: * Copyright (C) 2015 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/steelblue-src
22: * git clone https://github.com/tidalwave-it/steelblue-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.ui.core.spi;
27:
28: import jakarta.annotation.Nonnull;
29: import java.util.Collection;
30: import java.util.Comparator;
31: import java.util.HashMap;
32: import java.util.Map;
33: import java.util.function.Supplier;
34: import it.tidalwave.util.As;
35: import it.tidalwave.util.Pair;
36: import it.tidalwave.ui.core.MenuBarControl;
37: import it.tidalwave.ui.core.role.UserAction;
38: import lombok.AccessLevel;
39: import lombok.RequiredArgsConstructor;
40: import lombok.experimental.Delegate;
41: import lombok.extern.slf4j.Slf4j;
42: import static java.util.stream.Collectors.*;
43: import static it.tidalwave.ui.core.MenuBarControl.MenuPlacement._MenuItemPlacement_;
44: import static it.tidalwave.ui.core.role.UserActionProvider._UserActionProvider_;
45:
46: /***************************************************************************************************************************************************************
47: *
48: * A support implementation for {@link MenuBarControl}.
49: *
50: * @param <B> the type of the binder
51: * @param <MB> the type of the menubar
52: * @param <M> the type of the menu
53: * @since 1.1-ALPHA-6
54: * @author Fabrizio Giudici
55: *
56: **************************************************************************************************************************************************************/
57: @RequiredArgsConstructor(access = AccessLevel.PROTECTED) @Slf4j @SuppressWarnings("this-escape")
58: public abstract class MenuBarControlSupport<B, MB, M> implements MenuBarControl<B, MB>
59: {
60: @Delegate
61: private final As as = As.forObject(this);
62:
63: /** The default supplier of {@link UserAction}s, can be injected for testing. */
64: @Nonnull
65: protected final Supplier<Collection<? extends UserAction>> userActionsSupplier;
66:
67: /***********************************************************************************************************************************************************
68: * Default constructor.
69: **********************************************************************************************************************************************************/
70: protected MenuBarControlSupport ()
71: {
72: userActionsSupplier = () -> asMany(_UserActionProvider_).stream().flatMap(ap -> ap.getActions().stream()).collect(toList());
73: }
74:
75: /***********************************************************************************************************************************************************
76: * {@inheritDoc}
77: **********************************************************************************************************************************************************/
78: @Override
79: public void populate (@Nonnull final B binder, @Nonnull final MB menuBar)
80: {
81: final var menuMapByLabel = new HashMap<String, M>();
82: final var actions = userActionsSupplier.get();
83: log.info("Menu bar user actions: {}", actions);
84: actions.stream().map(a -> Pair.of(a, a.maybeAs(_MenuItemPlacement_)))
85: .filter(p -> p.b.isPresent())
86: .forEach(p ->
87: {
88: final var menuPath = p.b.map(MenuPlacement::getPath).orElseThrow();
89: final var menu = menuMapByLabel.computeIfAbsent(menuPath, this::createMenu);
90: log.debug("Binding {} to menu item {}", p.a, menuPath);
91: addMenuItemToMenu(menu, binder, p.a);
92: });
93:
94: menuMapByLabel.entrySet().stream().sorted(menuComparator()).forEach(e -> addMenuToMenuBar(menuBar, e.getValue()));
95: }
96:
97: /***********************************************************************************************************************************************************
98: * {@return a new menu with the given label}.
99: * @param label the label
100: **********************************************************************************************************************************************************/
101: @Nonnull
102: protected abstract M createMenu (@Nonnull final String label);
103:
104: /***********************************************************************************************************************************************************
105: * Adds a menu to the menu bar.
106: * @param menuBar the menu bar
107: * @param menu the menu
108: **********************************************************************************************************************************************************/
109: protected abstract void addMenuToMenuBar (@Nonnull final MB menuBar, @Nonnull final M menu);
110:
111: /***********************************************************************************************************************************************************
112: * Adds to the given menu a new item bound to the given {@link UserAction}.
113: * @param menu the menu
114: * @param binder the binder
115: * @param action the user action
116: **********************************************************************************************************************************************************/
117: protected abstract void addMenuItemToMenu (@Nonnull final M menu, @Nonnull final B binder, @Nonnull final UserAction action);
118:
119: /***********************************************************************************************************************************************************
120: * {@return a {@link Comparator } for menus}
121: **********************************************************************************************************************************************************/
122: @Nonnull
123: private final Comparator<Map.Entry<String, ?>> menuComparator()
124: {
125: return (e1, e2) ->
126: {
127: final var i1 = MenuIndex.findPosition(e1.getKey());
128: final var i2 = MenuIndex.findPosition(e2.getKey());
129: return (i1 >= 0 && i2 >= 0) ? i1 - i2 : e1.getKey().compareTo(e2.getKey());
130: };
131: }
132: }