You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/05/28 07:48:06 UTC

[isis] branch master updated: ISIS-2340: adds menu decorator, also polishing action dialog (Vaadin)

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 5f4aec6  ISIS-2340: adds menu decorator, also polishing action dialog (Vaadin)
5f4aec6 is described below

commit 5f4aec6396bcc77d182af86b46dc6aafd8f5bc5c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu May 28 09:47:24 2020 +0200

    ISIS-2340: adds menu decorator, also polishing action dialog (Vaadin)
---
 .../viewer/vaadin/model/decorator/Decorators.java  |  38 +++-
 .../vaadin/ui/components/action/ActionButton.java  |   5 +
 .../vaadin/ui/components/action/ActionDialog.java  | 191 ++++++++++++---------
 .../ui/pages/main/MainView_createHeader.java       |  13 +-
 4 files changed, 159 insertions(+), 88 deletions(-)

diff --git a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/decorator/Decorators.java b/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/decorator/Decorators.java
index 5ba4cb0..4596de7 100644
--- a/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/decorator/Decorators.java
+++ b/incubator/viewers/vaadin/model/src/main/java/org/apache/isis/incubator/viewer/vaadin/model/decorator/Decorators.java
@@ -25,14 +25,17 @@ import com.vaadin.flow.component.html.Image;
 import com.vaadin.flow.component.html.Label;
 import com.vaadin.flow.component.html.Span;
 import com.vaadin.flow.component.icon.VaadinIcon;
+import com.vaadin.flow.component.orderedlayout.FlexComponent.Alignment;
 import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
 
 import org.apache.isis.applib.layout.component.CssClassFaPosition;
+import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
 import org.apache.isis.viewer.common.model.decorator.fa.FontAwesomeDecorator;
 import org.apache.isis.viewer.common.model.decorator.fa.FontAwesomeUiModel;
 import org.apache.isis.viewer.common.model.decorator.tooltip.TooltipDecorator;
 import org.apache.isis.viewer.common.model.decorator.tooltip.TooltipUiModel;
 import org.apache.isis.viewer.common.model.userprofile.UserProfileUiModel;
+import org.apache.isis.viewer.common.model.userprofile.UserProfileUiModelProvider;
 
 import lombok.Getter;
 import lombok.val;
