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/04/21 14:04:19 UTC
[isis] 03/03: ISIS-2340: getting our hands dirty with responsive
layout
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
commit d1ecd1e905da02b3b61a791f451caa761b0d5393
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Apr 21 16:04:03 2020 +0200
ISIS-2340: getting our hands dirty with responsive layout
---
.../isis/applib/services/grid/GridService.java | 1 -
.../ui/components/object/ObjectFormView.java | 164 ++++++++++++++++++---
.../ui/pages/main/MainView_createHeader.java | 4 +-
.../binding/interaction/ObjectInteractor.java | 17 ++-
.../common/model/gridlayout/UiGridLayout.java | 145 ++++++++++++++++++
5 files changed, 304 insertions(+), 27 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/grid/GridService.java b/api/applib/src/main/java/org/apache/isis/applib/services/grid/GridService.java
index 13847cb..eced5e0 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/grid/GridService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/grid/GridService.java
@@ -22,7 +22,6 @@ import org.apache.isis.applib.annotation.ActionLayout;
import org.apache.isis.applib.annotation.CollectionLayout;
import org.apache.isis.applib.annotation.DomainObjectLayout;
import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.annotation.PropertyLayout;
import org.apache.isis.applib.layout.grid.Grid;
diff --git a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/object/ObjectFormView.java b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/object/ObjectFormView.java
index f561d49..f0f1572 100644
--- a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/object/ObjectFormView.java
+++ b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/object/ObjectFormView.java
@@ -22,19 +22,35 @@ import java.util.Collection;
import java.util.Optional;
import com.vaadin.flow.component.Component;
+import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.formlayout.FormLayout;
+import com.vaadin.flow.component.formlayout.FormLayout.ResponsiveStep;
import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.H3;
-import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
+import com.vaadin.flow.component.html.H4;
+import com.vaadin.flow.component.orderedlayout.FlexLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
+import com.vaadin.flow.component.tabs.Tab;
+import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.component.textfield.TextField;
+import org.apache.isis.applib.layout.component.ActionLayoutData;
+import org.apache.isis.applib.layout.component.FieldSet;
+import org.apache.isis.applib.layout.component.PropertyLayoutData;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3ClearFix;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Col;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Row;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Tab;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3TabGroup;
+import org.apache.isis.core.commons.internal.primitives._Ints;
+import org.apache.isis.core.commons.internal.primitives._Ints.Bound;
import org.apache.isis.core.metamodel.spec.ManagedObject;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.incubator.viewer.vaadin.ui.components.UiComponentFactoryVaa;
import org.apache.isis.incubator.viewer.vaadin.ui.components.collection.TableView;
import org.apache.isis.viewer.common.model.binding.interaction.ObjectInteractor;
+import org.apache.isis.viewer.common.model.gridlayout.UiGridLayout;
import lombok.NonNull;
import lombok.val;
@@ -53,15 +69,114 @@ public class ObjectFormView extends VerticalLayout {
@NonNull final UiComponentFactoryVaa uiComponentFactory,
@NonNull final ManagedObject managedObject) {
+
val objectInteractor = ObjectInteractor.bind(managedObject);
add(new H1(objectInteractor.getTitle()));
+
+ val uiGridLayout = UiGridLayout.bind(managedObject);
+
+ // force new row
+ //formLayout.getElement().appendChild(ElementFactory.createBr());
+
+ val range1_12 = _Ints.Range.of(Bound.inclusive(1), Bound.inclusive(12));
+
+ val gridVisistor = new UiGridLayout.Visitor<HasComponents>(this) {
+
+ @Override
+ protected HasComponents newRow(HasComponents container, BS3Row bs3Row) {
+ val uiRow = new FlexLayout();
+ container.add(uiRow);
+ //uiRow.setWidthFull();
+ uiRow.setWrapMode(FlexLayout.WrapMode.WRAP); // allow line breaking
+ return uiRow;
+ }
+
+ @Override
+ protected HasComponents newCol(HasComponents container, BS3Col bs3col) {
+
+ val uiCol = new VerticalLayout();
+ container.add(uiCol);
+
+ final int span = range1_12.bounded(bs3col.getSpan());
+ ((FlexLayout)container).setFlexGrow(span, uiCol);
+ val widthEm = String.format("%.2fem", span * 100./16.); // 1em ~ 16px
+ uiCol.setWidth(null); // clear preset width style
+ uiCol.setMinWidth(widthEm);
+
+ return uiCol;
+ }
+
+ @Override
+ protected HasComponents newActionPanel(HasComponents container) {
+ val uiActionPanel = new FlexLayout();
+ container.add(uiActionPanel);
+
+ uiActionPanel.setWrapMode(FlexLayout.WrapMode.WRAP); // allow line breaking
+
+ return uiActionPanel;
+ }
+
+ @Override
+ protected HasComponents newTabGroup(HasComponents container, BS3TabGroup tabGroupData) {
+ val uiTabGroup = new Tabs();
+ container.add(uiTabGroup);
+ uiTabGroup.setOrientation(Tabs.Orientation.HORIZONTAL);
+ return uiTabGroup;
+ }
+
+ @Override
+ protected HasComponents newTab(HasComponents container, BS3Tab tabData) {
+ val uiTab = new Tab(tabData.getName());
+ container.add(uiTab);
+ return uiTab;
+ }
+
+ @Override
+ protected HasComponents newFieldSet(HasComponents container, FieldSet fieldSetData) {
+
+ container.add(new H4(fieldSetData.getName()));
+
+ val uiFieldSet = new FormLayout();
+ container.add(uiFieldSet);
+ //uiFieldSet.setWidthFull();
+
+ uiFieldSet.setResponsiveSteps(
+ new ResponsiveStep("0", 1));
+
+ return uiFieldSet;
+ }
- val actionsLayout = new HorizontalLayout();
- add(actionsLayout);
+
+ @Override
+ protected void onClearfix(HasComponents container, BS3ClearFix clearFixData) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ protected void onAction(HasComponents container, ActionLayoutData actionData) {
+ objectInteractor.lookupAction(actionData.getId())
+ .ifPresent(action->{
+ val uiAction = new Button(action.getName());
+ container.add(uiAction);
+ });
+ }
+
+ @Override
+ protected void onProperty(HasComponents container, PropertyLayoutData propertyData) {
+ objectInteractor.lookupProperty(propertyData.getId())
+ .ifPresent(property->{
+ val uiPropertyCreateRequest = objectInteractor.newUiComponentCreateRequest(property);
+ val uiProperty = uiComponentFactory.componentFor(uiPropertyCreateRequest);
+ container.add(uiProperty);
+ });
+ }
+
+ };
+
+
- val formLayout = new FormLayout();
- add(formLayout);
+ uiGridLayout.visit(gridVisistor);
val tablesLayout = new VerticalLayout();
add(tablesLayout);
@@ -70,21 +185,32 @@ public class ObjectFormView extends VerticalLayout {
// -- populate actions
- objectInteractor
- .streamVisisbleActions()
- .forEach(action -> {
- actionsLayout.add(new Button(action.getName()));
- });
-
- // -- populate properties
+// objectInteractor
+// .streamVisisbleActions()
+// .forEach(action -> {
+//
+// val button = new Button(action.getName());
+// actionsLayout.add(button);
+//
+// Dialog dialog = new Dialog();
+// dialog.add(new Label("Under Construction ... Close me with the esc-key or an outside click"));
+//
+// dialog.setWidth("400px");
+// dialog.setHeight("150px");
+//
+// button.addClickListener(e->{
+// dialog.open();
+// });
+//
+////similar code in menu item ...
+//// val actionModel = (ActionVaa)menuItemModel.getMenuActionUiModel();
+////
+//// subMenu.addItem(
+//// (Component)menuActionModel.getUiComponent(),
+//// e->subMenuEventHandler.accept(menuActionModel));
+//
+// });
- objectInteractor
- .streamVisisbleProperties()
- .forEach(property -> {
- val uiComponentCreateRequest = objectInteractor.newUiComponentCreateRequest(property);
- val uiComponent = uiComponentFactory.componentFor(uiComponentCreateRequest);
- formLayout.add(uiComponent);
- });
// -- populate collections
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 71c12e0..23c6606 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
@@ -132,8 +132,8 @@ final class MainView_createHeader {
val logo = new Image(
webAppContextPath.prependContextPathIfLocal(brandingLogo.get()),
"brandingLogo");
- logo.setWidth("48px");
- logo.setHeight("48px");
+ logo.setWidth("48px"); //TODO make this part of the UI model
+ logo.setHeight("48px"); //TODO make this part of the UI model
return logo;
}
return new Text(brandingName.orElse("App"));
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java
index bcbed4c..853f5ee 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/binding/interaction/ObjectInteractor.java
@@ -18,6 +18,7 @@
*/
package org.apache.isis.viewer.common.model.binding.interaction;
+import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
@@ -98,11 +99,17 @@ public class ObjectInteractor {
}
-// public UiComponentFactory.Request newUiComponentCreateRequest(
-// final ObjectAction action) {
-// // TODO Auto-generated method stub
-// return null;
-// }
+ public Optional<OneToOneAssociation> lookupProperty(String id) {
+ return streamVisisbleProperties()
+ .filter(property->Objects.equals(id, property.getId()))
+ .findFirst();
+ }
+
+ public Optional<ObjectAction> lookupAction(String id) {
+ return streamVisisbleActions()
+ .filter(action->Objects.equals(id, action.getId()))
+ .findFirst();
+ }
}
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/gridlayout/UiGridLayout.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/gridlayout/UiGridLayout.java
new file mode 100644
index 0000000..3ee90cf
--- /dev/null
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/gridlayout/UiGridLayout.java
@@ -0,0 +1,145 @@
+/*
+ * 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.isis.viewer.common.model.gridlayout;
+
+import java.util.Optional;
+
+import org.apache.isis.applib.layout.component.ActionLayoutData;
+import org.apache.isis.applib.layout.component.FieldSet;
+import org.apache.isis.applib.layout.component.PropertyLayoutData;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3ClearFix;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Col;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Grid;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Row;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3Tab;
+import org.apache.isis.applib.layout.grid.bootstrap3.BS3TabGroup;
+import org.apache.isis.core.commons.internal.exceptions._Exceptions;
+import org.apache.isis.core.metamodel.facets.object.grid.GridFacet;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+@RequiredArgsConstructor(staticName = "bind")
+public class UiGridLayout {
+
+ @RequiredArgsConstructor
+ public static abstract class Visitor<T> {
+ private final T rootContainer;
+ protected abstract T newActionPanel(T container);
+ protected abstract T newRow(T container, BS3Row rowData);
+ protected abstract T newCol(T container, BS3Col colData);
+ protected abstract T newTabGroup(T container, BS3TabGroup tabGroupData);
+ protected abstract T newTab(T container, BS3Tab tabData);
+ protected abstract T newFieldSet(T container, FieldSet fieldSetData);
+ protected abstract void onClearfix(T container, BS3ClearFix clearFixData);
+ protected abstract void onAction(T container, ActionLayoutData actionData);
+ protected abstract void onProperty(T container, PropertyLayoutData propertyData);
+ }
+
+ @NonNull private final ManagedObject managedObject;
+ private Optional<BS3Grid> gridData;
+
+ public <T> void visit(Visitor<T> visitor) {
+
+ if(gridData==null) {
+ gridData = Optional.ofNullable(
+ managedObject.getSpecification().getFacet(GridFacet.class))
+ .map(gridFacet->gridFacet.getGrid(managedObject))
+ .filter(grid->grid instanceof BS3Grid)
+ .map(BS3Grid.class::cast);
+ }
+
+ // recursively visit the grid
+ gridData
+ .ifPresent(bs3Grid->{
+ for(val bs3Row: bs3Grid.getRows()) {
+ visitRow(bs3Row, visitor.rootContainer, visitor);
+ }
+ });
+
+ }
+
+ private <T> void visitRow(BS3Row bs3Row, T container, Visitor<T> visitor) {
+
+ val uiRow = visitor.newRow(container, bs3Row);
+
+ for(val bs3RowContent: bs3Row.getCols()) {
+ if(bs3RowContent instanceof BS3Col) {
+
+ visitCol((BS3Col) bs3RowContent, uiRow, visitor);
+
+ } else if (bs3RowContent instanceof BS3ClearFix) {
+ visitor.onClearfix(uiRow, (BS3ClearFix) bs3RowContent);
+ } else {
+ throw new IllegalStateException("Unrecognized implementation of BS3RowContent");
+ }
+ }
+ }
+
+ private <T> void visitCol(BS3Col bS3Col, T container, Visitor<T> visitor) {
+ val uiCol = visitor.newCol(container, bS3Col);
+
+ if(bS3Col.getActions().size()>0) {
+ val uiActionPanel = visitor.newActionPanel(uiCol);
+ for(val action : bS3Col.getActions()) {
+ visitor.onAction(uiActionPanel, action);
+ }
+ }
+
+ for(val fieldSet : bS3Col.getFieldSets()) {
+ visitFieldSet(fieldSet, uiCol, visitor);
+ }
+
+ for(val tabGroup : bS3Col.getTabGroups()) {
+ visitTabGroup(tabGroup, uiCol, visitor);
+ }
+
+ // columns having rows seems not permitted by XML schema
+ for(val bs3Row: bS3Col.getRows()) {
+ throw _Exceptions.unsupportedOperation();
+ //visitRow(bs3Row, uiCol, visitor);
+ }
+
+ }
+
+ private <T> void visitTabGroup(BS3TabGroup bS3ColTabGroup, T container, Visitor<T> visitor) {
+ val uiTabGroup = visitor.newTabGroup(container, bS3ColTabGroup);
+ for(val bs3Tab: bS3ColTabGroup.getTabs()) {
+ visitTab(bs3Tab, uiTabGroup, visitor);
+ }
+ }
+
+ private <T> void visitTab(BS3Tab bS3Tab, T container, Visitor<T> visitor) {
+ val uiTab = visitor.newTab(container, bS3Tab);
+ for(val bs3Row: bS3Tab.getRows()) {
+ visitRow(bs3Row, uiTab, visitor);
+ }
+ }
+
+ private <T> void visitFieldSet(FieldSet cptFieldSet, T container, Visitor<T> visitor) {
+ val uiFieldSet = visitor.newFieldSet(container, cptFieldSet);
+ for(val propertyData: cptFieldSet.getProperties()) {
+ visitor.onProperty(uiFieldSet, propertyData);
+ }
+ }
+
+
+}