diff --git a/viewers/wicket/ui/src/main/java/module-info.java b/viewers/wicket/ui/src/main/java/module-info.java index 6422c87935e..4f8171dcd87 100644 --- a/viewers/wicket/ui/src/main/java/module-info.java +++ b/viewers/wicket/ui/src/main/java/module-info.java @@ -143,7 +143,7 @@ requires spring.beans; requires spring.context; requires spring.core; - requires wicket.bootstrap.core; + requires transitive wicket.bootstrap.core; requires wicket.bootstrap.extensions; requires wicket.bootstrap.themes; requires de.agilecoders.wicket.webjars; diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/CausewayModuleViewerWicketUi.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/CausewayModuleViewerWicketUi.java index 0d13297f211..90a70cbe61d 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/CausewayModuleViewerWicketUi.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/CausewayModuleViewerWicketUi.java @@ -18,27 +18,83 @@ */ package org.apache.causeway.viewer.wicket.ui; +import java.util.List; + +import org.apache.wicket.markup.head.CssHeaderItem; +import org.apache.wicket.markup.head.HeaderItem; +import org.apache.wicket.markup.head.IHeaderResponse; + +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.apache.causeway.viewer.commons.services.CausewayModuleViewerCommonsServices; import org.apache.causeway.viewer.wicket.model.CausewayModuleViewerWicketModel; import org.apache.causeway.viewer.wicket.ui.app.logout.LogoutHandlerWkt; -import org.apache.causeway.viewer.wicket.ui.components.widgets.themepicker.CausewayWicketThemeSupportDefault; +import org.apache.causeway.viewer.wicket.ui.components.widgets.themepicker.CausewayWicketThemeSupport; + +import de.agilecoders.wicket.core.Bootstrap; +import de.agilecoders.wicket.core.settings.ITheme; +import de.agilecoders.wicket.core.settings.NoopThemeProvider; +import de.agilecoders.wicket.core.settings.ThemeProvider; +import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchTheme; +import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchThemeProvider; /** * @since 1.x {@index} */ -@Configuration +@Configuration(proxyBeanMethods = false) @Import({ // Modules CausewayModuleViewerCommonsServices.class, CausewayModuleViewerWicketModel.class, // @Service's - CausewayWicketThemeSupportDefault.class, + CausewayWicketThemeSupport.class, LogoutHandlerWkt.class, }) public class CausewayModuleViewerWicketUi { + @Bean + ThemeProvider bootstrapDefaultThemeProvider() { + return new BootstrapDefaultThemeProvider(); + } + + @Bean + ThemeProvider bootswatchThemeProvider() { + return new BootswatchThemeProvider(BootswatchTheme.Flatly); + } + + /** + * Default Bootstrap Theme + * + * @see NoopThemeProvider + */ + private static class BootstrapDefaultThemeProvider implements ThemeProvider { + private final ITheme theme = new BootstrapDefaultTheme(); + @Override public ITheme byName(final String name) { + return theme; + } + @Override public List available() { + return List.of(theme); + } + @Override public ITheme defaultTheme() { + return theme; + } + private static final class BootstrapDefaultTheme implements ITheme { + @Override public String name() { + return "Default"; + } + @Override public List getDependencies() { + return List.of(); + } + @Override public void renderHead(final IHeaderResponse response) { + response.render(CssHeaderItem.forReference(Bootstrap.getSettings().getCssResourceReference())); + } + @Override public Iterable getCdnUrls() { + return List.of(); + } + } + } + } diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/CausewayWicketThemeSupport.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/CausewayWicketThemeSupport.java index 2ac7d53002c..77fb2d8d8d7 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/CausewayWicketThemeSupport.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/CausewayWicketThemeSupport.java @@ -18,18 +18,147 @@ */ package org.apache.causeway.viewer.wicket.ui.components.widgets.themepicker; +import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +import org.apache.wicket.Component; +import org.apache.wicket.util.string.Strings; + +import org.springframework.stereotype.Service; + +import org.apache.causeway.applib.services.registry.ServiceRegistry; +import org.apache.causeway.commons.internal.base._NullSafe; +import org.apache.causeway.core.config.CausewayConfiguration; + +import lombok.extern.slf4j.Slf4j; + +import de.agilecoders.wicket.core.Bootstrap; +import de.agilecoders.wicket.core.settings.ITheme; +import de.agilecoders.wicket.core.settings.NoopThemeProvider; import de.agilecoders.wicket.core.settings.ThemeProvider; /** * @since 2.0 */ -public interface CausewayWicketThemeSupport { +@Service +@Named("causeway.viewer.wicket.CausewayWicketThemeSupport") +@Slf4j +public record CausewayWicketThemeSupport( + ITheme defaultTheme, + Map themeByNameLower, + Map providerByThemeNameLower) { + + @Inject + public CausewayWicketThemeSupport(final CausewayConfiguration configuration, final ServiceRegistry serviceRegistry) { + this(Args.create(configuration, serviceRegistry)); + } + + private CausewayWicketThemeSupport(final Args args) { + this(args.defaultTheme, args.themeByNameLower, args.providerByThemeNameLower); + } + + public ITheme byName(final String name) { + if (!Strings.isEmpty(name)) { + var theme = themeByNameLower.get(name.toLowerCase()); + if(theme!=null) + return theme; + } + + log.warn("'{}' theme not found amoung enabled {}, " + + "falling back to '{}'", + name, + available().stream().map(ITheme::name).collect(Collectors.joining(", ")), + defaultTheme.name()); + + return defaultTheme; + } + + public List available() { + return themeByNameLower.values() + .stream() + .toList(); + } + + public List availableNames() { + return available() + .stream() + .map(ITheme::name) + .toList(); + } + + public ThemeProvider compositeThemeProvider() { + return new ThemeProvider() { + @Override public ITheme defaultTheme() { + return defaultTheme; + } + @Override public ITheme byName(final String name) { + return CausewayWicketThemeSupport.this.byName(name); + } + @Override public List available() { + return CausewayWicketThemeSupport.this.available(); + } + }; + } + + /** + * Required in order for ThemeProvider specific resources to be made available. + * + *

set during {@link Component#beforeRender()}, un-set during {@link Component#afterRender()} + * + * @see #unsetCustomThemeProvider() + */ + public void setCustomThemeProvider(final ITheme theme) { + Optional.ofNullable(providerByThemeNameLower.get(theme.name().toLowerCase())) + .ifPresent(Bootstrap.getSettings()::setThemeProvider); + } + + public void unsetCustomThemeProvider() { + Bootstrap.getSettings().setThemeProvider(compositeThemeProvider()); + } + + // -- HELPER + + /** + * Can be refactored/removed once we have flexible constructor bodies in Java. + */ + private record Args( + ITheme defaultTheme, + Map themeByNameLower, + Map providerByThemeNameLower) { + + static Args create( + final CausewayConfiguration configuration, + final ServiceRegistry serviceRegistry) { + + var enabledThemeNamesLowercase = _NullSafe.stream(configuration.viewer().wicket().themes().enabled()) + .map(String::toLowerCase) + .collect(Collectors.toCollection(HashSet::new)); + + var providerByThemeNameLower = new LinkedHashMap(); + var themeByNameLower = new LinkedHashMap(); + serviceRegistry.select(ThemeProvider.class) + .forEach(provider->{ + _NullSafe.stream(provider.available()) + .filter(theme->enabledThemeNamesLowercase.contains(theme.name().toLowerCase())) + .forEach(theme->{ + var themeKey = theme.name().toLowerCase(); + themeByNameLower.put(themeKey, theme); + providerByThemeNameLower.put(themeKey, provider); + }); + }); - // -- INTERFACE + var defaultTheme = Optional.ofNullable(themeByNameLower.get(configuration.viewer().wicket().themes().initial())) + .orElseGet(()->new NoopThemeProvider().defaultTheme()); - ThemeProvider getThemeProvider(); - List getEnabledThemeNames(); + return new Args(defaultTheme, themeByNameLower, providerByThemeNameLower); + } + } } diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/CausewayWicketThemeSupportDefault.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/CausewayWicketThemeSupportDefault.java deleted file mode 100644 index a278700cbad..00000000000 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/CausewayWicketThemeSupportDefault.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.causeway.viewer.wicket.ui.components.widgets.themepicker; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import jakarta.annotation.Priority; -import jakarta.inject.Inject; -import jakarta.inject.Named; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Service; - -import org.apache.causeway.applib.annotation.PriorityPrecedence; -import org.apache.causeway.applib.services.registry.ServiceRegistry; -import org.apache.causeway.commons.collections.Can; -import org.apache.causeway.commons.internal.base._Lazy; -import org.apache.causeway.core.config.CausewayConfiguration; - -import lombok.extern.slf4j.Slf4j; - -import de.agilecoders.wicket.core.settings.NoopThemeProvider; -import de.agilecoders.wicket.core.settings.ThemeProvider; -import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchTheme; -import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchThemeProvider; - -/** - * @since 2.0 - */ -@Service -@Named("causeway.viewer.wicket.CausewayWicketThemeSupportDefault") -@Priority(PriorityPrecedence.MIDPOINT) -@Qualifier("Default") -@Slf4j -public class CausewayWicketThemeSupportDefault implements CausewayWicketThemeSupport { - - private final _Lazy themeProvider = _Lazy.threadSafe(this::createThemeProvider); - - @Inject private CausewayConfiguration configuration; - @Inject private ServiceRegistry serviceRegistry; - - @Override - public ThemeProvider getThemeProvider() { - return themeProvider.get(); - } - - @Override - public List getEnabledThemeNames() { - - var composite = themeProvider.get(); - - List allThemes = composite.availableNames(); - - allThemes = filterThemes(allThemes); - - return allThemes; - } - - // -- HELPER - - private ThemeProviderComposite createThemeProvider() { - - var providerBeans = serviceRegistry.select(ThemeProvider.class); - if (providerBeans.isEmpty()) { - return ThemeProviderComposite.of(Can.ofSingleton(createFallbackThemeProvider())); - } - - return ThemeProviderComposite.of(providerBeans); - } - - private ThemeProvider createFallbackThemeProvider() { - var themeName = configuration.viewer().wicket().themes().initial(); - if ("default".equalsIgnoreCase(themeName)) { - // in effect uses the bootstrap 'default' theme - return new NoopThemeProvider(); - } - BootswatchTheme bootswatchTheme; - try { - bootswatchTheme = BootswatchTheme.valueOf(themeName); - } catch (Exception ex) { - bootswatchTheme = BootswatchTheme.Flatly; - log.warn("Did not recognise configured bootswatch theme '{}', defaulting to '{}'", - themeName, - bootswatchTheme); - - } - - return new BootswatchThemeProvider(bootswatchTheme); - } - - /** - * Filters which themes to show in the drop up by using the provided values - * in {@link CausewayConfiguration.Viewer.Wicket.Themes#getEnabled()} - * - * @param availableThemes All available themes - * @return A list of all enabled themes - */ - private List filterThemes(final List availableThemes) { - - var configuredThemes = configuration.viewer().wicket().themes().enabled(); - if (configuredThemes == null || configuredThemes.isEmpty()) { - return Collections.emptyList(); - } - - var enabledThemes = new ArrayList(); - availableThemes.stream() - .filter(availableTheme -> configuredThemes.stream().anyMatch(configuredTheme -> configuredTheme.equalsIgnoreCase(availableTheme))) - .forEach(enabledThemes::add); - - return enabledThemes; - } - -} diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/ThemeChooser.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/ThemeChooser.java index b1e4aa833d8..9adea625d96 100644 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/ThemeChooser.java +++ b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/ThemeChooser.java @@ -18,30 +18,22 @@ */ package org.apache.causeway.viewer.wicket.ui.components.widgets.themepicker; -import jakarta.inject.Inject; - -import org.apache.wicket.AttributeModifier; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.util.cookies.CookieUtils; -import org.apache.wicket.util.string.Strings; +import org.apache.causeway.commons.internal.base._StableValue; +import org.apache.causeway.commons.internal.base._Strings; +import org.apache.causeway.commons.internal.exceptions._Exceptions; +import org.apache.causeway.core.metamodel.context.MetaModelContext; import org.apache.causeway.viewer.wicket.ui.panels.PanelAbstract; import org.apache.causeway.viewer.wicket.ui.util.Wkt; -import lombok.Getter; - import de.agilecoders.wicket.core.Bootstrap; -import de.agilecoders.wicket.core.settings.ActiveThemeProvider; -import de.agilecoders.wicket.core.settings.IBootstrapSettings; import de.agilecoders.wicket.core.settings.ITheme; import de.agilecoders.wicket.core.settings.SessionThemeProvider; -import de.agilecoders.wicket.core.settings.SingleThemeProvider; import de.agilecoders.wicket.core.util.Attributes; -import de.agilecoders.wicket.themes.markup.html.bootstrap.BootstrapThemeTheme; -import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchTheme; -import de.agilecoders.wicket.themes.markup.html.bootswatch.BootswatchThemeProvider; /** * A panel used as a Navbar item to change the application theme/skin @@ -51,13 +43,13 @@ public class ThemeChooser private static final long serialVersionUID = 1L; - @Inject @Getter transient private CausewayWicketThemeSupport themeSupport; - /** * The name of the cookie that stores the last user selection */ private static final String CAUSEWAY_THEME_COOKIE_NAME = "causeway.viewer.wicket.themes.selected"; + private final _StableValue themeSupport = new _StableValue<>(); + /** * Constructor * @@ -67,95 +59,88 @@ public ThemeChooser(final String id) { super(id); } + @Override + protected void onConfigure() { + super.onConfigure(); + setVisible(getWicketViewerSettings().themes().showChooser()); + } + @Override protected void onInitialize() { super.onInitialize(); + initializeActiveThemeFromCookie(); + Wkt.ajaxEnable(this); + } - if(getThemeSupport()==null) { - super.getMetaModelContext().injectServicesInto(this); - } + @Override + protected void onBeforeRender() { + super.onBeforeRender(); + buildGui(); + themeSupport().setCustomThemeProvider(getActiveTheme()); + } - final ActiveThemeProvider activeThemeProvider = getActiveThemeProvider(); - if(activeThemeProvider.getClass() == SessionThemeProvider.class) { - initializeActiveThemeFromCookie(); - } else { - // if anything other than the default, then we do NOT initialize - // (on the assumption that it is a persistent store and we don't want to overwrite). - } + @Override + protected void onAfterRender() { + themeSupport().unsetCustomThemeProvider(); + super.onAfterRender(); + } - Wkt.listViewAdd(this, "themes", getThemeSupport().getEnabledThemeNames(), item->{ + void buildGui() { + final String activeThemeName = getActiveTheme().name(); - final String themeName = item.getModelObject(); + Wkt.listViewAdd(this, "themes", themeSupport().availableNames(), item->{ - if (themeName.equals(getActiveThemeProvider().getActiveTheme().name())) { - item.add(AttributeModifier.append("class", "active")); - } + final String themeName = item.getModelObject(); // use Ajax link because Link's url looks like /object:3 and this confuses the browser - Wkt.add(item, - Wkt.link("themeLink", target->{ - setActiveTheme(themeName); - saveActiveThemeToCookie(themeName); - target.add(getPage()); // repaint the whole page - }) - .setBody(Model.of(themeName))); + var link = Wkt.link("themeLink", target->{ + setActiveTheme(themeName); + target.add(getPage()); // repaint the whole page + }) + .setBody(Model.of(themeName)); + + if (themeName.equals(activeThemeName)) { + Wkt.cssAppend(link, "active"); + } + Wkt.add(item, link); }); - } - private void saveActiveThemeToCookie(final String themeName) { - CookieUtils cookieUtils = new CookieUtils(); - cookieUtils.save(CAUSEWAY_THEME_COOKIE_NAME, themeName); + @Override + protected void onComponentTag(final ComponentTag tag) { + super.onComponentTag(tag); + tag.setName("li"); + Attributes.addClass(tag, "dropdown"); } - private void initializeActiveThemeFromCookie() { - CookieUtils cookieUtils = new CookieUtils(); - String activeTheme = cookieUtils.load(CAUSEWAY_THEME_COOKIE_NAME); - if (!Strings.isEmpty(activeTheme)) { - - var isAvailable = getThemeSupport().getThemeProvider().available().stream() - .anyMatch(theme->activeTheme.equals(theme.name())); + // -- HELPER - if(isAvailable) { - setActiveTheme(activeTheme); - } - } - } - - private void setActiveTheme(final String activeTheme) { - IBootstrapSettings bootstrapSettings = Bootstrap.getSettings(); - ITheme theme = getThemeSupport().getThemeProvider().byName(activeTheme); - getActiveThemeProvider().setActiveTheme(theme); - if (theme instanceof BootstrapThemeTheme) { - bootstrapSettings.setThemeProvider(new SingleThemeProvider(theme)); - } else if (theme instanceof BootswatchTheme) { - bootstrapSettings.setThemeProvider(new BootswatchThemeProvider((BootswatchTheme) theme)); - /* - } else if (theme instanceof VegibitTheme) { - bootstrapSettings.setThemeProvider(new VegibitThemeProvider((VegibitTheme) theme)); - */ - } + private void initializeActiveThemeFromCookie() { + // legacy code - perhaps could be refactored to use CookieThemeProvider + if(!Bootstrap.getSettings().getActiveThemeProvider().getClass().equals(SessionThemeProvider.class)) + return; + _Strings.nonEmpty(new CookieUtils().load(CAUSEWAY_THEME_COOKIE_NAME)) + .filter(themeSupport().availableNames()::contains) + .ifPresent(this::setActiveTheme); } - private ActiveThemeProvider getActiveThemeProvider() { - return Bootstrap.getSettings().getActiveThemeProvider(); + private void setActiveTheme(final String themeName) { + ITheme theme = themeSupport().byName(themeName); + if(theme==null) + return; + new CookieUtils().save(CAUSEWAY_THEME_COOKIE_NAME, themeName); + Bootstrap.getSettings().getActiveThemeProvider().setActiveTheme(theme); } - @Override - protected void onComponentTag(final ComponentTag tag) { - super.onComponentTag(tag); - - tag.setName("li"); - Attributes.addClass(tag, "dropdown"); + private ITheme getActiveTheme() { + return Bootstrap.getSettings().getActiveThemeProvider().getActiveTheme(); } - @Override - protected void onConfigure() { - super.onConfigure(); - - boolean shouldShow = getWicketViewerSettings().themes().showChooser(); - setVisible(shouldShow); + private CausewayWicketThemeSupport themeSupport() { + return themeSupport.orElseSet(()->MetaModelContext.instance() + .flatMap(mmc->mmc.lookupService(CausewayWicketThemeSupport.class)) + .orElseThrow(()->_Exceptions.illegalState("no CausewayWicketThemeSupport found"))); } } diff --git a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/ThemeProviderComposite.java b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/ThemeProviderComposite.java deleted file mode 100644 index e87740917db..00000000000 --- a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/widgets/themepicker/ThemeProviderComposite.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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 CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.causeway.viewer.wicket.ui.components.widgets.themepicker; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.apache.wicket.util.string.Strings; - -import org.apache.causeway.commons.collections.Can; -import org.apache.causeway.commons.internal.collections._Lists; -import org.apache.causeway.commons.internal.collections._Maps; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import de.agilecoders.wicket.core.settings.ITheme; -import de.agilecoders.wicket.core.settings.ThemeProvider; - -/** - * - * @since 2.0 - * - */ -@RequiredArgsConstructor(staticName = "of") -@Slf4j -public class ThemeProviderComposite implements ThemeProvider { - - private final Can themeProviders; - - private ITheme defaultTheme; - private Map themesByName; - private List availableNames; - private List availableThemes; - - @Override - public ITheme byName(final String name) { - if (!Strings.isEmpty(name)) { - ensureInit(); - var theme = themesByName.get(name.toLowerCase()); - if(theme!=null) { - return theme; - } - } - - log.warn("'{}' theme not found amoung providers {} provinding {}, " - + "using default '{}' instead", - name, - themeProviders.toList(), - available().stream().map(ITheme::name).collect(Collectors.joining(", ")), - defaultTheme().name()); - - return defaultTheme(); - } - - @Override - public List available() { - ensureInit(); - return availableThemes; - } - - @Override - public ITheme defaultTheme() { - ensureInit(); - return defaultTheme; - } - - public List availableNames() { - ensureInit(); - return availableNames; - } - - // -- HELPER - - private void ensureInit() { - if(themesByName!=null) { - return; - } - themesByName = _Maps.newLinkedHashMap(); - themeProviders.forEach(themeProvider->{ - - if(defaultTheme==null) { - defaultTheme = themeProvider.defaultTheme(); - } - - themeProvider.available().forEach(theme->{ - themesByName.put(theme.name().toLowerCase(), theme); - }); - - }); - availableThemes = Collections.unmodifiableList(_Lists.newArrayList(themesByName.values())); - availableNames = Collections.unmodifiableList(_Lists.map(availableThemes, ITheme::name)); - } - -} diff --git a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/BootstrapInitWkt.java b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/BootstrapInitWkt.java index 44f7fb9b9c0..1526833d2fa 100644 --- a/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/BootstrapInitWkt.java +++ b/viewers/wicket/viewer/src/main/java/org/apache/causeway/viewer/wicket/viewer/wicketapp/config/BootstrapInitWkt.java @@ -53,11 +53,10 @@ public void renderHead(final IHeaderResponse response) { } }); - serviceRegistry.select(CausewayWicketThemeSupport.class) - .getFirst() - .ifPresent(themeSupport->{ - bsSettings.setThemeProvider(themeSupport.getThemeProvider()); - }); + serviceRegistry.lookupService(CausewayWicketThemeSupport.class) + .ifPresent(themeSupport->{ + bsSettings.setThemeProvider(themeSupport.compositeThemeProvider()); + }); } }