From 58c5c3336d7856e1d3a416df284ac8abb70507fb Mon Sep 17 00:00:00 2001 From: jensp Date: Thu, 22 Mar 2018 14:19:49 +0000 Subject: [PATCH] CCM NG: Page Model component FlexBox git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5354 8810af33-2d31-482b-a856-94f89814c4df --- .../libreccm/pagemodel/layout/FlexBox.java | 172 ++++++++++++++++++ .../pagemodel/layout/FlexBoxRepository.java | 67 +++++++ .../pagemodel/layout/FlexDirection.java | 30 +++ .../libreccm/pagemodel/layout/FlexLayout.java | 142 +++++++++++++++ .../pagemodel/layout/FlexLayoutManager.java | 136 ++++++++++++++ 5 files changed, 547 insertions(+) create mode 100644 ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java create mode 100644 ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBoxRepository.java create mode 100644 ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexDirection.java create mode 100644 ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java create mode 100644 ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutManager.java diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java new file mode 100644 index 000000000..de0c17205 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2018 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.pagemodel.layout; + +import org.libreccm.core.CoreConstants; +import org.libreccm.pagemodel.ComponentModel; + +import java.io.Serializable; +import java.util.Objects; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +/** + * A box in a {@link FlexLayout}. + * + * @author Jens Pelzetter + */ +@Entity +@Table(name = "FLEX_LAYOUT_BOXES", schema = CoreConstants.DB_SCHEMA) +@NamedQueries( +@NamedQuery(name = "FlexBox.findBoxesForLayout", + query = "SELECT b FROM FlexBox b WHERE b.layout = :layout")) +public class FlexBox implements Serializable { + + private static final long serialVersionUID = -6085798536072937899L; + + @Id + @Column(name = "BOX_ID") + @GeneratedValue(strategy = GenerationType.AUTO) + private long boxId; + + @ManyToOne + private FlexLayout layout; + + @Column(name = "BOX_ORDER") + private int order; + + @Column(name = "BOX_SIZE") + private int size; + + @OneToOne + @JoinColumn(name = "COMPONENT_ID") + private ComponentModel component; + + public long getBoxId() { + return boxId; + } + + public void setBoxId(final long boxId) { + this.boxId = boxId; + } + + public FlexLayout getLayout() { + return layout; + } + + protected void setLayout(final FlexLayout layout) { + this.layout = layout; + } + + public int getOrder() { + return order; + } + + public void setOrder(final int order) { + this.order = order; + } + + public int getSize() { + return size; + } + + public void setSize(final int size) { + this.size = size; + } + + public ComponentModel getComponent() { + return component; + } + + public void setComponent(final ComponentModel component) { + this.component = component; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 89 * hash + (int) (boxId ^ (boxId >>> 32)); + hash = 89 * hash + order; + hash = 89 * hash + size; + hash = 89 * hash + Objects.hashCode(component); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof FlexBox)) { + return false; + } + final FlexBox other = (FlexBox) obj; + if (!other.canEqual(this)) { + return false; + } + if (boxId != other.getBoxId()) { + return false; + } + if (order != other.getOrder()) { + return false; + } + if (size != other.getSize()) { + return false; + } + return Objects.equals(component, other.getComponent()); + } + + public boolean canEqual(final Object obj) { + return obj instanceof FlexBox; + } + + @Override + public final String toString() { + return toString(""); + } + + public String toString(final String data) { + return String.format("%s{ " + + "columnId = %d, " + + "order = %d" + + "size = %d, " + + "component = %s%s" + + " }", + super.toString(), + boxId, + order, + size, + Objects.toString(component), + data); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBoxRepository.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBoxRepository.java new file mode 100644 index 000000000..f417572b4 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBoxRepository.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2018 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.pagemodel.layout; + +import org.libreccm.core.AbstractEntityRepository; + +import java.util.List; + +import javax.enterprise.context.RequestScoped; +import javax.persistence.TypedQuery; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class FlexBoxRepository extends AbstractEntityRepository { + + private static final long serialVersionUID = -5321887349687319620L; + + @Override + public Class getEntityClass() { + return FlexBox.class; + } + + @Override + public String getIdAttributeName() { + return "boxId"; + } + + @Override + public Long getIdOfEntity(final FlexBox entity) { + return entity.getBoxId(); + } + + @Override + public boolean isNew(final FlexBox entity) { + return entity.getBoxId() == 0; + } + + @Transactional(Transactional.TxType.REQUIRED) + public List getBoxesForLayout(final FlexLayout layout) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("FlexBox.findBoxesForLayout", FlexBox.class); + query.setParameter("layout", layout); + + return query.getResultList(); + } +} diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexDirection.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexDirection.java new file mode 100644 index 000000000..fc972b347 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexDirection.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2018 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.pagemodel.layout; + +/** + * + * @author Jens Pelzetter + */ +public enum FlexDirection { + + HORIZONTAL, + VERTICAL + +} diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java new file mode 100644 index 000000000..5eecb3e56 --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2018 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.pagemodel.layout; + +import org.libreccm.core.CoreConstants; +import org.libreccm.pagemodel.ComponentModel; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; +import javax.persistence.Table; + +/** + * A layout component container which provides the information for laying + * out other components using the Flex Layout properties in CSS. + * + * The component contains a collection of {@code FlexBox} objects which contain + * another component. A theme should use the Flex Layout properties in CSS to + * create the real layout. + * + * @author Jens Pelzetter + */ +@Entity +@Table(name = "HORIZONTAL_LAYOUT_COMPONENTS", schema = CoreConstants.DB_SCHEMA) +public class FlexLayout extends ComponentModel { + + private static final long serialVersionUID = 1977244351125227610L; + + /** + * The direction in which the components are shown. This is really only a + * hint for the theme, usually for the layout on wide screens. On small + * screens is is most likely that the boxes are stacked vertically. + */ + @Column(name = "DIRECTION") + @Enumerated(EnumType.STRING) + private FlexDirection direction; + + /** + * The boxes containing the components. + */ + @OneToMany(mappedBy = "layout") + @OrderBy(value = "order") + @JoinColumn(name = "LAYOUT_ID") + private List boxes; + + public FlexLayout() { + boxes = new ArrayList<>(); + } + + public FlexDirection getDirection() { + return direction; + } + + public void setDirection(final FlexDirection direction) { + this.direction = direction; + } + + public List getBoxes() { + return Collections.unmodifiableList(boxes); + } + + protected void setBoxes(final List boxes) { + this.boxes = new ArrayList<>(boxes); + } + + protected void addBox(final FlexBox box) { + boxes.add(box); + } + + protected void removeBox(final FlexBox box) { + boxes.remove(box); + } + + @Override + public int hashCode() { + int hash = 3; + hash = 67 * hash + Objects.hashCode(direction); + hash = 67 * hash + Objects.hashCode(boxes); + return hash; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof FlexLayout)) { + return false; + } + final FlexLayout other = (FlexLayout) obj; + if (!other.canEqual(this)) { + return false; + } + if (direction != other.getDirection()) { + return false; + } + return Objects.equals(boxes, other.getBoxes()); + } + + @Override + public boolean canEqual(final Object obj) { + return obj instanceof FlexLayout; + } + + @Override + public String toString(final String data) { + return super.toString(String.format(", " + + "direction = %s, " + + "layoutCells = %s", + direction, + Objects.toString(boxes))); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutManager.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutManager.java new file mode 100644 index 000000000..e51857c9f --- /dev/null +++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutManager.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2018 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.libreccm.pagemodel.layout; + +import org.libreccm.pagemodel.ComponentModelRepository; + +import java.io.Serializable; +import java.util.Objects; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class FlexLayoutManager implements Serializable { + + private static final long serialVersionUID = 6697380241367469301L; + + @Inject + private ComponentModelRepository componentModelRepo; + + @Inject + private FlexBoxRepository flexBoxRepo; + + public void addBoxToLayout(final FlexBox box, final FlexLayout layout) { + + Objects.requireNonNull(box); + Objects.requireNonNull(layout); + + layout.addBox(box); + box.setLayout(layout); + + componentModelRepo.save(layout); + flexBoxRepo.save(box); + } + + public void removeBoxFromLayout(final FlexBox box, + final FlexLayout layout) { + + Objects.requireNonNull(box); + Objects.requireNonNull(layout); + + layout.removeBox(box); + box.setLayout(null); + + componentModelRepo.save(layout); + flexBoxRepo.delete(box); + } + + public void decreaseBoxOrder(final FlexLayout layout, + final FlexBox box) { + + Objects.requireNonNull(box); + Objects.requireNonNull(layout); + + final int currentPosition = layout.getBoxes().indexOf(box); + + if (currentPosition < 0) { + throw new IllegalArgumentException(String + .format("The FlexBox with ID %d is not part " + + "of the FlexLayout \"%s\".", + box.getBoxId(), + layout.getUuid())); + } + + final FlexBox prevBox; + if ((currentPosition - 1) > 0) { + prevBox = layout.getBoxes().get(currentPosition -1); + } else { + // No previous box, return silently. + return; + } + + final int prevPosition = prevBox.getOrder(); + + prevBox.setOrder(currentPosition); + box.setOrder(prevPosition); + + flexBoxRepo.save(box); + flexBoxRepo.save(prevBox); + } + + public void increaseBoxOrder(final FlexLayout layout, + final FlexBox box) { + + Objects.requireNonNull(box); + Objects.requireNonNull(layout); + + final int currentPosition = layout.getBoxes().indexOf(box); + + if (currentPosition < 0) { + throw new IllegalArgumentException(String + .format("The FlexBox with ID %d is not part " + + "of the FlexLayout \"%s\".", + box.getBoxId(), + layout.getUuid())); + } + + final FlexBox nextBox; + if ((currentPosition + 1) < layout.getBoxes().size()) { + nextBox = layout.getBoxes().get(currentPosition + 1); + } else { + // No previous box, return silently. + return; + } + + final int nextPosition = nextBox.getOrder(); + + nextBox.setOrder(currentPosition); + box.setOrder(nextPosition); + + flexBoxRepo.save(box); + flexBoxRepo.save(nextBox); + + } + +}