From ac932a6e0c51ffa61f5e151c99130ec33d0f5b4a Mon Sep 17 00:00:00 2001 From: Arne Keller Date: Sun, 7 Mar 2021 21:31:50 +0100 Subject: [PATCH] Fix page title not updating --- .../edu/kit/typicalc/presenter/Presenter.java | 6 -- .../content/infocontent/StartPageView.java | 1 - .../TypeInferenceView.java | 52 +++++++++++++--- .../kit/typicalc/view/main/MainViewImpl.java | 61 +++++++------------ .../edu/kit/typicalc/view/main/UpperBar.java | 23 +++---- 5 files changed, 74 insertions(+), 69 deletions(-) diff --git a/src/main/java/edu/kit/typicalc/presenter/Presenter.java b/src/main/java/edu/kit/typicalc/presenter/Presenter.java index 5e36082..22d6065 100644 --- a/src/main/java/edu/kit/typicalc/presenter/Presenter.java +++ b/src/main/java/edu/kit/typicalc/presenter/Presenter.java @@ -2,7 +2,6 @@ package edu.kit.typicalc.presenter; import java.util.Map; -import com.vaadin.flow.component.UI; import edu.kit.typicalc.model.Model; import edu.kit.typicalc.model.TypeInfererInterface; import edu.kit.typicalc.model.parser.ParseError; @@ -31,11 +30,6 @@ public class Presenter implements MainViewListener { @Override public void typeInferLambdaString(String lambdaTerm, Map typeAssumptions) { - if (lambdaTerm.isBlank()) { - UI.getCurrent().getPage().setTitle(UI.getCurrent().getTranslation("root.typicalc")); - } else { - UI.getCurrent().getPage().setTitle(UI.getCurrent().getTranslation("root.typicalc") + " - " + lambdaTerm); - } Result result = model.getTypeInferer(lambdaTerm, typeAssumptions); if (result.isError()) { view.displayError(result.unwrapError()); diff --git a/src/main/java/edu/kit/typicalc/view/content/infocontent/StartPageView.java b/src/main/java/edu/kit/typicalc/view/content/infocontent/StartPageView.java index e740951..0e4b540 100644 --- a/src/main/java/edu/kit/typicalc/view/content/infocontent/StartPageView.java +++ b/src/main/java/edu/kit/typicalc/view/content/infocontent/StartPageView.java @@ -36,7 +36,6 @@ public class StartPageView extends VerticalLayout implements ControlPanelView, L private static final String CONTROL_PANEL_ID = "controlPanel"; private static final String START_PAGE_ID = "startPage"; private static final String SLIDE_SHOW_ID = "slideShow"; - private static final String FOOTER_ID = "startpage-footer"; private static final String DOT = "."; diff --git a/src/main/java/edu/kit/typicalc/view/content/typeinferencecontent/TypeInferenceView.java b/src/main/java/edu/kit/typicalc/view/content/typeinferencecontent/TypeInferenceView.java index aabb5e5..51804d8 100644 --- a/src/main/java/edu/kit/typicalc/view/content/typeinferencecontent/TypeInferenceView.java +++ b/src/main/java/edu/kit/typicalc/view/content/typeinferencecontent/TypeInferenceView.java @@ -10,11 +10,18 @@ import com.vaadin.flow.component.html.Footer; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.i18n.LocaleChangeEvent; import com.vaadin.flow.i18n.LocaleChangeObserver; +import com.vaadin.flow.router.BeforeEnterEvent; +import com.vaadin.flow.router.BeforeEnterObserver; +import com.vaadin.flow.router.HasDynamicTitle; +import com.vaadin.flow.router.Route; import edu.kit.typicalc.model.TypeInfererInterface; import edu.kit.typicalc.view.content.ControlPanel; import edu.kit.typicalc.view.content.ControlPanelView; import edu.kit.typicalc.view.content.typeinferencecontent.latexcreator.LatexCreator; +import edu.kit.typicalc.view.main.MainViewImpl; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Locale; @@ -27,8 +34,10 @@ import java.util.Locale; */ @CssImport("./styles/view/type-inference.css") @JavaScript("./src/key-shortcuts.js") +@Route(value = TypeInferenceView.ROUTE + "/:term", layout = MainViewImpl.class) public class TypeInferenceView extends VerticalLayout - implements ControlPanelView, ComponentEventListener, LocaleChangeObserver { + implements ControlPanelView, ComponentEventListener, LocaleChangeObserver, HasDynamicTitle, + BeforeEnterObserver { /** * Route of this view. */ @@ -47,6 +56,15 @@ public class TypeInferenceView extends VerticalLayout private final transient TypeInfererInterface typeInferer; private final Div content; private final ControlPanel controlPanel; + private String term = "?"; + + // used by Spring + public TypeInferenceView() { + this.typeInferer = null; + this.content = null; + this.controlPanel = null; + this.treeNumbers = null; + } /** * Initializes the component. When initialization is complete, the first step of the type @@ -138,11 +156,31 @@ public class TypeInferenceView extends VerticalLayout @Override public void localeChange(LocaleChangeEvent localeChangeEvent) { - lc = new LatexCreator(typeInferer, - error -> getTranslation("root." + error.toString().toLowerCase(Locale.ENGLISH))); - unification = new MathjaxUnification(lc.getUnification()); - content.removeAll(); - content.add(unification, tree); - refreshElements(); + if (typeInferer != null) { + lc = new LatexCreator(typeInferer, + error -> getTranslation("root." + error.toString().toLowerCase(Locale.ENGLISH))); + unification = new MathjaxUnification(lc.getUnification()); + content.removeAll(); + content.add(unification, tree); + refreshElements(); + } + } + + @Override + public void beforeEnter(BeforeEnterEvent event) { + if (event.getLocation().getPath().matches(ROUTE + "/.*")) { + term = URLDecoder.decode( + event.getRouteParameters().get("term") + .orElseThrow(IllegalStateException::new), + StandardCharsets.UTF_8); + } + } + + @Override + public String getPageTitle() { + if (typeInferer != null) { + return typeInferer.getFirstInferenceStep().getConclusion().getLambdaTerm().toString(); + } + return UI.getCurrent().getTranslation("root.typicalc") + " - " + term; } } diff --git a/src/main/java/edu/kit/typicalc/view/main/MainViewImpl.java b/src/main/java/edu/kit/typicalc/view/main/MainViewImpl.java index abb9553..f1c437c 100644 --- a/src/main/java/edu/kit/typicalc/view/main/MainViewImpl.java +++ b/src/main/java/edu/kit/typicalc/view/main/MainViewImpl.java @@ -16,11 +16,12 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import javax.servlet.http.HttpServletResponse; +import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Optional; +import java.util.TreeMap; import java.util.stream.Collectors; /** @@ -34,9 +35,8 @@ import java.util.stream.Collectors; @CssImport(value = "./styles/view/main/app-layout.css", themeFor = "vaadin-app-layout") @JavaScript("./src/svg-pan-zoom.min.js") @JavaScript("./src/tex-svg-full.js") -@Route(TypeInferenceView.ROUTE + "/:term") public class MainViewImpl extends AppLayout - implements MainView, BeforeEnterObserver, HasErrorParameter { + implements MainView, HasErrorParameter, AfterNavigationObserver { private static final long serialVersionUID = -2411433187835906976L; /** @@ -45,7 +45,6 @@ public class MainViewImpl extends AppLayout public static final String PAGE_TITLE = "Typicalc"; private final UpperBar upperBar; - private transient Optional tiv = Optional.empty(); /** * Creates a new MainViewImpl. @@ -53,15 +52,14 @@ public class MainViewImpl extends AppLayout public MainViewImpl() { setDrawerOpened(false); MainViewListener presenter = new Presenter(new ModelImpl(), this); - upperBar = new UpperBar(presenter, this::setTermInURL); + upperBar = new UpperBar(presenter, this::processInput); addToNavbar(upperBar); addToDrawer(new DrawerContent()); } @Override public void setTypeInferenceView(TypeInfererInterface typeInferer) { - tiv = Optional.of(new TypeInferenceView(typeInferer)); - setContent(tiv.get()); + setContent(new TypeInferenceView(typeInferer)); } @Override @@ -70,56 +68,41 @@ public class MainViewImpl extends AppLayout } @Override - public void beforeEnter(BeforeEnterEvent event) { - tiv = Optional.empty(); - if (event.getLocation().getPath().matches(TypeInferenceView.ROUTE + "/.*")) { - Location url = event.getLocation(); + public void afterNavigation(AfterNavigationEvent event) { + this.handleLocation(event.getLocation()); + } + + private void handleLocation(Location url) { + if (url.getPath().matches(TypeInferenceView.ROUTE + "/.*")) { List segments = url.getSegments(); String term = segments.get(segments.size() - 1); Map types = url.getQueryParameters().getParameters().entrySet().stream().map(entry -> Pair.of(entry.getKey(), entry.getValue().get(0)) ).collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); upperBar.inferTerm(decodeURL(term), types); - } else if (event.getLocation().getPath().equals(TypeInferenceView.ROUTE)) { + } else if (url.getPath().equals(TypeInferenceView.ROUTE)) { setContent(new StartPageView()); upperBar.inferTerm(StringUtils.EMPTY, Collections.emptyMap()); - } else if (event.getLocation().getPath().equals(StringUtils.EMPTY)) { + } else if (url.getPath().equals(StringUtils.EMPTY)) { setContent(new StartPageView()); } } - @Override - protected void afterNavigation() { - // this method ensures that the content is visible after navigation - tiv.ifPresent(this::setContent); - } - - private void setTermInURL(Pair> lambdaTermAndAssumptions) { + private void processInput(Pair> lambdaTermAndAssumptions) { String lambdaTerm = lambdaTermAndAssumptions.getLeft(); - if ("".equals(lambdaTerm)) { - UI.getCurrent().getPage().getHistory().pushState(null, "./"); - setContent(new StartPageView()); + if (lambdaTerm.isBlank()) { + UI.getCurrent().navigate("./"); return; } - StringBuilder types = new StringBuilder(); - for (Map.Entry type : lambdaTermAndAssumptions.getRight().entrySet()) { - if (types.length() > 0) { - types.append('&'); - } - types.append(type.getKey()); - types.append('='); - types.append(type.getValue()); - } - String typeAssumptions = ""; - if (types.length() > 0) { - typeAssumptions = "?" + types.toString(); - } - UI.getCurrent().getPage().getHistory().pushState(null, - new Location(TypeInferenceView.ROUTE + "/" + lambdaTerm + typeAssumptions)); + QueryParameters qp = new QueryParameters(lambdaTermAndAssumptions.getRight().entrySet().stream().map(entry -> + Pair.of(entry.getKey(), List.of(entry.getValue())) + ).collect(Collectors.toMap(Pair::getLeft, Pair::getRight, + (existing, replacement) -> existing, TreeMap::new))); + UI.getCurrent().navigate(TypeInferenceView.ROUTE + "/" + lambdaTerm, qp); } private String decodeURL(String encodedUrl) { - return java.net.URLDecoder.decode(encodedUrl, StandardCharsets.UTF_8); + return URLDecoder.decode(encodedUrl, StandardCharsets.UTF_8); } @Override diff --git a/src/main/java/edu/kit/typicalc/view/main/UpperBar.java b/src/main/java/edu/kit/typicalc/view/main/UpperBar.java index 10751df..1c3279d 100644 --- a/src/main/java/edu/kit/typicalc/view/main/UpperBar.java +++ b/src/main/java/edu/kit/typicalc/view/main/UpperBar.java @@ -3,7 +3,6 @@ package edu.kit.typicalc.view.main; import com.vaadin.flow.component.applayout.DrawerToggle; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.dependency.CssImport; -import com.vaadin.flow.component.dialog.Dialog; import com.vaadin.flow.component.html.Anchor; import com.vaadin.flow.component.html.H1; import com.vaadin.flow.component.icon.Icon; @@ -39,20 +38,20 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver { private final InputBar inputBar; private final Button toggle; private final Button helpButton; - + private final transient MainViewListener presenter; - private final transient Consumer>> setTermInURL; + private final transient Consumer>> inputConsumer; /** * Initializes a new UpperBar with the provided mainViewListener. * * @param presenter the listener used to communicate with the model - * @param setTermInURL function to set the term into the URL + * @param inputConsumer function to handle user input */ - protected UpperBar(MainViewListener presenter, Consumer>> setTermInURL) { + protected UpperBar(MainViewListener presenter, Consumer>> inputConsumer) { this.presenter = presenter; - this.setTermInURL = setTermInURL; + this.inputConsumer = inputConsumer; toggle = new DrawerToggle(); H1 viewTitle = new H1(new Anchor("/", getTranslation("root.typicalc"))); @@ -60,7 +59,7 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver { this.inputBar = new InputBar(this::typeInfer); inputBar.setId(INPUT_BAR_ID); helpButton = new Button(new Icon(VaadinIcon.QUESTION_CIRCLE)); - helpButton.addClickListener(event -> onHelpIconClick()); + helpButton.addClickListener(event -> new HelpDialog().open()); helpButton.setId(HELP_ICON_ID); add(toggle, viewTitle, inputBar, helpButton); @@ -76,10 +75,7 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver { * @param termAndAssumptions the lambda term to be type-inferred and the type assumptions to use */ protected void typeInfer(Pair> termAndAssumptions) { - setTermInURL.accept(termAndAssumptions); - if (!"".equals(termAndAssumptions.getLeft())) { - startInfer(termAndAssumptions.getLeft(), termAndAssumptions.getRight()); - } + inputConsumer.accept(termAndAssumptions); } private void startInfer(String term, Map typeAssumptions) { @@ -98,11 +94,6 @@ public class UpperBar extends HorizontalLayout implements LocaleChangeObserver { startInfer(term, typeAssumptions); } - private void onHelpIconClick() { - Dialog helpDialog = new HelpDialog(); - helpDialog.open(); - } - @Override public void localeChange(LocaleChangeEvent event) { toggle.getElement().setAttribute("title", getTranslation("root.drawerToggleTooltip"));