@@ -48,6 +51,7 @@ public class Decorators {
 
     @Getter(lazy = true) private final static Tooltip tooltip = new Tooltip();
     @Getter(lazy = true) private final static Icon icon = new Icon();
+    @Getter(lazy = true) private final static Menu menu = new Menu();
     @Getter(lazy = true) private final static User user = new User();
 
     // -- DECORATOR CLASSES
@@ -78,7 +82,7 @@ public class Decorators {
 
                 return CssClassFaPosition.isLeftOrUnspecified(fontAwesome.getPosition())
                         ? new HorizontalLayout(faIcon, uiComponent)
-                                : new HorizontalLayout(uiComponent, faIcon);
+                        : new HorizontalLayout(uiComponent, faIcon);
 
             })
             .orElseGet(()->{
@@ -94,10 +98,38 @@ public class Decorators {
         }
 
     }
+    
+    public final static class Menu {
+        
+        public Component decorateTopLevel(
+                final Label label) {
+            val icon = getTopLevelMenuIcon();
+            val layout =  new HorizontalLayout(label, icon);
+            layout.setVerticalComponentAlignment(Alignment.END, icon);
+            return (Component) layout;
+        }
+        
+        private Component getTopLevelMenuIcon() {
+            val menuIcon = new com.vaadin.flow.component.icon.Icon(VaadinIcon.CARET_DOWN);
+            menuIcon.setSize("1em");
+            menuIcon.getElement().getStyle().set("margin-left", "2px");
+            return menuIcon;
+        }
+        
+    }
 
     public final static class User {
 
-        public Component decorate( 
+        public Component decorateWithAvatar(
+                final Label label,
+                final IsisWebAppCommonContext commonContext) {
+            
+            val profileIfAny = commonContext.lookupServiceElseFail(UserProfileUiModelProvider.class)
+                    .getUserProfile(); 
+            return decorateWithAvatar(label, Optional.ofNullable(profileIfAny));
+        }
+        
+        public Component decorateWithAvatar( 
                 final Label label,
                 final Optional<UserProfileUiModel> userProfileUiModel) {
             
@@ -137,4 +169,6 @@ public class Decorators {
     }
 
 
+
+
 }
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionButton.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionButton.java
index c980807..1dce1fa 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionButton.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionButton.java
@@ -27,6 +27,11 @@ import org.apache.isis.incubator.viewer.vaadin.ui.components.UiComponentFactoryV
 import lombok.NonNull;
 import lombok.val;
 
+/**
+ * Button that when clicked opens an {@link ActionDialog}. 
+ * 
+ * @since May 28, 2020
+ */
 public class ActionButton extends Button {
 
     private static final long serialVersionUID = 1L;
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionDialog.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionDialog.java
index b865959..6fccec8 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionDialog.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/action/ActionDialog.java
@@ -20,6 +20,7 @@ package org.apache.isis.incubator.viewer.vaadin.ui.components.action;
 
 import java.util.stream.Stream;
 
+import com.vaadin.flow.component.Component;
 import com.vaadin.flow.component.button.Button;
 import com.vaadin.flow.component.button.ButtonVariant;
 import com.vaadin.flow.component.dependency.CssImport;
@@ -31,10 +32,12 @@ import com.vaadin.flow.component.html.Header;
 import com.vaadin.flow.component.icon.VaadinIcon;
 import com.vaadin.flow.theme.lumo.Lumo;
 
+import org.apache.isis.core.commons.collections.Can;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.incubator.viewer.vaadin.ui.components.UiComponentFactoryVaa;
 
 import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 @CssImport(value = "./css/dialog-overlay.css", themeFor = "vaadin-dialog-overlay")
@@ -42,19 +45,7 @@ import lombok.val;
 public class ActionDialog extends Dialog {
 
     private static final long serialVersionUID = 1L;
-    private static final String DOCK = "dock";
-    private static final String FULLSCREEN = "fullscreen";
-
-    private boolean isDocked = false;
-    private boolean isFullScreen = false;
-
-    private Header header;
-    private Button min;
-    private Button max;
-
-    private Div content;
-    private Footer footer;
-
+    
     public static ActionDialog forManagedAction(
             @NonNull final UiComponentFactoryVaa uiComponentFactory, 
             @NonNull final ManagedAction managedAction) {
@@ -71,100 +62,146 @@ public class ActionDialog extends Dialog {
         setModal(false);
         setResizable(true);
         
-        // Dialog theming
+        // Dialog Theme
+        
         getElement().getThemeList().add("action-dialog");
         setWidth("600px");
         setHeight("auto");
         
+        // Content
+        
+        val actionForm = ActionForm.forManagedAction(uiComponentFactory, managedAction);
+        val content = new Div(actionForm);
+        content.addClassName("dialog-content");
+
+        // Footer
+        
+        val footer = footer(managedAction); 
+        
         // Header
+        
+        val hidableComponents = Can.of(content, footer);
+        val header = header(managedAction, hidableComponents);
+        
+        // Add to Layout
+        
+        add(header, content, footer);
+    }
+
+    // -- HELPER
+    
+    private Component header(ManagedAction managedAction, Can<Component> hidableComponents) {
+        
+        val resizeHandler = DialogResizeHandler.of(this, hidableComponents);
+        
         val title = new H2(managedAction.getName());
         title.addClassName("dialog-title");
 
-        min = new Button(VaadinIcon.ANGLE_DOWN.create());
-        min.addClickListener(event -> minimise());
-
-        max = new Button(VaadinIcon.EXPAND_SQUARE.create());
-        max.addClickListener(event -> maximise());
-
+        val minButton = new Button(VaadinIcon.ANGLE_DOWN.create());
+        val maxButton = new Button(VaadinIcon.EXPAND_SQUARE.create());
         val closeButton = new Button(VaadinIcon.CLOSE_SMALL.create());
 
-        header = new Header(title, min, max, closeButton);
+        val header = new Header(title, minButton, maxButton, closeButton);
         header.getElement().getThemeList().add(Lumo.DARK);
-        add(header);
-
-        // Content
-        val actionForm = ActionForm.forManagedAction(uiComponentFactory, managedAction);
         
-        content = new Div(actionForm);
-        content.addClassName("dialog-content");
-        add(content);
-
-        // Footer
+        // Button Themes
+        Stream.of(minButton, maxButton, closeButton)
+        .forEach(button->
+            button.addThemeVariants(ButtonVariant.LUMO_CONTRAST, ButtonVariant.LUMO_TERTIARY));
+        
+        // Button Events
+        resizeHandler.bindMinimise(minButton);
+        resizeHandler.bindMaximise(maxButton);
+        closeButton.addClickListener(event -> close());
+        
+        return header;
+    }
+    
+    private Component footer(ManagedAction managedAction) {
+        
         val okButton = new Button("Ok");
         val cancelButton = new Button("Cancel");
-        footer = new Footer(okButton, cancelButton);
-        add(footer);
-
-        // Button Themes
+        val footer = new Footer(okButton, cancelButton);
         
+        // Button Themes
         okButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
         cancelButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
         
-        Stream.of(min, max, closeButton)
-        .forEach(button->
-            button.addThemeVariants(ButtonVariant.LUMO_CONTRAST, ButtonVariant.LUMO_TERTIARY));
-        
         // Button Events
-        
-        okButton.addClickListener(event -> close()); //TODO should invoke the action
+        okButton.addClickListener(event -> close()); //TODO should invoke the action and route to the result page
         cancelButton.addClickListener(event -> close());
-        closeButton.addClickListener(event -> close());
         
+        return footer;
     }
 
-    // -- HELPER
+    // -- RESIZING
     
-    private void minimise() {
-        if (isDocked) {
-            initialSize();
-        } else {
-            if (isFullScreen) {
-                initialSize();
-            }
-            min.setIcon(VaadinIcon.ANGLE_UP.create());
-            getElement().getThemeList().add(DOCK);
-            setWidth("320px");
-        }
-        isDocked = !isDocked;
-        isFullScreen = false;
-        content.setVisible(!isDocked);
-        footer.setVisible(!isDocked);
-    }
+    @RequiredArgsConstructor(staticName = "of")
+    private static class DialogResizeHandler {
+    
+        private static final String DOCK = "dock";
+        private static final String FULLSCREEN = "fullscreen";
+        
+        private boolean isDocked = false;
+        private boolean isFullScreen = false;
+        
+        private final Dialog dialog;
+        private final Can<Component> hidableComponents;
+        
+        private Button minButton;
+        private Button maxButton;
 
-    private void initialSize() {
-        min.setIcon(VaadinIcon.ANGLE_DOWN.create());
-        getElement().getThemeList().remove(DOCK);
-        max.setIcon(VaadinIcon.EXPAND_SQUARE.create());
-        getElement().getThemeList().remove(FULLSCREEN);
-        setHeight("auto");
-        setWidth("600px");
-    }
+        public void bindMinimise(Button minButton) {
+            this.minButton = minButton;
+            minButton.addClickListener(event -> minimise());
+        }
+        
+        public void bindMaximise(Button maxButton) {
+            this.maxButton = maxButton;
+            maxButton.addClickListener(event -> maximise());
+        }
+        
+        private void initialSize() {
+            minButton.setIcon(VaadinIcon.ANGLE_DOWN.create());
+            dialog.getElement().getThemeList().remove(DOCK);
+            maxButton.setIcon(VaadinIcon.EXPAND_SQUARE.create());
+            dialog.getElement().getThemeList().remove(FULLSCREEN);
+            dialog.setWidth("600px");
+            dialog.setHeight("auto");
+        }
 
-    private void maximise() {
-        if (isFullScreen) {
-            initialSize();
-        } else {
+        private void minimise() {
             if (isDocked) {
                 initialSize();
+            } else {
+                if (isFullScreen) {
+                    initialSize();
+                }
+                minButton.setIcon(VaadinIcon.ANGLE_UP.create());
+                dialog.getElement().getThemeList().add(DOCK);
+                dialog.setWidth("320px");
             }
-            max.setIcon(VaadinIcon.COMPRESS_SQUARE.create());
-            getElement().getThemeList().add(FULLSCREEN);
-            setSizeFull();
-            content.setVisible(true);
-            footer.setVisible(true);
+            isDocked = !isDocked;
+            isFullScreen = false;
+            hidableComponents.forEach(comp->comp.setVisible(!isDocked));
         }
-        isFullScreen = !isFullScreen;
-        isDocked = false;
+    
+        private void maximise() {
+            if (isFullScreen) {
+                initialSize();
+            } else {
+                if (isDocked) {
+                    initialSize();
+                }
+                maxButton.setIcon(VaadinIcon.COMPRESS_SQUARE.create());
+                dialog.getElement().getThemeList().add(FULLSCREEN);
+                dialog.setSizeFull();
+                hidableComponents.forEach(comp->comp.setVisible(true));
+            }
+            isFullScreen = !isFullScreen;
+            isDocked = false;
+        }
+        
     }
 
 }
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java
index 23c6606..6964d1c 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/pages/main/MainView_createHeader.java
@@ -18,7 +18,6 @@
  */
 package org.apache.isis.incubator.viewer.vaadin.ui.pages.main;
 
-import java.util.Optional;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 
@@ -40,7 +39,6 @@ import org.apache.isis.incubator.viewer.vaadin.model.menu.MenuItemVaa;
 import org.apache.isis.viewer.common.model.branding.BrandingUiModel;
 import org.apache.isis.viewer.common.model.header.HeaderUiModel;
 import org.apache.isis.viewer.common.model.menu.MenuUiModel;
-import org.apache.isis.viewer.common.model.userprofile.UserProfileUiModelProvider;
 
 import lombok.val;
 
@@ -76,13 +74,10 @@ final class MainView_createHeader {
         // menu section handler, that creates and adds sub-menus to their parent top level menu   
         final BiConsumer<MenuBar, MenuItemVaa> menuSectionBuilder = (menuBar, menuSectionUiModel) -> {
             val menuItem = menuSectionUiModel.isTertiaryRoot() 
-                    ? menuBar.addItem(Decorators.getUser().decorate(
-                            new Label(),
-                            Optional.ofNullable(
-                                commonContext.lookupServiceElseFail(UserProfileUiModelProvider.class)
-                                .getUserProfile())
-                            ))
-                    : menuBar.addItem(menuSectionUiModel.getName());
+                    ? menuBar.addItem(Decorators.getUser()
+                            .decorateWithAvatar(new Label(), commonContext))
+                    : menuBar.addItem(Decorators.getMenu()
+                            .decorateTopLevel(new Label(menuSectionUiModel.getName())));
             val subMenu = menuItem.getSubMenu();
             menuSectionUiModel.getSubMenuItems().forEach(menuItemModel -> {
                 val menuActionModel = (ActionVaa)menuItemModel.getMenuActionUiModel();